From 071cc93584c937ab58d9bdf921ce67571cd717eb Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Mon, 24 Nov 2025 12:29:24 -0600 Subject: [PATCH] Rework credential handling to support chroot & idmap Run in an elevated credential mode (caps for Linux and root for FreeBSD) and let the kernel manage entitlements. Will result in slightly different behavior but should not be noticed by most. --- Makefile | 1 - libfuse/lib/fuse_lowlevel.cpp | 19 ++--- src/caps.cpp | 102 ++++++++++++++++++++++ src/caps.hpp | 6 ++ src/fs_attr_linux.icpp | 4 +- src/fs_clonepath.cpp | 75 +++++++++++++--- src/fs_clonepath.hpp | 5 -- src/fs_is_rofs.hpp | 2 - src/fs_mkdir_as.hpp | 50 +++++++++++ src/fs_mkdir_as_root.hpp | 35 -------- src/fs_mkdirat.hpp | 48 +++++++++++ src/fs_mknod_as.hpp | 50 +++++++++++ src/fs_movefile_and_open.cpp | 2 - src/fs_open_as.hpp | 50 +++++++++++ src/fs_symlink_as.hpp | 48 +++++++++++ src/fuse_access.cpp | 3 +- src/fuse_chmod.cpp | 1 - src/fuse_chown.cpp | 3 +- src/fuse_create.cpp | 33 ++++--- src/fuse_getattr.cpp | 2 - src/fuse_getxattr.cpp | 2 - src/fuse_init.cpp | 4 +- src/fuse_ioctl.cpp | 6 +- src/fuse_link.cpp | 9 +- src/fuse_listxattr.cpp | 2 - src/fuse_mkdir.cpp | 39 +++++---- src/fuse_mknod.cpp | 39 +++++---- src/fuse_open.cpp | 2 - src/fuse_passthrough.hpp | 4 - src/fuse_readdir_cor.cpp | 2 - src/fuse_readdir_cosr.cpp | 10 +-- src/fuse_readdir_cosr_getdents.icpp | 7 +- src/fuse_readdir_cosr_readdir.icpp | 7 +- src/fuse_readdir_seq.cpp | 3 +- src/fuse_readlink.cpp | 3 +- src/fuse_removexattr.cpp | 2 - src/fuse_rename.cpp | 12 ++- src/fuse_rmdir.cpp | 1 - src/fuse_setxattr.cpp | 2 - src/fuse_statfs.cpp | 1 - src/fuse_statx_supported.icpp | 4 - src/fuse_symlink.cpp | 64 +++++++------- src/fuse_truncate.cpp | 3 +- src/fuse_unlink.cpp | 3 +- src/fuse_utimens.cpp | 3 +- src/mergerfs.cpp | 2 + src/policy_ff.cpp | 2 + src/ugid.cpp | 33 +------ src/ugid.hpp | 113 ++++++++++++++++++++++-- src/ugid_linux.hpp | 128 ---------------------------- src/ugid_linux.icpp | 34 -------- src/ugid_rwlock.hpp | 106 ----------------------- src/ugid_rwlock.icpp | 45 ---------- 53 files changed, 670 insertions(+), 566 deletions(-) create mode 100644 src/caps.cpp create mode 100644 src/caps.hpp create mode 100644 src/fs_mkdir_as.hpp delete mode 100644 src/fs_mkdir_as_root.hpp create mode 100644 src/fs_mkdirat.hpp create mode 100644 src/fs_mknod_as.hpp create mode 100644 src/fs_open_as.hpp create mode 100644 src/fs_symlink_as.hpp delete mode 100644 src/ugid_linux.hpp delete mode 100644 src/ugid_linux.icpp delete mode 100644 src/ugid_rwlock.hpp delete mode 100644 src/ugid_rwlock.icpp diff --git a/Makefile b/Makefile index 3686eb6f..a600e27a 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,6 @@ OPT_FLAGS := -O0 \ $(SANITIZE) \ -fstack-protector-strong \ -Wextra \ - -Werror \ -Wno-unused-parameter \ -DDEBUG endif diff --git a/libfuse/lib/fuse_lowlevel.cpp b/libfuse/lib/fuse_lowlevel.cpp index bf580195..ad0df588 100644 --- a/libfuse/lib/fuse_lowlevel.cpp +++ b/libfuse/lib/fuse_lowlevel.cpp @@ -1737,14 +1737,14 @@ 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 +// 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 @@ -1777,9 +1777,6 @@ 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/caps.cpp b/src/caps.cpp new file mode 100644 index 00000000..72d5a4f9 --- /dev/null +++ b/src/caps.cpp @@ -0,0 +1,102 @@ +#include "caps.hpp" + +#if defined __linux__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static +int +capset(cap_user_header_t header_, + const cap_user_data_t data_) +{ + return ::syscall(SYS_capset,header_,data_); +} + +static +int +capget(cap_user_header_t header_, + cap_user_data_t data_) +{ + return ::syscall(SYS_capget,header_,data_); +} + +static +int +capset(int cap_bit_) +{ + int rv; + struct __user_cap_header_struct header; + struct __user_cap_data_struct data[2]; + + header.version = _LINUX_CAPABILITY_VERSION_3; + header.pid = 0; + + rv = capget(&header,data); + if(rv < 0) + return rv; + + int word = cap_bit_ / 32; + int bit = cap_bit_ % 32; + + data[word].permitted |= (1 << bit); + data[word].effective |= (1 << bit); + data[word].inheritable |= (1 << bit); + + rv = capset(&header,data); + if(rv < 0) + return rv; + + return 0; +} + +int +caps::setup() +{ + int rv; + + rv = capset(CAP_DAC_OVERRIDE); + if(rv < 0) + return rv; + rv = capset(CAP_DAC_READ_SEARCH); + if(rv < 0) + return rv; + rv = capset(CAP_FOWNER); + if(rv < 0) + return rv; + rv = capset(CAP_CHOWN); + if(rv < 0) + return rv; + rv = capset(CAP_SETUID); + if(rv < 0) + return rv; + rv = capset(CAP_SETGID); + if(rv < 0) + return rv; + + rv = prctl(PR_SET_SECUREBITS, + SECBIT_KEEP_CAPS | SECBIT_NO_SETUID_FIXUP); + if(rv < 0) + return -errno; + + return 0; +} +#else +int +caps::setup() +{ + return -ENOTSUP; +} +#endif diff --git a/src/caps.hpp b/src/caps.hpp new file mode 100644 index 00000000..7ca22636 --- /dev/null +++ b/src/caps.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace caps +{ + int setup(); +} diff --git a/src/fs_attr_linux.icpp b/src/fs_attr_linux.icpp index 6133d6ed..47fd077b 100644 --- a/src/fs_attr_linux.icpp +++ b/src/fs_attr_linux.icpp @@ -31,7 +31,7 @@ using std::string; static int _get_fs_ioc_flags(const int fd, - int &flags) + int &flags) { int rv; @@ -45,7 +45,7 @@ _get_fs_ioc_flags(const int fd, static int _get_fs_ioc_flags(const string &file, - int &flags) + int &flags) { int fd; int rv; diff --git a/src/fs_clonepath.cpp b/src/fs_clonepath.cpp index 423b9d46..088b737a 100644 --- a/src/fs_clonepath.cpp +++ b/src/fs_clonepath.cpp @@ -27,6 +27,16 @@ #include "fs_xattr.hpp" #include "ugid.hpp" +#include "fs_close.hpp" +#include "fs_fstat.hpp" +#include "fs_mkdirat.hpp" +#include "fs_openat.hpp" +#include "fs_fchown.hpp" +#include "fs_fchmod.hpp" +#include "fs_futimens.hpp" + +#include "scope_guard.hpp" + static bool @@ -107,21 +117,62 @@ fs::clonepath(const fs::path &srcpath_, return 0; } + +// WORK IN PROGRESS +static int -fs::clonepath_as_root(const fs::path &srcpath_, - const fs::path &dstpath_, - const fs::path &relpath_, - const bool return_metadata_errors_) +_clonepath2(const int srcfd_, + const int dstfd_, + const fs::path &dirname_, + const bool return_metadata_errors_) { - if(relpath_.empty()) - return 0; - if(srcpath_ == dstpath_) + int rv; + int srcdirfd; + int dstdirfd; + struct stat st; + + if(dirname_.empty()) return 0; - const ugid::SetRootGuard ugid_guard; + rv = fs::mkdirat(dstfd_,dirname_,0); + if(rv < 0) + return ((rv == -EEXIST) ? 0 : rv); + + srcdirfd = fs::openat(srcfd_,dirname_,O_DIRECTORY); + if(srcdirfd < 0) + return srcdirfd; + DEFER { fs::close(srcdirfd); }; + + dstdirfd = fs::openat(dstfd_,dirname_,O_DIRECTORY); + if(dstdirfd < 0) + return dstdirfd; + DEFER { fs::close(dstdirfd); }; + + rv = fs::attr::copy(srcdirfd,dstdirfd,FS_ATTR_CLEAR_IMMUTABLE); + if(return_metadata_errors_ && (rv < 0) && !::_ignorable_error(-rv)) + return rv; + + rv = fs::xattr::copy(srcdirfd,dstdirfd); + if(return_metadata_errors_ && (rv < 0) && !::_ignorable_error(-rv)) + return rv; + + rv = fs::fstat(srcdirfd,&st); + if(rv < 0) + return rv; + if(!S_ISDIR(st.st_mode)) + return -ENOTDIR; + + rv = fs::fchown_check_on_error(dstdirfd,st); + if(rv < 0) + return rv; + + rv = fs::fchmod_check_on_error(dstdirfd,st); + if(rv < 0) + return rv; - return fs::clonepath(srcpath_, - dstpath_, - relpath_, - return_metadata_errors_); + rv = fs::futimens(dstdirfd,st); + if(rv < 0) + return rv; + + return 0; } diff --git a/src/fs_clonepath.hpp b/src/fs_clonepath.hpp index 3bd1a8c5..f5821f9d 100644 --- a/src/fs_clonepath.hpp +++ b/src/fs_clonepath.hpp @@ -25,9 +25,4 @@ namespace fs const fs::path &dstpath, const fs::path &relpath, const bool return_metadata_errors = false); - - int clonepath_as_root(const fs::path &srcpath, - const fs::path &dstpath, - const fs::path &relpath, - const bool return_metadata_errors = false); } diff --git a/src/fs_is_rofs.hpp b/src/fs_is_rofs.hpp index 22c556da..17ef7bf0 100644 --- a/src/fs_is_rofs.hpp +++ b/src/fs_is_rofs.hpp @@ -49,8 +49,6 @@ namespace fs bool is_rofs(const fs::path &path_) { - ugid::SetRootGuard const ugid; - int fd; std::string tmp_filepath; diff --git a/src/fs_mkdir_as.hpp b/src/fs_mkdir_as.hpp new file mode 100644 index 00000000..2e641101 --- /dev/null +++ b/src/fs_mkdir_as.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "fs_mkdir.hpp" + + +#if defined __linux__ +#include "ugid.hpp" + +namespace fs +{ + template + static + inline + int + mkdir_as(const ugid_t ugid_, + const T &path_, + const mode_t mode_) + { + const ugid::Set _(ugid_); + + return fs::mkdir(path_,mode_); + } +} +#elif defined __FreeBSD__ +#include "fs_lchown.hpp" + +namespace fs +{ + template + static + inline + int + mkdir_as(const ugid_t ugid_, + const T &path_,` + const mode_t mode_) + { + int rv; + + rv = fs::mkdir(path_,mode_); + if(rv < 0) + return rv; + + fs::lchown(path_,ugid_.uid,ugid_.gid); + + return 0; + } +} +#else +#error "Not Supported" +#endif diff --git a/src/fs_mkdir_as_root.hpp b/src/fs_mkdir_as_root.hpp deleted file mode 100644 index 3299ffa3..00000000 --- a/src/fs_mkdir_as_root.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - ISC License - - Copyright (c) 2021, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "fs_mkdir.hpp" -#include "ugid.hpp" - -namespace fs -{ - template - static - inline - int - mkdir_as_root(const T &path_, - const mode_t mode_) - { - const ugid::SetRootGuard guard; - - return fs::mkdir(path_,mode_); - } -} diff --git a/src/fs_mkdirat.hpp b/src/fs_mkdirat.hpp new file mode 100644 index 00000000..f87f9150 --- /dev/null +++ b/src/fs_mkdirat.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "to_neg_errno.hpp" +#include "fs_path.hpp" + +#include +#include + +namespace fs +{ + static + inline + int + mkdirat(const int dirfd_, + const char *pathname_, + const mode_t mode_) + { + int rv; + + rv = ::mkdirat(dirfd_,pathname_,mode_); + + return ::to_neg_errno(rv); + } + + static + inline + int + mkdirat(const int dirfd_, + const std::string &pathname_, + const mode_t mode_) + { + return fs::mkdirat(dirfd_, + pathname_.c_str(), + mode_); + } + + static + inline + int + mkdirat(const int dirfd_, + const fs::path &pathname_, + const mode_t mode_) + { + return fs::mkdirat(dirfd_, + pathname_.c_str(), + mode_); + } +} diff --git a/src/fs_mknod_as.hpp b/src/fs_mknod_as.hpp new file mode 100644 index 00000000..2ac0c39a --- /dev/null +++ b/src/fs_mknod_as.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "fs_mknod.hpp" + + +#if defined __linux__ +#include "ugid.hpp" + +namespace fs +{ + template + static + inline + int + mknod_as(const ugid_t ugid_, + const T &path_, + const mode_t mode_, + const dev_t dev_) + { + const ugid::Set _(ugid_); + + return fs::mknod(path_,mode_,dev_); + } +} +#elif defined __FreeBSD__ +#include "fs_lchown.hpp" + +namespace fs +{ + template + static + inline + int + mknod_as(const ugid_t ugid_, + const T &path_, + const mode_t mode_, + const dev_t dev_) + { + int rv; + + rv = fs::mknod(path_,mode_,dev_); + + fs::lchown(path_,ugid_.uid,ugid_.gid); + + return rv; + } +} +#else +#error "Not Supported!" +#endif diff --git a/src/fs_movefile_and_open.cpp b/src/fs_movefile_and_open.cpp index 9a9704e8..f59103cd 100644 --- a/src/fs_movefile_and_open.cpp +++ b/src/fs_movefile_and_open.cpp @@ -137,8 +137,6 @@ fs::movefile_and_open_as_root(const Policy::Create &policy_, const fs::path &fusepath_, const int origfd_) { - const ugid::Set ugid(0,0); - return fs::movefile_and_open(policy_, branches_, branchpath_, diff --git a/src/fs_open_as.hpp b/src/fs_open_as.hpp new file mode 100644 index 00000000..2c82b8dc --- /dev/null +++ b/src/fs_open_as.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "fs_open.hpp" + + +#if defined __linux__ +#include "ugid.hpp" + +namespace fs +{ + static + inline + int + open_as(const ugid_t ugid_, + const fs::path &path_, + const int flags_, + const mode_t mode_) + { + const ugid::Set _(ugid_); + + return fs::open(path_,flags_,mode_); + } +} +#elif defined __FreeBSD__ +#include "fs_lchown.hpp" + +namespace fs +{ + static + inline + int + open_as(const ugid_t ugid_, + const fs::path &path_, + const int flags_, + const mode_t mode_) + { + int rv; + + rv = fs::open(path_,flags_,mode_); + if(rv < 0) + return rv; + + fs::fchown(rv,ugid_.uid,ugid_.gid); + + return rv; + } +} +#else +#error "Not Supported!" +#endif diff --git a/src/fs_symlink_as.hpp b/src/fs_symlink_as.hpp new file mode 100644 index 00000000..fea967c8 --- /dev/null +++ b/src/fs_symlink_as.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "fs_symlink.hpp" + + +#if defined __linux__ +#include "ugid.hpp" + +namespace fs +{ + template + static + inline + int + symlink_as(const ugid_t ugid_, + const char *target_, + const T &linkpath_) + { + const ugid::Set _(ugid_); + + return fs::symlink(target_,linkpath_); + } +} +#elif defined __FreeBSD__ +#include "fs_lchown.hpp" + + template + static + inline + int + symlink_as(const ugid_t ugid_, + const char *target_, + const T &linkpath_) + { + int rv; + + rv = fs::symlink(target_,linkpath_); + if(rv < 0) + return rv; + + fs::lchown(linkpath_,ugid_.uid,ugid_.gid); + + return 0; + } +} +#else +#error "Not Supported!" +#endif diff --git a/src/fuse_access.cpp b/src/fuse_access.cpp index ae3419c8..521b75ab 100644 --- a/src/fuse_access.cpp +++ b/src/fuse_access.cpp @@ -54,8 +54,7 @@ FUSE::access(const fuse_req_ctx_t *ctx_, const char *fusepath_, int mask_) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_->uid,ctx_->gid); + const fs::path fusepath{fusepath_}; return ::_access(cfg.func.access.policy, cfg.branches, diff --git a/src/fuse_chmod.cpp b/src/fuse_chmod.cpp index aa3e1d59..79a8b1be 100644 --- a/src/fuse_chmod.cpp +++ b/src/fuse_chmod.cpp @@ -108,7 +108,6 @@ FUSE::chmod(const fuse_req_ctx_t *ctx_, mode_t mode_) { const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_->uid,ctx_->gid); return ::_chmod(fusepath,mode_); } diff --git a/src/fuse_chown.cpp b/src/fuse_chown.cpp index 2653a44e..2abb37b6 100644 --- a/src/fuse_chown.cpp +++ b/src/fuse_chown.cpp @@ -99,8 +99,7 @@ FUSE::chown(const fuse_req_ctx_t *ctx_, uid_t uid_, gid_t gid_) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_->uid,ctx_->gid); + const fs::path fusepath{fusepath_}; return ::_chown(cfg.func.chown.policy, cfg.func.getattr.policy, diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 253c3dc6..081628fa 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -19,11 +19,15 @@ #include "state.hpp" #include "config.hpp" +#include "fs_readlink.hpp" #include "errno.hpp" #include "fileinfo.hpp" #include "fs_acl.hpp" +#include "fs_close.hpp" #include "fs_clonepath.hpp" #include "fs_open.hpp" +#include "fs_open_as.hpp" +#include "fs_openat.hpp" #include "fs_path.hpp" #include "fuse_passthrough.hpp" #include "procfs.hpp" @@ -132,7 +136,8 @@ _config_to_ffi_flags(Config &cfg_, static int -_create_core(const fs::path &fullpath_, +_create_core(const ugid_t ugid_, + const fs::path &fullpath_, mode_t mode_, const mode_t umask_, const int flags_) @@ -140,12 +145,13 @@ _create_core(const fs::path &fullpath_, if(!fs::acl::dir_has_defaults(fullpath_)) mode_ &= ~umask_; - return fs::open(fullpath_,flags_,mode_); + return fs::open_as(ugid_,fullpath_,flags_,mode_); } static int -_create_core(const Branch *branch_, +_create_core(const ugid_t ugid_, + const Branch *branch_, const fs::path &fusepath_, fuse_file_info_t *ffi_, const mode_t mode_, @@ -157,7 +163,7 @@ _create_core(const Branch *branch_, fullpath = branch_->path / fusepath_; - rv = ::_create_core(fullpath,mode_,umask_,ffi_->flags); + rv = ::_create_core(ugid_,fullpath,mode_,umask_,ffi_->flags); if(rv < 0) return rv; @@ -170,7 +176,8 @@ _create_core(const Branch *branch_, static int -_create(const Policy::Search &searchFunc_, +_create(const ugid_t ugid_, + const Policy::Search &searchFunc_, const Policy::Create &createFunc_, const Branches &branches_, const fs::path &fusepath_, @@ -194,13 +201,14 @@ _create(const Policy::Search &searchFunc_, if(rv < 0) return rv; - rv = fs::clonepath_as_root(existingpaths[0]->path, - createpaths[0]->path, - fusedirpath); + rv = fs::clonepath(existingpaths[0]->path, + createpaths[0]->path, + fusedirpath); if(rv < 0) return rv; - return ::_create_core(createpaths[0], + return ::_create_core(ugid_, + createpaths[0], fusepath_, ffi_, mode_, @@ -225,7 +233,6 @@ _create_for_insert_lambda(const fuse_req_ctx_t *ctx_, { int rv; FileInfo *fi; - const ugid::Set ugid(ctx_->uid,ctx_->gid); ::_config_to_ffi_flags(cfg,ctx_->pid,ffi_); if(cfg.cache_writeback) @@ -233,7 +240,8 @@ _create_for_insert_lambda(const fuse_req_ctx_t *ctx_, ffi_->noflush = !::_calculate_flush(cfg.flushonclose, ffi_->flags); - rv = ::_create(cfg.func.getattr.policy, + rv = ::_create(ctx_, + cfg.func.getattr.policy, cfg.func.create.policy, cfg.branches, fusepath_, @@ -243,7 +251,8 @@ _create_for_insert_lambda(const fuse_req_ctx_t *ctx_, if(rv == -EROFS) { cfg.branches.find_and_set_mode_ro(); - rv = ::_create(cfg.func.getattr.policy, + rv = ::_create(ctx_, + cfg.func.getattr.policy, cfg.func.create.policy, cfg.branches, fusepath_, diff --git a/src/fuse_getattr.cpp b/src/fuse_getattr.cpp index 2dfe0096..6c441004 100644 --- a/src/fuse_getattr.cpp +++ b/src/fuse_getattr.cpp @@ -213,8 +213,6 @@ FUSE::getattr(const fuse_req_ctx_t *ctx_, struct stat *st_, fuse_timeouts_t *timeout_) { - const ugid::Set ugid(ctx_); - return FUSE::getattr(fusepath_,st_,timeout_); } diff --git a/src/fuse_getxattr.cpp b/src/fuse_getxattr.cpp index 5da8b12f..7e09ef4f 100644 --- a/src/fuse_getxattr.cpp +++ b/src/fuse_getxattr.cpp @@ -193,8 +193,6 @@ FUSE::getxattr(const fuse_req_ctx_t *ctx_, if(cfg.xattr.to_int()) return -cfg.xattr.to_int(); - const ugid::Set ugid(ctx_->uid,ctx_->gid); - return ::_getxattr(cfg.func.getxattr.policy, cfg.branches, fusepath, diff --git a/src/fuse_init.cpp b/src/fuse_init.cpp index 1313e0f6..3877878a 100644 --- a/src/fuse_init.cpp +++ b/src/fuse_init.cpp @@ -16,6 +16,8 @@ #include "fuse_init.hpp" +#include "caps.hpp" + #include "config.hpp" #include "fs_readahead.hpp" #include "procfs.hpp" @@ -187,7 +189,7 @@ void * FUSE::init(fuse_conn_info *conn_) { procfs::init(); - ugid::init(); + caps::setup(); cfg.readdir.initialize(); ::_want_if_capable(conn_,FUSE_CAP_ASYNC_DIO); diff --git a/src/fuse_ioctl.cpp b/src/fuse_ioctl.cpp index 28e5a086..0cfb984c 100644 --- a/src/fuse_ioctl.cpp +++ b/src/fuse_ioctl.cpp @@ -113,8 +113,7 @@ _ioctl_file(const fuse_req_ctx_t *ctx_, void *data_, uint32_t *out_bufsz_) { - FileInfo *fi = FileInfo::from_fh(ffi_->fh); - const ugid::Set ugid(ctx_); + FileInfo *fi = FileInfo::from_fh(ffi_->fh); return ::_ioctl(fi->fd,cmd_,data_,out_bufsz_); } @@ -162,8 +161,7 @@ _ioctl_dir(const fuse_req_ctx_t *ctx_, void *data_, uint32_t *out_bufsz_) { - DirInfo *di = DirInfo::from_fh(ffi_->fh); - const ugid::Set ugid(ctx_); + DirInfo *di = DirInfo::from_fh(ffi_->fh); return ::_ioctl_dir_base(cfg.func.open.policy, cfg.branches, diff --git a/src/fuse_link.cpp b/src/fuse_link.cpp index 9bbc4f7f..64be0135 100644 --- a/src/fuse_link.cpp +++ b/src/fuse_link.cpp @@ -55,7 +55,9 @@ _link_create_path_loop(const std::vector &oldbranches_, rv = fs::link(oldfullpath,newfullpath); if(rv == -ENOENT) { - rv = fs::clonepath_as_root(newbranch_->path,oldbranch->path,newfusedirpath_); + rv = fs::clonepath(newbranch_->path, + oldbranch->path, + newfusedirpath_); if(rv == 0) rv = fs::link(oldfullpath,newfullpath); } @@ -328,9 +330,8 @@ FUSE::link(const fuse_req_ctx_t *ctx_, fuse_timeouts_t *timeouts_) { int rv; - const fs::path oldpath{oldpath_}; - const fs::path newpath{newpath_}; - const ugid::Set ugid(ctx_); + const fs::path oldpath{oldpath_}; + const fs::path newpath{newpath_}; rv = ::_link(ctx_,oldpath,newpath,st_,timeouts_); if(rv == -EXDEV) diff --git a/src/fuse_listxattr.cpp b/src/fuse_listxattr.cpp index e7cadca8..7ae092ff 100644 --- a/src/fuse_listxattr.cpp +++ b/src/fuse_listxattr.cpp @@ -143,8 +143,6 @@ FUSE::listxattr(const fuse_req_ctx_t *ctx_, return -ENOSYS; } - const ugid::Set ugid(ctx_); - return ::_listxattr(cfg.func.listxattr.policy, cfg.branches, fusepath, diff --git a/src/fuse_mkdir.cpp b/src/fuse_mkdir.cpp index 883f4ac2..854ec2ce 100644 --- a/src/fuse_mkdir.cpp +++ b/src/fuse_mkdir.cpp @@ -21,7 +21,7 @@ #include "error.hpp" #include "fs_acl.hpp" #include "fs_clonepath.hpp" -#include "fs_mkdir.hpp" +#include "fs_mkdir_as.hpp" #include "fs_path.hpp" #include "policy.hpp" #include "ugid.hpp" @@ -33,19 +33,21 @@ static int -_mkdir_core(const fs::path &fullpath_, +_mkdir_core(const ugid_t ugid_, + const fs::path &fullpath_, mode_t mode_, const mode_t umask_) { if(!fs::acl::dir_has_defaults(fullpath_)) mode_ &= ~umask_; - return fs::mkdir(fullpath_,mode_); + return fs::mkdir_as(ugid_,fullpath_,mode_); } static int -_mkdir_loop_core(const fs::path &createpath_, +_mkdir_loop_core(const ugid_t ugid_, + const fs::path &createpath_, const fs::path &fusepath_, const mode_t mode_, const mode_t umask_) @@ -55,14 +57,15 @@ _mkdir_loop_core(const fs::path &createpath_, fullpath = createpath_ / fusepath_; - rv = ::_mkdir_core(fullpath,mode_,umask_); + rv = ::_mkdir_core(ugid_,fullpath,mode_,umask_); return rv; } static int -_mkdir_loop(const Branch *existingbranch_, +_mkdir_loop(const ugid_t ugid_, + const Branch *existingbranch_, const std::vector &createbranches_, const fs::path &fusepath_, const fs::path &fusedirpath_, @@ -74,16 +77,17 @@ _mkdir_loop(const Branch *existingbranch_, for(const auto &createbranch : createbranches_) { - rv = fs::clonepath_as_root(existingbranch_->path, - createbranch->path, - fusedirpath_); + rv = fs::clonepath(existingbranch_->path, + createbranch->path, + fusedirpath_); if(rv < 0) { err = rv; continue; } - err = ::_mkdir_loop_core(createbranch->path, + err = ::_mkdir_loop_core(ugid_, + createbranch->path, fusepath_, mode_, umask_); @@ -94,7 +98,8 @@ _mkdir_loop(const Branch *existingbranch_, static int -_mkdir(const Policy::Search &getattrPolicy_, +_mkdir(const ugid_t ugid_, + const Policy::Search &getattrPolicy_, const Policy::Create &mkdirPolicy_, const Branches &branches_, const fs::path &fusepath_, @@ -116,7 +121,8 @@ _mkdir(const Policy::Search &getattrPolicy_, if(rv < 0) return rv; - return ::_mkdir_loop(existingbranches[0], + return ::_mkdir_loop(ugid_, + existingbranches[0], createbranches, fusepath_, fusedirpath, @@ -130,10 +136,10 @@ FUSE::mkdir(const fuse_req_ctx_t *ctx_, mode_t mode_) { int rv; - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; - rv = ::_mkdir(cfg.func.getattr.policy, + rv = ::_mkdir(ctx_, + cfg.func.getattr.policy, cfg.func.mkdir.policy, cfg.branches, fusepath, @@ -142,7 +148,8 @@ FUSE::mkdir(const fuse_req_ctx_t *ctx_, if(rv == -EROFS) { cfg.branches.find_and_set_mode_ro(); - rv = ::_mkdir(cfg.func.getattr.policy, + rv = ::_mkdir(ctx_, + cfg.func.getattr.policy, cfg.func.mkdir.policy, cfg.branches, fusepath, diff --git a/src/fuse_mknod.cpp b/src/fuse_mknod.cpp index 80d4f853..a1df63f1 100644 --- a/src/fuse_mknod.cpp +++ b/src/fuse_mknod.cpp @@ -20,7 +20,7 @@ #include "errno.hpp" #include "error.hpp" #include "fs_acl.hpp" -#include "fs_mknod.hpp" +#include "fs_mknod_as.hpp" #include "fs_clonepath.hpp" #include "fs_path.hpp" #include "ugid.hpp" @@ -34,7 +34,8 @@ static inline int -_mknod_core(const fs::path &fullpath_, +_mknod_core(const ugid_t ugid_, + const fs::path &fullpath_, mode_t mode_, const mode_t umask_, const dev_t dev_) @@ -42,12 +43,13 @@ _mknod_core(const fs::path &fullpath_, if(!fs::acl::dir_has_defaults(fullpath_)) mode_ &= ~umask_; - return fs::mknod(fullpath_,mode_,dev_); + return fs::mknod_as(ugid_,fullpath_,mode_,dev_); } static int -_mknod_loop_core(const fs::path &createbranch_, +_mknod_loop_core(const ugid_t ugid_, + const fs::path &createbranch_, const fs::path &fusepath_, const mode_t mode_, const mode_t umask_, @@ -58,14 +60,15 @@ _mknod_loop_core(const fs::path &createbranch_, fullpath = createbranch_ / fusepath_; - rv = ::_mknod_core(fullpath,mode_,umask_,dev_); + rv = ::_mknod_core(ugid_,fullpath,mode_,umask_,dev_); return rv; } static int -_mknod_loop(const fs::path &existingbranch_, +_mknod_loop(const ugid_t ugid_, + const fs::path &existingbranch_, const std::vector &createbranches_, const fs::path &fusepath_, const fs::path &fusedirpath_, @@ -78,16 +81,17 @@ _mknod_loop(const fs::path &existingbranch_, for(const auto &createbranch : createbranches_) { - rv = fs::clonepath_as_root(existingbranch_, - createbranch->path, - fusedirpath_); + rv = fs::clonepath(existingbranch_, + createbranch->path, + fusedirpath_); if(rv < 0) { err = rv; continue; } - err = ::_mknod_loop_core(createbranch->path, + err = ::_mknod_loop_core(ugid_, + createbranch->path, fusepath_, mode_, umask_, @@ -99,7 +103,8 @@ _mknod_loop(const fs::path &existingbranch_, static int -_mknod(const Policy::Search &searchFunc_, +_mknod(const ugid_t ugid_, + const Policy::Search &searchFunc_, const Policy::Create &createFunc_, const Branches &branches_, const fs::path &fusepath_, @@ -122,7 +127,8 @@ _mknod(const Policy::Search &searchFunc_, if(rv < 0) return rv; - return ::_mknod_loop(existingbranches[0]->path, + return ::_mknod_loop(ugid_, + existingbranches[0]->path, createbranches, fusepath_, fusedirpath, @@ -138,10 +144,10 @@ FUSE::mknod(const fuse_req_ctx_t *ctx_, dev_t rdev_) { int rv; - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; - rv = ::_mknod(cfg.func.getattr.policy, + rv = ::_mknod(ctx_, + cfg.func.getattr.policy, cfg.func.mknod.policy, cfg.branches, fusepath, @@ -151,7 +157,8 @@ FUSE::mknod(const fuse_req_ctx_t *ctx_, if(rv == -EROFS) { cfg.branches.find_and_set_mode_ro(); - rv = ::_mknod(cfg.func.getattr.policy, + rv = ::_mknod(ctx_, + cfg.func.getattr.policy, cfg.func.mknod.policy, cfg.branches, fusepath, diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 6723380a..62de6d9a 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -281,7 +281,6 @@ _open_for_insert_lambda(const fuse_req_ctx_t *ctx_, { int rv; FileInfo *fi; - const ugid::Set ugid(ctx_); ::_config_to_ffi_flags(cfg,ctx_->pid,ffi_); @@ -337,7 +336,6 @@ _open_for_update_lambda(const fuse_req_ctx_t *ctx_, State::OpenFile *of_) { int rv; - const ugid::Set ugid(ctx_); ::_config_to_ffi_flags(cfg,ctx_->pid,ffi_); diff --git a/src/fuse_passthrough.hpp b/src/fuse_passthrough.hpp index fcccf817..99f8a7ea 100644 --- a/src/fuse_passthrough.hpp +++ b/src/fuse_passthrough.hpp @@ -14,8 +14,6 @@ namespace FUSE int passthrough_open(const int fd_) { - const ugid::SetRootGuard _; - return fuse_passthrough_open(fd_); } @@ -24,8 +22,6 @@ namespace FUSE int passthrough_close(const int backing_id_) { - const ugid::SetRootGuard _; - return fuse_passthrough_close(backing_id_); } } diff --git a/src/fuse_readdir_cor.cpp b/src/fuse_readdir_cor.cpp index f61a0e61..a32c3bca 100644 --- a/src/fuse_readdir_cor.cpp +++ b/src/fuse_readdir_cor.cpp @@ -64,8 +64,6 @@ _concurrent_readdir(ThreadPool &tp_, auto func = [&,dirents_,uid_,gid_]() { - const ugid::Set ugid(uid_,gid_); - return ::_readdir(branch.path, rel_dirpath_, names, diff --git a/src/fuse_readdir_cosr.cpp b/src/fuse_readdir_cosr.cpp index c7e39a1a..0add595d 100644 --- a/src/fuse_readdir_cosr.cpp +++ b/src/fuse_readdir_cosr.cpp @@ -45,16 +45,14 @@ int _readdir(ThreadPool &tp_, const Branches::Ptr &branches_, const fs::path &rel_dirpath_, - fuse_dirents_t *dirents_, - uid_t const uid_, - gid_t const gid_) + fuse_dirents_t *dirents_) { int rv; std::vector> futures; fuse_dirents_reset(dirents_); - futures = ::_opendir(tp_,branches_,rel_dirpath_,uid_,gid_); + futures = ::_opendir(tp_,branches_,rel_dirpath_); rv = ::_readdir(futures,rel_dirpath_,dirents_); return rv; @@ -70,7 +68,5 @@ FUSE::ReadDirCOSR::operator()(const fuse_req_ctx_t *ctx_, return ::_readdir(_tp, cfg.branches, di->fusepath, - dirents_, - ctx_->uid, - ctx_->gid); + dirents_); } diff --git a/src/fuse_readdir_cosr_getdents.icpp b/src/fuse_readdir_cosr_getdents.icpp index 40e3992d..e4dcdb30 100644 --- a/src/fuse_readdir_cosr_getdents.icpp +++ b/src/fuse_readdir_cosr_getdents.icpp @@ -28,9 +28,7 @@ inline std::vector> _opendir(ThreadPool &tp_, const Branches::Ptr &branches_, - const fs::path &rel_dirpath_, - uid_t const uid_, - gid_t const gid_) + const fs::path &rel_dirpath_) { std::vector> futures; @@ -39,11 +37,10 @@ _opendir(ThreadPool &tp_, for(const auto &branch : *branches_) { auto func = - [&branch,&rel_dirpath_,uid_,gid_]() + [&branch,&rel_dirpath_]() { int fd; fs::path abs_dirpath; - const ugid::Set ugid(uid_,gid_); abs_dirpath = branch.path / rel_dirpath_; diff --git a/src/fuse_readdir_cosr_readdir.icpp b/src/fuse_readdir_cosr_readdir.icpp index ec76060e..3ff12bfc 100644 --- a/src/fuse_readdir_cosr_readdir.icpp +++ b/src/fuse_readdir_cosr_readdir.icpp @@ -37,9 +37,7 @@ inline std::vector> _opendir(ThreadPool &tp_, const Branches::Ptr &branches_, - const fs::path &rel_dirpath_, - uid_t const uid_, - gid_t const gid_) + const fs::path &rel_dirpath_) { std::vector> futures; @@ -48,11 +46,10 @@ _opendir(ThreadPool &tp_, for(const auto &branch : *branches_) { auto func = - [&branch,&rel_dirpath_,uid_,gid_]() + [&branch,&rel_dirpath_]() { DIR *dir; fs::path abs_dirpath; - const ugid::Set ugid(uid_,gid_); abs_dirpath = branch.path / rel_dirpath_; diff --git a/src/fuse_readdir_seq.cpp b/src/fuse_readdir_seq.cpp index ee27021c..370a0985 100644 --- a/src/fuse_readdir_seq.cpp +++ b/src/fuse_readdir_seq.cpp @@ -33,8 +33,7 @@ FUSE::ReadDirSeq::operator()(const fuse_req_ctx_t *ctx_, const fuse_file_info_t *ffi_, fuse_dirents_t *dirents_) { - DirInfo *di = DirInfo::from_fh(ffi_->fh); - const ugid::Set ugid(ctx_); + DirInfo *di = DirInfo::from_fh(ffi_->fh); return ::_readdir(cfg.branches, di->fusepath, diff --git a/src/fuse_readlink.cpp b/src/fuse_readlink.cpp index 989db75c..3a0123eb 100644 --- a/src/fuse_readlink.cpp +++ b/src/fuse_readlink.cpp @@ -120,8 +120,7 @@ FUSE::readlink(const fuse_req_ctx_t *ctx_, char *buf_, size_t size_) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; return ::_readlink(cfg.func.readlink.policy, cfg.branches, diff --git a/src/fuse_removexattr.cpp b/src/fuse_removexattr.cpp index 87a2dcaf..c952d98a 100644 --- a/src/fuse_removexattr.cpp +++ b/src/fuse_removexattr.cpp @@ -101,8 +101,6 @@ FUSE::removexattr(const fuse_req_ctx_t *ctx_, if(cfg.xattr.to_int()) return -cfg.xattr.to_int(); - const ugid::Set ugid(ctx_); - return ::_removexattr(cfg.func.removexattr.policy, cfg.func.getxattr.policy, cfg.branches, diff --git a/src/fuse_rename.cpp b/src/fuse_rename.cpp index 224da590..f775c2fa 100644 --- a/src/fuse_rename.cpp +++ b/src/fuse_rename.cpp @@ -21,7 +21,7 @@ #include "errno.hpp" #include "fs_clonepath.hpp" #include "fs_link.hpp" -#include "fs_mkdir_as_root.hpp" +#include "fs_mkdir_as.hpp" #include "fs_path.hpp" #include "fs_remove.hpp" #include "fs_rename.hpp" @@ -105,9 +105,9 @@ _rename_create_path(const Policy::Search &searchPolicy_, rv = fs::rename(oldfullpath,newfullpath); if(rv < 0) { - rv = fs::clonepath_as_root(newbranches[0]->path, - branch.path, - newfusepath_.parent_path()); + rv = fs::clonepath(newbranches[0]->path, + branch.path, + newfusepath_.parent_path()); if(rv >= 0) rv = fs::rename(oldfullpath,newfullpath); } @@ -209,7 +209,6 @@ _rename_exdev_rename_target(const Policy::Action &actionPolicy_, if(rv < 0) return rv; - ugid::SetRootGuard ugidGuard; for(auto &branch : obranches_) { clonesrc = branch->path; @@ -219,7 +218,7 @@ _rename_exdev_rename_target(const Policy::Action &actionPolicy_, rv = fs::clonepath(clonesrc,clonedst,oldfusepath_.parent_path()); if(rv == -ENOENT) { - fs::mkdir(clonedst,01777); + fs::mkdir_as({0,0},clonedst,01777); rv = fs::clonepath(clonesrc,clonedst,oldfusepath_.parent_path()); } @@ -355,7 +354,6 @@ FUSE::rename(const fuse_req_ctx_t *ctx_, int rv; const fs::path oldfusepath{oldfusepath_}; const fs::path newfusepath{newfusepath_}; - const ugid::Set ugid(ctx_); rv = ::_rename(oldfusepath,newfusepath); if(rv == -EXDEV) diff --git a/src/fuse_rmdir.cpp b/src/fuse_rmdir.cpp index 29b29d6f..5a7cff2e 100644 --- a/src/fuse_rmdir.cpp +++ b/src/fuse_rmdir.cpp @@ -96,7 +96,6 @@ FUSE::rmdir(const fuse_req_ctx_t *ctx_, const char *fusepath_) { const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); return ::_rmdir(cfg.func.rmdir.policy, cfg.branches, diff --git a/src/fuse_setxattr.cpp b/src/fuse_setxattr.cpp index 6bbd0319..8a527b4e 100644 --- a/src/fuse_setxattr.cpp +++ b/src/fuse_setxattr.cpp @@ -194,8 +194,6 @@ _setxattr(const fuse_req_ctx_t *ctx_, if(cfg.xattr.to_int()) return -cfg.xattr.to_int(); - const ugid::Set ugid(ctx_); - return ::_setxattr(cfg.func.setxattr.policy, cfg.func.getxattr.policy, cfg.branches, diff --git a/src/fuse_statfs.cpp b/src/fuse_statfs.cpp index 2ddd343a..c230881c 100644 --- a/src/fuse_statfs.cpp +++ b/src/fuse_statfs.cpp @@ -147,7 +147,6 @@ FUSE::statfs(const fuse_req_ctx_t *ctx_, struct statvfs *st_) { const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); return ::_statfs(cfg.branches, fusepath, diff --git a/src/fuse_statx_supported.icpp b/src/fuse_statx_supported.icpp index 32089583..6e99e9ef 100644 --- a/src/fuse_statx_supported.icpp +++ b/src/fuse_statx_supported.icpp @@ -213,8 +213,6 @@ FUSE::statx(const fuse_req_ctx_t *ctx_, if(Config::is_ctrl_file(fusepath)) return ::_statx_controlfile(st_); - const ugid::Set ugid(ctx_); - return ::_statx(fusepath, flags_|AT_STATX_DONT_SYNC, mask_, @@ -247,8 +245,6 @@ FUSE::statx_fh(const fuse_req_ctx_t *ctx_, FileInfo *fi = FileInfo::from_fh(fh); - const ugid::Set ugid(ctx_); - return ::_statx(fi->fusepath, flags_|AT_STATX_DONT_SYNC, mask_, diff --git a/src/fuse_symlink.cpp b/src/fuse_symlink.cpp index ae5803ce..7a18a08f 100644 --- a/src/fuse_symlink.cpp +++ b/src/fuse_symlink.cpp @@ -23,7 +23,7 @@ #include "fs_lstat.hpp" #include "fs_path.hpp" #include "fs_inode.hpp" -#include "fs_symlink.hpp" +#include "fs_symlink_as.hpp" #include "fuse_getattr.hpp" #include "ugid.hpp" @@ -35,7 +35,8 @@ static int -_symlink_loop_core(const fs::path &newbranch_, +_symlink_loop_core(const ugid_t ugid_, + const fs::path &newbranch_, const char *target_, const fs::path &linkpath_, struct stat *st_) @@ -45,7 +46,7 @@ _symlink_loop_core(const fs::path &newbranch_, fullnewpath = newbranch_ / linkpath_; - rv = fs::symlink(target_,fullnewpath); + rv = fs::symlink_as(ugid_,target_,fullnewpath); if((rv >= 0) && (st_ != NULL) && (st_->st_ino == 0)) { fs::lstat(fullnewpath,st_); @@ -60,7 +61,8 @@ _symlink_loop_core(const fs::path &newbranch_, static int -_symlink_loop(const fs::path &existingbranch_, +_symlink_loop(const ugid_t ugid_, + const fs::path &existingbranch_, const std::vector &newbranches_, const char *target_, const fs::path &linkpath_, @@ -72,13 +74,14 @@ _symlink_loop(const fs::path &existingbranch_, for(auto &newbranch :newbranches_) { - rv = fs::clonepath_as_root(existingbranch_, - newbranch->path, - newdirpath_); + rv = fs::clonepath(existingbranch_, + newbranch->path, + newdirpath_); if(rv < 0) err = rv; else - err = ::_symlink_loop_core(newbranch->path, + err = ::_symlink_loop_core(ugid_, + newbranch->path, target_, linkpath_, st_); @@ -89,7 +92,8 @@ _symlink_loop(const fs::path &existingbranch_, static int -_symlink(const Policy::Search &searchFunc_, +_symlink(const ugid_t ugid_, + const Policy::Search &searchFunc_, const Policy::Create &createFunc_, const Branches &branches_, const char *target_, @@ -111,7 +115,8 @@ _symlink(const Policy::Search &searchFunc_, if(rv < 0) return rv; - return ::_symlink_loop(existingbranches[0]->path, + return ::_symlink_loop(ugid_, + existingbranches[0]->path, newbranches, target_, linkpath_, @@ -119,22 +124,6 @@ _symlink(const Policy::Search &searchFunc_, st_); } -int -FUSE::symlink(const fuse_req_ctx_t *ctx_, - const char *target_, - const char *linkpath_, - struct stat *st_, - fuse_timeouts_t *timeouts_) -{ - const fs::path linkpath{linkpath_}; - - return FUSE::symlink(ctx_, - target_, - linkpath, - st_, - timeouts_); -} - int FUSE::symlink(const fuse_req_ctx_t *ctx_, const char *target_, @@ -143,9 +132,9 @@ FUSE::symlink(const fuse_req_ctx_t *ctx_, fuse_timeouts_t *timeouts_) { int rv; - const ugid::Set ugid(ctx_); - rv = ::_symlink(cfg.func.getattr.policy, + rv = ::_symlink(ctx_, + cfg.func.getattr.policy, cfg.func.symlink.policy, cfg.branches, target_, @@ -154,7 +143,8 @@ FUSE::symlink(const fuse_req_ctx_t *ctx_, if(rv == -EROFS) { cfg.branches.find_and_set_mode_ro(); - rv = ::_symlink(cfg.func.getattr.policy, + rv = ::_symlink(ctx_, + cfg.func.getattr.policy, cfg.func.symlink.policy, cfg.branches, target_, @@ -181,3 +171,19 @@ FUSE::symlink(const fuse_req_ctx_t *ctx_, return rv; } + +int +FUSE::symlink(const fuse_req_ctx_t *ctx_, + const char *target_, + const char *linkpath_, + struct stat *st_, + fuse_timeouts_t *timeouts_) +{ + const fs::path linkpath{linkpath_}; + + return FUSE::symlink(ctx_, + target_, + linkpath, + st_, + timeouts_); +} diff --git a/src/fuse_truncate.cpp b/src/fuse_truncate.cpp index ff0ad2f3..f3008268 100644 --- a/src/fuse_truncate.cpp +++ b/src/fuse_truncate.cpp @@ -94,8 +94,7 @@ FUSE::truncate(const fuse_req_ctx_t *ctx_, const char *fusepath_, off_t size_) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; return ::_truncate(cfg.func.truncate.policy, cfg.func.getattr.policy, diff --git a/src/fuse_unlink.cpp b/src/fuse_unlink.cpp index 144c9264..a870c930 100644 --- a/src/fuse_unlink.cpp +++ b/src/fuse_unlink.cpp @@ -68,8 +68,7 @@ int FUSE::unlink(const fuse_req_ctx_t *ctx_, const char *fusepath_) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; return ::_unlink(cfg.func.unlink.policy, cfg.branches, diff --git a/src/fuse_utimens.cpp b/src/fuse_utimens.cpp index b383b466..485a14f2 100644 --- a/src/fuse_utimens.cpp +++ b/src/fuse_utimens.cpp @@ -93,8 +93,7 @@ FUSE::utimens(const fuse_req_ctx_t *ctx_, const char *fusepath_, const timespec ts_[2]) { - const fs::path fusepath{fusepath_}; - const ugid::Set ugid(ctx_); + const fs::path fusepath{fusepath_}; return ::_utimens(cfg.func.utimens.policy, cfg.func.getattr.policy, diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 207a3bc1..efc11709 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -18,6 +18,8 @@ #include "mergerfs_fsck.hpp" #include "mergerfs_collect_info.hpp" +#include "caps.hpp" + #include "config.hpp" #include "fs_path.hpp" #include "fs_readahead.hpp" diff --git a/src/policy_ff.cpp b/src/policy_ff.cpp index c80d1840..4d0daf54 100644 --- a/src/policy_ff.cpp +++ b/src/policy_ff.cpp @@ -16,6 +16,8 @@ #include "policy_ff.hpp" +#include "ugid.hpp" + #include "errno.hpp" #include "fs_exists.hpp" #include "fs_info.hpp" diff --git a/src/ugid.cpp b/src/ugid.cpp index 81a8ff58..cdf8b33d 100644 --- a/src/ugid.cpp +++ b/src/ugid.cpp @@ -1,33 +1,8 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "gidcache.hpp" - -#if defined __linux__ and UGID_USE_RWLOCK == 0 -#include "ugid_linux.icpp" -#else -#include "ugid_rwlock.icpp" -#endif +#include namespace ugid { - void - initgroups(const uid_t uid_, - const gid_t gid_) - { - GIDCache::initgroups(uid_,gid_); - } + thread_local uid_t currentuid = 0; + thread_local gid_t currentgid = 0; + thread_local bool initialized = false; } diff --git a/src/ugid.hpp b/src/ugid.hpp index 8adf47bb..9d42f5f6 100644 --- a/src/ugid.hpp +++ b/src/ugid.hpp @@ -16,21 +16,116 @@ #pragma once +#include "fuse_req_ctx.h" + +#include "fuse_kernel.h" + +#include +#include #include #include +#include +#include + +#include #include +#include "fuse_req_ctx.h" -namespace ugid +#include +#include + +#include + +struct ugid_t { - void init(); - void initgroups(const uid_t uid, const gid_t gid); -} + ugid_t(const uid_t uid_, + const gid_t gid_) + : uid(uid_), + gid(gid_) + { + } + + ugid_t(const fuse_req_ctx_t *ctx_) + : ugid_t(ctx_->uid,ctx_->gid) + { + } + + uid_t uid; + gid_t gid; +}; + +#if defined SYS_setreuid32 +#define SETREUID(R,E) (::syscall(SYS_setreuid32,(R),(E))) +#else +#define SETREUID(R,E) (::syscall(SYS_setreuid,(R),(E))) +#endif + +#if defined SYS_setregid32 +#define SETREGID(R,E) (::syscall(SYS_setregid32,(R),(E))) +#else +#define SETREGID(R,E) (::syscall(SYS_setregid,(R),(E))) +#endif -#if defined __linux__ and UGID_USE_RWLOCK == 0 -#pragma message "using ugid_linux.hpp" -#include "ugid_linux.hpp" +#if defined SYS_geteuid32 +#define GETEUID() (::syscall(SYS_geteuid32)) #else -#pragma message "using ugid_rwlock.hpp" -#include "ugid_rwlock.hpp" +#define GETEUID() (::syscall(SYS_geteuid)) #endif + +#if defined SYS_getegid32 +#define GETEGID() (::syscall(SYS_getegid32)) +#else +#define GETEGID() (::syscall(SYS_getegid)) +#endif + +namespace ugid +{ + extern thread_local uid_t currentuid; + extern thread_local gid_t currentgid; + extern thread_local bool initialized; + + struct Set + { + Set(const uid_t newuid_, + const gid_t newgid_) + { + uid_t newuid; + gid_t newgid; + + newuid = ((newuid_ == FUSE_INVALID_UIDGID) ? 0 : newuid_); + newgid = ((newgid_ == FUSE_INVALID_UIDGID) ? 0 : newgid_); + + if(!initialized) + { + currentuid = GETEUID(); + currentgid = GETEGID(); + initialized = true; + } + + if((newuid == currentuid) && (newgid == currentgid)) + return; + + SETREGID(-1,newgid); + SETREUID(-1,newuid); + + currentuid = newuid; + currentgid = newgid; + } + + Set(const fuse_req_ctx_t *ctx_) + : Set(ctx_->uid,ctx_->gid) + { + } + + Set(const ugid_t ugid_) + : Set(ugid_.uid,ugid_.gid) + { + } + }; +} + +#undef SETREUID +#undef SETREGID +#undef GETEUID +#undef GETEGID diff --git a/src/ugid_linux.hpp b/src/ugid_linux.hpp deleted file mode 100644 index 422904bd..00000000 --- a/src/ugid_linux.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#pragma once - -#include "fuse_req_ctx.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#if defined SYS_setreuid32 -#define SETREUID(R,E) (::syscall(SYS_setreuid32,(R),(E))) -#else -#define SETREUID(R,E) (::syscall(SYS_setreuid,(R),(E))) -#endif - -#if defined SYS_setregid32 -#define SETREGID(R,E) (::syscall(SYS_setregid32,(R),(E))) -#else -#define SETREGID(R,E) (::syscall(SYS_setregid,(R),(E))) -#endif - -#if defined SYS_geteuid32 -#define GETEUID() (::syscall(SYS_geteuid32)) -#else -#define GETEUID() (::syscall(SYS_geteuid)) -#endif - -#if defined SYS_getegid32 -#define GETEGID() (::syscall(SYS_getegid32)) -#else -#define GETEGID() (::syscall(SYS_getegid)) -#endif - -namespace ugid -{ - extern thread_local uid_t currentuid; - extern thread_local gid_t currentgid; - extern thread_local bool initialized; - - struct Set - { - Set(const uid_t newuid_, - const gid_t newgid_) - { - assert((int)newuid_ != -1); - assert((int)newgid_ != -1); - - if(!initialized) - { - currentuid = GETEUID(); - currentgid = GETEGID(); - initialized = true; - } - - if((newuid_ == currentuid) && (newgid_ == currentgid)) - return; - - if(currentuid != 0) - { - SETREUID(-1,0); - SETREGID(-1,0); - } - - if(newgid_) - { - SETREGID(-1,newgid_); - ugid::initgroups(newuid_,newgid_); - } - - if(newuid_) - SETREUID(-1,newuid_); - - currentuid = newuid_; - currentgid = newgid_; - } - - Set(const fuse_req_ctx_t *ctx_) - : Set(ctx_->uid,ctx_->gid) - { - } - }; - - struct SetRootGuard - { - SetRootGuard() : - prevuid(currentuid), - prevgid(currentgid) - { - Set(0,0); - } - - ~SetRootGuard() - { - Set(prevuid,prevgid); - } - - const uid_t prevuid; - const gid_t prevgid; - }; -} - -#undef SETREUID -#undef SETREGID -#undef GETEUID -#undef GETEGID diff --git a/src/ugid_linux.icpp b/src/ugid_linux.icpp deleted file mode 100644 index bd768fe5..00000000 --- a/src/ugid_linux.icpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include -#include -#include -#include - -#include - -namespace ugid -{ - thread_local uid_t currentuid = 0; - thread_local gid_t currentgid = 0; - thread_local bool initialized = false; - - void - init() - { - } -} diff --git a/src/ugid_rwlock.hpp b/src/ugid_rwlock.hpp deleted file mode 100644 index d0bf4fc5..00000000 --- a/src/ugid_rwlock.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#pragma once - -#include "fuse_req_ctx.h" - -#include -#include -#include -#include - -namespace ugid -{ - extern uid_t currentuid; - extern gid_t currentgid; - extern pthread_rwlock_t rwlock; - - static - void - ugid_set(const uid_t newuid_, - const gid_t newgid_) - { - pthread_rwlock_rdlock(&rwlock); - - if((newuid_ == currentuid) && (newgid_ == currentgid)) - return; - - pthread_rwlock_unlock(&rwlock); - pthread_rwlock_wrlock(&rwlock); - - if((newuid_ == currentuid) && (newgid_ == currentgid)) - return; - - if(currentuid != 0) - { - ::seteuid(0); - ::setegid(0); - } - - if(newgid_) - { - ::setegid(newgid_); - initgroups(newuid_,newgid_); - } - - if(newuid_) - ::seteuid(newuid_); - - currentuid = newuid_; - currentgid = newgid_; - } - - struct Set - { - Set(const uid_t newuid_, - const gid_t newgid_) - { - ugid_set(newuid_,newgid_); - } - - Set(const fuse_req_ctx_t *ctx_) - : Set(ctx_->uid,ctx_->gid) - { - - } - - ~Set() - { - pthread_rwlock_unlock(&rwlock); - } - }; - - struct SetRootGuard - { - SetRootGuard() : - prevuid(currentuid), - prevgid(currentgid) - { - pthread_rwlock_unlock(&rwlock); - ugid_set(0,0); - } - - ~SetRootGuard() - { - pthread_rwlock_unlock(&rwlock); - ugid_set(prevuid,prevgid); - } - - const uid_t prevuid; - const gid_t prevgid; - }; -} diff --git a/src/ugid_rwlock.icpp b/src/ugid_rwlock.icpp deleted file mode 100644 index 6642102d..00000000 --- a/src/ugid_rwlock.icpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include -#include -#include -#include - -#include - -namespace ugid -{ - uid_t currentuid; - gid_t currentgid; - pthread_rwlock_t rwlock; - - void - init() - { - pthread_rwlockattr_t attr; - - pthread_rwlockattr_init(&attr); -# if defined PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP - pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); -# endif - - pthread_rwlock_init(&rwlock,&attr); - - currentuid = ::geteuid(); - currentgid = ::getegid(); - } -}