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<bool> 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.
This commit is contained in:
Antonio S. Musumeci 2026-04-18 00:58:06 -04:00 • committed by trapexit
parent f5d9a60b9d
commit cf38a37176
5 changed files with 14 additions and 3 deletions

View file

@ -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;
}

View file

@ -22,6 +22,7 @@
#include "tofrom_string.hpp"
#include "fuse_readdir_base.hpp"
#include <atomic>
#include <memory>
#include <mutex>
@ -58,7 +59,7 @@ namespace FUSE
void initialize();
private:
bool _initialized = false;
std::atomic<bool> _initialized = false;
std::shared_ptr<std::string> _str;
std::shared_ptr<FUSE::ReadDirBase> _impl;
};

View file

@ -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_);

View file

@ -87,6 +87,8 @@ _readdir(std::vector<std::future<DirRV>> &dh_futures_,
fuse_msgbuf_t *buf;
buf = msgbuf_alloc();
if(not buf)
return -ENOMEM;
DEFER { msgbuf_free(buf); };
for(auto &dh_future : dh_futures_)

View file

@ -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_)