From 1e8e313db0b2fda7f3a6338c7129adffdbdfb72a Mon Sep 17 00:00:00 2001 From: "Antonio S. Musumeci" Date: Sat, 18 Apr 2026 00:58:06 -0400 Subject: [PATCH] fuse_readdir: atomic initialized flag; bound error string; check msgbuf allocation - ReadDir::_initialized is set by the first thread through the lazy-init path and read by every subsequent caller; make it std::atomic so the read/write pair has a happens-before relationship. - The 'no valid mergerfs branch found' error directory entry used strcpy into a fixed-size dirent buffer. The message happens to fit today but the buffer is only NAME_MAX wide; switch to a length-bounded strncpy driven by the constexpr string size. - The getdents implementations for seq/cor/cosr allocated a msgbuf without checking for allocation failure and then dereferenced it. Return -ENOMEM when the allocation fails. --- src/fuse_readdir.cpp | 7 +++++-- src/fuse_readdir.hpp | 3 ++- src/fuse_readdir_cor_getdents.icpp | 3 +++ src/fuse_readdir_cosr_getdents.icpp | 2 ++ src/fuse_readdir_seq_getdents.icpp | 2 ++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/fuse_readdir.cpp b/src/fuse_readdir.cpp index 0c315fa0..d506d3d8 100644 --- a/src/fuse_readdir.cpp +++ b/src/fuse_readdir.cpp @@ -90,15 +90,18 @@ _handle_ENOENT(const fuse_file_info_t *ffi_, if(!di->fusepath.empty()) return -ENOENT; + constexpr const char msg[] = + "error: no valid mergerfs branch found, check config"; + de = {}; de.d_ino = 0; de.d_off = 0; de.d_type = DT_UNKNOWN; - strcpy(de.d_name,"error: no valid mergerfs branch found, check config"); + strncpy(de.d_name,msg,(sizeof(msg) - 1)); de.d_reclen = sizeof(de); - fuse_dirents_add(buf_,&de,::strlen(de.d_name)); + fuse_dirents_add(buf_,&de,(sizeof(msg) - 1)); return 0; } diff --git a/src/fuse_readdir.hpp b/src/fuse_readdir.hpp index 8abf8820..afcff6da 100644 --- a/src/fuse_readdir.hpp +++ b/src/fuse_readdir.hpp @@ -22,6 +22,7 @@ #include "tofrom_string.hpp" #include "fuse_readdir_base.hpp" +#include #include #include @@ -58,7 +59,7 @@ namespace FUSE void initialize(); private: - bool _initialized = false; + std::atomic _initialized = false; std::shared_ptr _str; std::shared_ptr _impl; }; diff --git a/src/fuse_readdir_cor_getdents.icpp b/src/fuse_readdir_cor_getdents.icpp index 03fb7941..3df46a5b 100644 --- a/src/fuse_readdir_cor_getdents.icpp +++ b/src/fuse_readdir_cor_getdents.icpp @@ -53,6 +53,9 @@ _readdir(const fs::path &branch_path_, DEFER{ fs::close(fd); }; buf = msgbuf_alloc(); + if(not buf) + return -ENOMEM; + DEFER{ msgbuf_free(buf); }; fs::inode::ReaddirCalc inodecalc(branch_path_,rel_dirpath_); diff --git a/src/fuse_readdir_cosr_getdents.icpp b/src/fuse_readdir_cosr_getdents.icpp index 93b0cc18..52a48adb 100644 --- a/src/fuse_readdir_cosr_getdents.icpp +++ b/src/fuse_readdir_cosr_getdents.icpp @@ -87,6 +87,8 @@ _readdir(std::vector> &dh_futures_, fuse_msgbuf_t *buf; buf = msgbuf_alloc(); + if(not buf) + return -ENOMEM; DEFER { msgbuf_free(buf); }; for(auto &dh_future : dh_futures_) diff --git a/src/fuse_readdir_seq_getdents.icpp b/src/fuse_readdir_seq_getdents.icpp index e190eccf..da99bb56 100644 --- a/src/fuse_readdir_seq_getdents.icpp +++ b/src/fuse_readdir_seq_getdents.icpp @@ -45,6 +45,8 @@ _readdir(const Branches::Ptr &branches_, fuse_dirents_reset(dirents_); buf = msgbuf_alloc(); + if(not buf) + return -ENOMEM; DEFER { msgbuf_free(buf); }; for(const auto &branch : *branches_)