From f48c16d162edc622c4dbb681f6f9419685e4b0e5 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Wed, 7 Mar 2018 18:24:47 -0500 Subject: [PATCH] stop clonepath at base directory. fixes #467 --- src/create.cpp | 21 +++----- src/fs_clonepath.cpp | 29 +++++++++++ src/fs_clonepath.hpp | 7 +++ src/link.cpp | 24 ++++----- src/mkdir.cpp | 23 ++++----- src/mknod.cpp | 23 ++++----- src/rename.cpp | 59 ++++++++------------- src/symlink.cpp | 24 ++++----- src/ugid.cpp | 15 +++--- src/ugid.hpp | 9 ++-- src/ugid_linux.hpp | 112 ++++++++++++++++++++-------------------- src/ugid_linux.icpp | 17 +++---- src/ugid_rwlock.hpp | 119 +++++++++++++++++++++---------------------- src/ugid_rwlock.icpp | 29 +++++------ 14 files changed, 241 insertions(+), 270 deletions(-) diff --git a/src/create.cpp b/src/create.cpp index 5ea71e8f..fed2f5f2 100644 --- a/src/create.cpp +++ b/src/create.cpp @@ -34,7 +34,6 @@ using std::vector; using namespace mergerfs; static -inline int _create_core(const string &fullpath, mode_t mode, @@ -49,10 +48,8 @@ _create_core(const string &fullpath, static int -_create_core(const string &existingpath, - const string &createpath, +_create_core(const string &createpath, const char *fusepath, - const char *fusedirpath, const mode_t mode, const mode_t umask, const int flags, @@ -61,14 +58,6 @@ _create_core(const string &existingpath, int rv; string fullpath; - if(createpath != existingpath) - { - const ugid::SetRootGuard ugidGuard; - rv = fs::clonepath(existingpath,createpath,fusedirpath); - if(rv == -1) - return -errno; - } - fs::path::make(&createpath,fusepath,fullpath); rv = _create_core(fullpath,mode,umask,flags); @@ -111,8 +100,12 @@ _create(Policy::Func::Search searchFunc, if(rv == -1) return -errno; - return _create_core(*existingpaths[0],*createpaths[0], - fusepath,fusedirpathcstr, + rv = fs::clonepath_as_root(*existingpaths[0],*createpaths[0],fusedirpath); + if(rv == -1) + return -errno; + + return _create_core(*createpaths[0], + fusepath, mode,umask,flags,fh); } diff --git a/src/fs_clonepath.cpp b/src/fs_clonepath.cpp index f4fb32ce..5936f0fb 100644 --- a/src/fs_clonepath.cpp +++ b/src/fs_clonepath.cpp @@ -26,6 +26,7 @@ #include "fs_clonepath.hpp" #include "fs_path.hpp" #include "fs_xattr.hpp" +#include "ugid.hpp" using std::string; @@ -59,6 +60,9 @@ namespace fs string frompath; string dirname; + if((relative == NULL) || (relative[0] == '\0')) + return 0; + dirname = relative; fs::path::dirname(dirname); if(!dirname.empty()) @@ -114,4 +118,29 @@ namespace fs { return fs::clonepath(from,to,relative.c_str()); } + + int + clonepath_as_root(const string &from, + const string &to, + const char *relative) + { + if((relative == NULL) || (relative[0] == '\0')) + return 0; + if(from == to) + return 0; + + { + const ugid::SetRootGuard ugidGuard; + + return fs::clonepath(from,to,relative); + } + } + + int + clonepath_as_root(const std::string &from, + const std::string &to, + const std::string &relative) + { + return fs::clonepath_as_root(from,to,relative.c_str()); + } } diff --git a/src/fs_clonepath.hpp b/src/fs_clonepath.hpp index be9f4aaa..e98e7316 100644 --- a/src/fs_clonepath.hpp +++ b/src/fs_clonepath.hpp @@ -26,4 +26,11 @@ namespace fs int clonepath(const std::string &from, const std::string &to, const std::string &relative); + + int clonepath_as_root(const std::string &from, + const std::string &to, + const char *relative); + int clonepath_as_root(const std::string &from, + const std::string &to, + const std::string &relative); } diff --git a/src/link.cpp b/src/link.cpp index dd3ab49e..2c492124 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -39,21 +39,12 @@ _link_create_path_core(const string &oldbasepath, const string &newbasepath, const char *oldfusepath, const char *newfusepath, - const string &newfusedirpath, const int error) { int rv; string oldfullpath; string newfullpath; - if(oldbasepath != newbasepath) - { - const ugid::SetRootGuard ugidGuard; - rv = fs::clonepath(newbasepath,oldbasepath,newfusedirpath); - if(rv == -1) - return errno; - } - fs::path::make(&oldbasepath,oldfusepath,oldfullpath); fs::path::make(&oldbasepath,newfusepath,newfullpath); @@ -70,15 +61,19 @@ _link_create_path_loop(const vector &oldbasepaths, const char *newfusepath, const string &newfusedirpath) { + int rv; int error; error = -1; for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) { - error = _link_create_path_core(*oldbasepaths[i],newbasepath, - oldfusepath,newfusepath, - newfusedirpath, - error); + rv = fs::clonepath_as_root(newbasepath,*oldbasepaths[i],newfusedirpath); + if(rv == -1) + error = error::calc(rv,error,errno); + else + error = _link_create_path_core(*oldbasepaths[i],newbasepath, + oldfusepath,newfusepath, + error); } return -error; @@ -143,8 +138,7 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc, if(rv == -1) return -1; - const ugid::SetRootGuard ugidGuard; - return fs::clonepath(*newbasepath[0],oldbasepath,newfusedirpathcstr); + return fs::clonepath_as_root(*newbasepath[0],oldbasepath,newfusedirpathcstr); } static diff --git a/src/mkdir.cpp b/src/mkdir.cpp index c054b321..355913df 100644 --- a/src/mkdir.cpp +++ b/src/mkdir.cpp @@ -34,7 +34,6 @@ using std::vector; using namespace mergerfs; static -inline int _mkdir_core(const string &fullpath, mode_t mode, @@ -48,10 +47,8 @@ _mkdir_core(const string &fullpath, static int -_mkdir_loop_core(const string &existingpath, - const string &createpath, +_mkdir_loop_core(const string &createpath, const char *fusepath, - const char *fusedirpath, const mode_t mode, const mode_t umask, const int error) @@ -59,14 +56,6 @@ _mkdir_loop_core(const string &existingpath, int rv; string fullpath; - if(createpath != existingpath) - { - const ugid::SetRootGuard ugidGuard; - rv = fs::clonepath(existingpath,createpath,fusedirpath); - if(rv == -1) - return errno; - } - fs::path::make(&createpath,fusepath,fullpath); rv = _mkdir_core(fullpath,mode,umask); @@ -83,13 +72,19 @@ _mkdir_loop(const string &existingpath, const mode_t mode, const mode_t umask) { + int rv; int error; error = -1; for(size_t i = 0, ei = createpaths.size(); i != ei; i++) { - error = _mkdir_loop_core(existingpath,*createpaths[i], - fusepath,fusedirpath,mode,umask,error); + rv = fs::clonepath_as_root(existingpath,*createpaths[i],fusedirpath); + if(rv == -1) + error = error::calc(rv,error,errno); + else + error = _mkdir_loop_core(*createpaths[i], + fusepath, + mode,umask,error); } return -error; diff --git a/src/mknod.cpp b/src/mknod.cpp index b5033c1f..9f51c43a 100644 --- a/src/mknod.cpp +++ b/src/mknod.cpp @@ -49,10 +49,8 @@ _mknod_core(const string &fullpath, static int -_mknod_loop_core(const string &existingpath, - const string &createpath, +_mknod_loop_core(const string &createpath, const char *fusepath, - const char *fusedirpath, const mode_t mode, const mode_t umask, const dev_t dev, @@ -61,14 +59,6 @@ _mknod_loop_core(const string &existingpath, int rv; string fullpath; - if(createpath != existingpath) - { - const ugid::SetRootGuard ugidGuard; - rv = fs::clonepath(existingpath,createpath,fusedirpath); - if(rv == -1) - return -1; - } - fs::path::make(&createpath,fusepath,fullpath); rv = _mknod_core(fullpath,mode,umask,dev); @@ -86,14 +76,19 @@ _mknod_loop(const string &existingpath, const mode_t umask, const dev_t dev) { + int rv; int error; error = -1; for(size_t i = 0, ei = createpaths.size(); i != ei; i++) { - error = _mknod_loop_core(existingpath,*createpaths[i], - fusepath,fusedirpath, - mode,umask,dev,error); + rv = fs::clonepath_as_root(existingpath,*createpaths[i],fusedirpath); + if(rv == -1) + error = error::calc(rv,error,errno); + else + error = _mknod_loop_core(*createpaths[i], + fusepath, + mode,umask,dev,error); } return -error; diff --git a/src/rename.cpp b/src/rename.cpp index b65d464e..f7ab4bf0 100644 --- a/src/rename.cpp +++ b/src/rename.cpp @@ -27,7 +27,6 @@ #include "fs_path.hpp" #include "rv.hpp" #include "rwlock.hpp" -#include "success_fail.hpp" #include "ugid.hpp" using std::string; @@ -57,27 +56,6 @@ _remove(const vector &toremove) fs::remove(toremove[i]); } -static -int -_rename(const std::string &oldbasepath, - const std::string &oldfullpath, - const std::string &newbasepath, - const std::string &newfusedirpath, - const std::string &newfullpath) -{ - int rv; - - if(oldbasepath != newbasepath) - { - const ugid::SetRootGuard guard; - rv = fs::clonepath(newbasepath,oldbasepath,newfusedirpath); - if(rv == -1) - return -1; - } - - return fs::rename(oldfullpath,newfullpath); -} - static void _rename_create_path_core(const vector &oldbasepaths, @@ -94,21 +72,26 @@ _rename_create_path_core(const vector &oldbasepaths, string oldfullpath; string newfullpath; - fs::path::make(&oldbasepath,newfusepath,newfullpath); - ismember = member(oldbasepaths,oldbasepath); if(ismember) { - fs::path::make(&oldbasepath,oldfusepath,oldfullpath); + rv = fs::clonepath_as_root(newbasepath,oldbasepath,newfusedirpath); + if(rv != -1) + { + fs::path::make(&oldbasepath,oldfusepath,oldfullpath); + fs::path::make(&oldbasepath,newfusepath,newfullpath); + + rv = fs::rename(oldfullpath,newfullpath); + } - rv = _rename(oldbasepath,oldfullpath, - newbasepath,newfusedirpath,newfullpath); error = error::calc(rv,error,errno); - if(RENAME_FAILED(rv)) + if(rv == -1) tounlink.push_back(oldfullpath); } else { + fs::path::make(&oldbasepath,newfusepath,newfullpath); + tounlink.push_back(newfullpath); } } @@ -138,7 +121,7 @@ _rename_create_path(Policy::Func::Search searchFunc, if(POLICY_FAILED(rv)) return -errno; - error = RENAME_FAIL; + error = -1; for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { const string &oldbasepath = srcmounts[i]; @@ -150,7 +133,8 @@ _rename_create_path(Policy::Func::Search searchFunc, error,toremove); } - if(RENAME_SUCCEEDED(error)) + + if(error == 0) _remove(toremove); return -error; @@ -169,12 +153,9 @@ _clonepath(Policy::Func::Search searchFunc, rv = searchFunc(srcmounts,fusedirpath.c_str(),minfreespace,srcbasepath); if(POLICY_FAILED(rv)) - return rv; + return -errno; - { - const ugid::SetRootGuard ugidGuard; - fs::clonepath(*srcbasepath[0],dstbasepath,fusedirpath); - } + fs::clonepath_as_root(*srcbasepath[0],dstbasepath,fusedirpath); return POLICY_SUCCESS; } @@ -232,7 +213,7 @@ _rename_preserve_path_core(Policy::Func::Search searchFunc, fs::path::make(&oldbasepath,oldfusepath,oldfullpath); rv = fs::rename(oldfullpath,newfullpath); - if(RENAME_FAILED_WITH(rv,ENOENT)) + if((rv == -1) && (errno == ENOENT)) { rv = _clonepath_if_would_create(searchFunc,createFunc, srcmounts,minfreespace, @@ -242,7 +223,7 @@ _rename_preserve_path_core(Policy::Func::Search searchFunc, } error = error::calc(rv,error,errno); - if(RENAME_FAILED(rv)) + if(rv == -1) toremove.push_back(oldfullpath); } else @@ -270,7 +251,7 @@ _rename_preserve_path(Policy::Func::Search searchFunc, if(POLICY_FAILED(rv)) return -errno; - error = RENAME_FAIL; + error = -1; for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { const string &oldbasepath = srcmounts[i]; @@ -282,7 +263,7 @@ _rename_preserve_path(Policy::Func::Search searchFunc, error,toremove); } - if(RENAME_SUCCEEDED(error)) + if(error == 0) _remove(toremove); return -error; diff --git a/src/symlink.cpp b/src/symlink.cpp index 5c1434f3..cc49faf8 100644 --- a/src/symlink.cpp +++ b/src/symlink.cpp @@ -36,24 +36,14 @@ using namespace mergerfs; static int -_symlink_loop_core(const string &existingpath, - const string &newbasepath, +_symlink_loop_core(const string &newbasepath, const char *oldpath, const char *newpath, - const char *newdirpath, const int error) { int rv; string fullnewpath; - if(newbasepath != existingpath) - { - const ugid::SetRootGuard ugidGuard; - rv = fs::clonepath(existingpath,newbasepath,newdirpath); - if(rv == -1) - return -1; - } - fs::path::make(&newbasepath,newpath,fullnewpath); rv = fs::symlink(oldpath,fullnewpath); @@ -69,14 +59,20 @@ _symlink_loop(const string &existingpath, const char *newpath, const char *newdirpath) { + int rv; int error; error = -1; for(size_t i = 0, ei = newbasepaths.size(); i != ei; i++) { - error = _symlink_loop_core(existingpath,*newbasepaths[i], - oldpath,newpath,newdirpath, - error); + rv = fs::clonepath_as_root(existingpath,*newbasepaths[i],newdirpath); + if(rv == -1) + error = error::calc(rv,error,errno); + else + error = _symlink_loop_core(*newbasepaths[i], + oldpath, + newpath, + error); } return -error; diff --git a/src/ugid.cpp b/src/ugid.cpp index 7448e9c0..70ce91ad 100644 --- a/src/ugid.cpp +++ b/src/ugid.cpp @@ -22,17 +22,14 @@ #include "ugid_rwlock.icpp" #endif -namespace mergerfs +namespace ugid { - namespace ugid + void + initgroups(const uid_t uid, + const gid_t gid) { - void - initgroups(const uid_t uid, - const gid_t gid) - { - static __thread gid_t_cache cache = {0}; + static __thread gid_t_cache cache = {0}; - cache.initgroups(uid,gid); - } + cache.initgroups(uid,gid); } } diff --git a/src/ugid.hpp b/src/ugid.hpp index 2860d7b5..9edde0c6 100644 --- a/src/ugid.hpp +++ b/src/ugid.hpp @@ -21,13 +21,10 @@ #include -namespace mergerfs +namespace ugid { - namespace ugid - { - void init(); - void initgroups(const uid_t uid, const gid_t gid); - } + void init(); + void initgroups(const uid_t uid, const gid_t gid); } #if defined __linux__ and UGID_USE_RWLOCK == 0 diff --git a/src/ugid_linux.hpp b/src/ugid_linux.hpp index 63b34c1b..06a872a4 100644 --- a/src/ugid_linux.hpp +++ b/src/ugid_linux.hpp @@ -51,68 +51,64 @@ #define GETEGID() (::syscall(SYS_getegid)) #endif - -namespace mergerfs +namespace ugid { - namespace ugid - { - extern __thread uid_t currentuid; - extern __thread gid_t currentgid; - extern __thread bool initialized; + extern __thread uid_t currentuid; + extern __thread gid_t currentgid; + extern __thread bool initialized; - struct Set + struct Set + { + Set(const uid_t newuid, + const gid_t newgid) { - Set(const uid_t newuid, - const gid_t newgid) - { - 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); - initgroups(newuid,newgid); - } - - if(newuid) - SETREUID(-1,newuid); - - currentuid = newuid; - currentgid = newgid; - } - }; - - struct SetRootGuard + 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); + initgroups(newuid,newgid); + } + + if(newuid) + SETREUID(-1,newuid); + + currentuid = newuid; + currentgid = newgid; + } + }; + + struct SetRootGuard + { + SetRootGuard() : + prevuid(currentuid), + prevgid(currentgid) { - SetRootGuard() : - prevuid(currentuid), - prevgid(currentgid) - { - Set(0,0); - } - - ~SetRootGuard() - { - Set(prevuid,prevgid); - } - - const uid_t prevuid; - const gid_t prevgid; - }; - } + Set(0,0); + } + + ~SetRootGuard() + { + Set(prevuid,prevgid); + } + + const uid_t prevuid; + const gid_t prevgid; + }; } #undef SETREUID diff --git a/src/ugid_linux.icpp b/src/ugid_linux.icpp index 1ad08048..81889f9b 100644 --- a/src/ugid_linux.icpp +++ b/src/ugid_linux.icpp @@ -21,17 +21,14 @@ #include -namespace mergerfs +namespace ugid { - namespace ugid - { - __thread uid_t currentuid = 0; - __thread gid_t currentgid = 0; - __thread bool initialized = false; + __thread uid_t currentuid = 0; + __thread gid_t currentgid = 0; + __thread bool initialized = false; - void - init() - { - } + void + init() + { } } diff --git a/src/ugid_rwlock.hpp b/src/ugid_rwlock.hpp index 7ea91f01..9ac08f83 100644 --- a/src/ugid_rwlock.hpp +++ b/src/ugid_rwlock.hpp @@ -21,81 +21,78 @@ #include #include -namespace mergerfs +namespace ugid { - 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) { - 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); + pthread_rwlock_rdlock(&rwlock); - if(newuid == currentuid && newgid == currentgid) - return; + if(newuid == currentuid && newgid == currentgid) + return; - pthread_rwlock_unlock(&rwlock); - pthread_rwlock_wrlock(&rwlock); + pthread_rwlock_unlock(&rwlock); + pthread_rwlock_wrlock(&rwlock); - if(newuid == currentuid && newgid == currentgid) - return; + if(newuid == currentuid && newgid == currentgid) + return; - if(currentuid != 0) - { - ::seteuid(0); - ::setegid(0); - } + if(currentuid != 0) + { + ::seteuid(0); + ::setegid(0); + } - if(newgid) - { - ::setegid(newgid); - initgroups(newuid,newgid); - } + if(newgid) + { + ::setegid(newgid); + initgroups(newuid,newgid); + } - if(newuid) - ::seteuid(newuid); + if(newuid) + ::seteuid(newuid); - currentuid = newuid; - currentgid = newgid; - } + currentuid = newuid; + currentgid = newgid; + } - struct Set + struct Set + { + Set(const uid_t newuid, + const gid_t newgid) { - Set(const uid_t newuid, - const gid_t newgid) - { - ugid_set(newuid,newgid); - } + ugid_set(newuid,newgid); + } - ~Set() - { - pthread_rwlock_unlock(&rwlock); - } - }; + ~Set() + { + pthread_rwlock_unlock(&rwlock); + } + }; - struct SetRootGuard + struct SetRootGuard + { + SetRootGuard() : + prevuid(currentuid), + prevgid(currentgid) { - SetRootGuard() : - prevuid(currentuid), - prevgid(currentgid) - { - pthread_rwlock_unlock(&rwlock); - ugid_set(0,0); - } + pthread_rwlock_unlock(&rwlock); + ugid_set(0,0); + } - ~SetRootGuard() - { - pthread_rwlock_unlock(&rwlock); - ugid_set(prevuid,prevgid); - } + ~SetRootGuard() + { + pthread_rwlock_unlock(&rwlock); + ugid_set(prevuid,prevgid); + } - const uid_t prevuid; - const gid_t prevgid; - }; - } + const uid_t prevuid; + const gid_t prevgid; + }; } diff --git a/src/ugid_rwlock.icpp b/src/ugid_rwlock.icpp index 666b2048..6642102d 100644 --- a/src/ugid_rwlock.icpp +++ b/src/ugid_rwlock.icpp @@ -21,28 +21,25 @@ #include -namespace mergerfs +namespace ugid { - namespace ugid - { - uid_t currentuid; - gid_t currentgid; - pthread_rwlock_t rwlock; + uid_t currentuid; + gid_t currentgid; + pthread_rwlock_t rwlock; - void - init() - { - pthread_rwlockattr_t attr; + void + init() + { + pthread_rwlockattr_t attr; - pthread_rwlockattr_init(&attr); + pthread_rwlockattr_init(&attr); # if defined PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP - pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); # endif - pthread_rwlock_init(&rwlock,&attr); + pthread_rwlock_init(&rwlock,&attr); - currentuid = ::geteuid(); - currentgid = ::getegid(); - } + currentuid = ::geteuid(); + currentgid = ::getegid(); } }