From 0f24bb29ac5fab7651de8bbaefe8d6e7dc4f0034 Mon Sep 17 00:00:00 2001 From: trapexit Date: Mon, 6 Oct 2025 15:46:58 -0400 Subject: [PATCH] Make allow-idmap optional (default: false) (#1541) This is just to correct default behavior for now. More investigation is necessary to properly support idmapping. --- libfuse/lib/fuse_lowlevel.cpp | 12 ++++++++++++ src/config.cpp | 5 ++++- src/config.hpp | 1 + src/fuse_init.cpp | 2 +- src/gidcache.cpp | 5 ++++- src/ugid_linux.hpp | 6 +++++- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libfuse/lib/fuse_lowlevel.cpp b/libfuse/lib/fuse_lowlevel.cpp index a7a8fdca..4319e642 100644 --- a/libfuse/lib/fuse_lowlevel.cpp +++ b/libfuse/lib/fuse_lowlevel.cpp @@ -1930,6 +1930,15 @@ fuse_send_enomem(struct fuse_ll *f_, fuse_send_errno(f_,ch_,ENOMEM,unique_id_); } +static +void +fuse_send_einval(struct fuse_ll *f_, + struct fuse_chan *ch_, + const uint64_t unique_id_) +{ + fuse_send_errno(f_,ch_,EINVAL,unique_id_); +} + static int fuse_ll_buf_receive_read(struct fuse_session *se_, @@ -1961,6 +1970,9 @@ fuse_ll_buf_process_read(struct fuse_session *se_, in = (struct fuse_in_header*)msgbuf_->mem; + if((in->uid == FUSE_INVALID_UIDGID) || (in->gid == FUSE_INVALID_UIDGID)) + return fuse_send_einval(se_->f,se_->ch,in->unique); + req = fuse_ll_alloc_req(se_->f); if(req == NULL) return fuse_send_enomem(se_->f,se_->ch,in->unique); diff --git a/src/config.cpp b/src/config.cpp index 67b68fe9..3d904ee0 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -53,6 +53,7 @@ namespace l bool readonly(const std::string &s_) { + IFERT("allow-idmap"); IFERT("async_read"); IFERT("branches-mount-timeout"); IFERT("branches-mount-timeout-fail"); @@ -81,7 +82,8 @@ namespace l } Config::Config() - : async_read(true), + : allow_idmap(false), + async_read(true), auto_cache(false), minfreespace(MINFREESPACE_DEFAULT), branches(minfreespace), @@ -140,6 +142,7 @@ Config::Config() xattr(XAttr::ENUM::PASSTHROUGH), _initialized(false) { + _map["allow-idmap"] = &allow_idmap; _map["async_read"] = &async_read; _map["auto_cache"] = &auto_cache; _map["branches"] = &branches; diff --git a/src/config.hpp b/src/config.hpp index ceffd157..8f3313d9 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -83,6 +83,7 @@ public: Config& operator=(const Config&); public: + ConfigBOOL allow_idmap; ConfigBOOL async_read; ConfigBOOL auto_cache; ConfigUINT64 minfreespace; diff --git a/src/fuse_init.cpp b/src/fuse_init.cpp index d99d95ea..c3735365 100644 --- a/src/fuse_init.cpp +++ b/src/fuse_init.cpp @@ -206,7 +206,7 @@ FUSE::init(fuse_conn_info *conn_) ::_want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&cfg.posix_acl); ::_want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&cfg.readdirplus); ::_want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&cfg.writeback_cache); - ::_want_if_capable(conn_,FUSE_CAP_ALLOW_IDMAP); + ::_want_if_capable(conn_,FUSE_CAP_ALLOW_IDMAP,&cfg.allow_idmap); // ::_want_if_capable(conn_,FUSE_CAP_READDIR_PLUS_AUTO); ::_want_if_capable_max_pages(conn_,cfg); conn_->want &= ~FUSE_CAP_POSIX_LOCKS; diff --git a/src/gidcache.cpp b/src/gidcache.cpp index 4bd0d1da..d84dff21 100644 --- a/src/gidcache.cpp +++ b/src/gidcache.cpp @@ -53,6 +53,9 @@ inline int _setgroups(const std::vector gids_) { + if(gids_.empty()) + return 0; + #if defined __linux__ and UGID_USE_RWLOCK == 0 # if defined SYS_setgroups32 return ::syscall(SYS_setgroups32,gids_.size(),gids_.data()); @@ -93,7 +96,7 @@ _getgroups(const uid_t uid_, error: gids_.clear(); - gids_.push_back(gid_); + //gids_.push_back(gid_); } diff --git a/src/ugid_linux.hpp b/src/ugid_linux.hpp index 7a0271f6..478dc8b5 100644 --- a/src/ugid_linux.hpp +++ b/src/ugid_linux.hpp @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -62,6 +63,9 @@ namespace ugid Set(const uid_t newuid_, const gid_t newgid_) { + assert((int)newuid_ != -1); + assert((int)newgid_ != -1); + if(!initialized) { currentuid = GETEUID(); @@ -81,7 +85,7 @@ namespace ugid if(newgid_) { SETREGID(-1,newgid_); - initgroups(newuid_,newgid_); + ugid::initgroups(newuid_,newgid_); } if(newuid_)