mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-23 03:10:43 +08:00
Merge pull request #135 from trapexit/op-ugid
make changing credentials opportunistic + per thread setgroups cache
This commit is contained in:
commit
ad5380d69e
6
Makefile
6
Makefile
|
@ -65,6 +65,8 @@ FLOCK = $(shell $(CPPFIND) "fuse_fs_flock")
|
|||
READ_BUF = $(shell $(CPPFIND) "fuse_fs_read_buf")
|
||||
WRITE_BUF = $(shell $(CPPFIND) "fuse_fs_write_buf")
|
||||
|
||||
UGID_USE_RWLOCK = 0
|
||||
|
||||
OPTS = -O2
|
||||
SRC = $(wildcard src/*.cpp)
|
||||
OBJ = $(SRC:src/%.cpp=obj/%.o)
|
||||
|
@ -74,6 +76,7 @@ MANPAGE = $(TARGET).1
|
|||
FUSE_CFLAGS = $(shell $(PKGCONFIG) --cflags fuse)
|
||||
CFLAGS = -g -Wall \
|
||||
$(OPTS) \
|
||||
-Wno-unused-result \
|
||||
$(FUSE_CFLAGS) \
|
||||
-DFUSE_USE_VERSION=26 \
|
||||
-MMD \
|
||||
|
@ -81,7 +84,8 @@ CFLAGS = -g -Wall \
|
|||
-DFALLOCATE=$(FALLOCATE) \
|
||||
-DFLOCK=$(FLOCK) \
|
||||
-DREAD_BUF=$(READ_BUF) \
|
||||
-DWRITE_BUF=$(WRITE_BUF)
|
||||
-DWRITE_BUF=$(WRITE_BUF) \
|
||||
-DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK)
|
||||
LDFLAGS = $(shell $(PKGCONFIG) fuse --libs)
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
|
|
@ -74,10 +74,10 @@ namespace mergerfs
|
|||
access(const char *fusepath,
|
||||
int mask)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _access(config.access,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -74,10 +74,10 @@ namespace mergerfs
|
|||
chmod(const char *fusepath,
|
||||
mode_t mode)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _chmod(config.chmod,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -78,10 +78,10 @@ namespace mergerfs
|
|||
uid_t uid,
|
||||
gid_t gid)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _chown(config.chown,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
using mergerfs::Policy;
|
||||
using namespace mergerfs;
|
||||
|
||||
static
|
||||
int
|
||||
|
@ -69,7 +70,7 @@ _create(Policy::Func::Search searchFunc,
|
|||
|
||||
if(createpath[0] != existingpath[0])
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
const ugid::SetRootGuard ugidGuard;
|
||||
fs::clonepath(existingpath[0],createpath[0],dirname);
|
||||
}
|
||||
|
||||
|
@ -93,10 +94,10 @@ namespace mergerfs
|
|||
mode_t mode,
|
||||
fuse_file_info *fileinfo)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _create(config.getattr,
|
||||
config.create,
|
||||
|
|
|
@ -100,8 +100,8 @@ namespace mergerfs
|
|||
if(fusepath == config.controlfile)
|
||||
return _getattr_controlfile(*st);
|
||||
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _getattr(config.getattr,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -303,8 +303,8 @@ namespace mergerfs
|
|||
buf,
|
||||
count);
|
||||
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _getxattr(config.getxattr,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <fuse.h>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
|
@ -33,6 +34,8 @@ namespace mergerfs
|
|||
void *
|
||||
init(fuse_conn_info *conn)
|
||||
{
|
||||
ugid::init();
|
||||
|
||||
#ifdef FUSE_CAP_ASYNC_READ
|
||||
conn->want |= FUSE_CAP_ASYNC_READ;
|
||||
#endif
|
||||
|
|
|
@ -98,10 +98,10 @@ _ioctl_dir(const string &fusepath,
|
|||
const int cmd,
|
||||
void *data)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _ioctl_dir_base(config.getattr,
|
||||
config.srcmounts,
|
||||
|
|
11
src/link.cpp
11
src/link.cpp
|
@ -38,6 +38,7 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
using mergerfs::Policy;
|
||||
using namespace mergerfs;
|
||||
|
||||
static
|
||||
int
|
||||
|
@ -64,7 +65,7 @@ _single_link(Policy::Func::Search searchFunc,
|
|||
return -1;
|
||||
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
const ugid::SetRootGuard ugidGuard;
|
||||
fs::clonepath(foundpath[0],base,newpathdir);
|
||||
}
|
||||
|
||||
|
@ -110,10 +111,10 @@ namespace mergerfs
|
|||
link(const char *from,
|
||||
const char *to)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _link(config.getattr,
|
||||
config.link,
|
||||
|
|
|
@ -117,8 +117,8 @@ namespace mergerfs
|
|||
if(fusepath == config.controlfile)
|
||||
return _listxattr_controlfile(list,size);
|
||||
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _listxattr(config.listxattr,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
using mergerfs::Policy;
|
||||
using namespace mergerfs;
|
||||
|
||||
static
|
||||
int
|
||||
|
@ -72,7 +73,7 @@ _mkdir(Policy::Func::Search searchFunc,
|
|||
|
||||
if(createpath != existingpath[0])
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
const ugid::SetRootGuard ugidGuard;
|
||||
fs::clonepath(existingpath[0],createpath,dirname);
|
||||
}
|
||||
|
||||
|
@ -94,10 +95,10 @@ namespace mergerfs
|
|||
mkdir(const char *fusepath,
|
||||
mode_t mode)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _mkdir(config.getattr,
|
||||
config.mkdir,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using mergerfs::Policy;
|
||||
using namespace mergerfs;
|
||||
|
||||
static
|
||||
int
|
||||
|
@ -74,7 +74,7 @@ _mknod(Policy::Func::Search searchFunc,
|
|||
|
||||
if(createpath != existingpath[0])
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
const ugid::SetRootGuard ugidGuard;
|
||||
fs::clonepath(existingpath[0],createpath,dirname);
|
||||
}
|
||||
|
||||
|
@ -97,10 +97,10 @@ namespace mergerfs
|
|||
mode_t mode,
|
||||
dev_t rdev)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _mknod(config.getattr,
|
||||
config.mknod,
|
||||
|
|
|
@ -76,10 +76,10 @@ namespace mergerfs
|
|||
open(const char *fusepath,
|
||||
fuse_file_info *fileinfo)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _open(config.open,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -96,10 +96,10 @@ namespace mergerfs
|
|||
off_t offset,
|
||||
fuse_file_info *fi)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _readdir(config.srcmounts,
|
||||
fusepath,
|
||||
|
|
|
@ -75,10 +75,10 @@ namespace mergerfs
|
|||
char *buf,
|
||||
size_t size)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _readlink(config.readlink,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -87,8 +87,8 @@ namespace mergerfs
|
|||
if(fusepath == config.controlfile)
|
||||
return -ENOTSUP;
|
||||
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _removexattr(config.removexattr,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -130,10 +130,10 @@ namespace mergerfs
|
|||
rename(const char *oldpath,
|
||||
const char *newpath)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _rename(config.getattr,
|
||||
config.rename,
|
||||
|
|
|
@ -73,10 +73,10 @@ namespace mergerfs
|
|||
int
|
||||
rmdir(const char *fusepath)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readguard(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readguard(&config.srcmountslock);
|
||||
|
||||
return _rmdir(config.rmdir,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -323,8 +323,8 @@ namespace mergerfs
|
|||
flags);
|
||||
}
|
||||
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _setxattr(config.setxattr,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -124,10 +124,10 @@ namespace mergerfs
|
|||
statfs(const char *fusepath,
|
||||
struct statvfs *stat)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _statfs(config.srcmounts,
|
||||
*stat);
|
||||
|
|
|
@ -77,10 +77,10 @@ namespace mergerfs
|
|||
symlink(const char *oldpath,
|
||||
const char *newpath)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _symlink(config.symlink,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -77,10 +77,10 @@ namespace mergerfs
|
|||
truncate(const char *fusepath,
|
||||
off_t size)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _truncate(config.truncate,
|
||||
config.srcmounts,
|
||||
|
|
63
src/ugid.cpp
63
src/ugid.cpp
|
@ -22,10 +22,65 @@
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ugid.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined __linux__
|
||||
#elif defined __APPLE__
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
typedef std::vector<gid_t> gid_t_vector;
|
||||
typedef std::map<uid_t,gid_t_vector> gid_t_cache;
|
||||
|
||||
#if defined __linux__ and UGID_USE_RWLOCK == 0
|
||||
#include "ugid_linux.ipp"
|
||||
#else
|
||||
pthread_mutex_t mergerfs::ugid::SetResetGuard::lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#include "ugid_rwlock.ipp"
|
||||
#endif
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
namespace ugid
|
||||
{
|
||||
static
|
||||
inline
|
||||
void
|
||||
prime_cache(const uid_t uid,
|
||||
const gid_t gid,
|
||||
gid_t_vector &gidlist)
|
||||
{
|
||||
int rv;
|
||||
char buf[4096];
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdrv;
|
||||
|
||||
rv = getpwuid_r(uid,&pwd,buf,sizeof(buf),&pwdrv);
|
||||
if(pwdrv != NULL && rv == 0)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
rv = ::getgrouplist(pwd.pw_name,gid,NULL,&count);
|
||||
gidlist.resize(count);
|
||||
rv = ::getgrouplist(pwd.pw_name,gid,&gidlist[0],&count);
|
||||
if(rv == -1)
|
||||
gidlist.resize(1,gid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
initgroups(const uid_t uid,
|
||||
const gid_t gid)
|
||||
{
|
||||
static __thread gid_t_cache cache;
|
||||
|
||||
gid_t_vector &gidlist = cache[uid];
|
||||
if(gidlist.empty())
|
||||
prime_cache(uid,gid,gidlist);
|
||||
|
||||
setgroups(gidlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
src/ugid.hpp
23
src/ugid.hpp
|
@ -25,12 +25,27 @@
|
|||
#ifndef __UGID_HPP__
|
||||
#define __UGID_HPP__
|
||||
|
||||
#if defined __linux__
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<gid_t> gid_t_vector;
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
namespace ugid
|
||||
{
|
||||
void init();
|
||||
void initgroups(const uid_t uid, const gid_t gid);
|
||||
void setgroups(const gid_t_vector &gidlist);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined __linux__ and UGID_USE_RWLOCK == 0
|
||||
#include "ugid_linux.hpp"
|
||||
#elif defined __APPLE__
|
||||
#include "ugid_osx.hpp"
|
||||
#else
|
||||
#include "ugid_mutex.hpp"
|
||||
#include "ugid_rwlock.hpp"
|
||||
#endif
|
||||
|
||||
#endif /* __UGID_HPP__ */
|
||||
|
|
|
@ -27,38 +27,71 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
namespace ugid
|
||||
{
|
||||
struct SetResetGuard
|
||||
extern __thread uid_t currentuid;
|
||||
extern __thread gid_t currentgid;
|
||||
extern __thread bool initialized;
|
||||
|
||||
struct Set
|
||||
{
|
||||
SetResetGuard(const uid_t _newuid,
|
||||
const gid_t _newgid)
|
||||
Set(const uid_t newuid,
|
||||
const gid_t newgid)
|
||||
{
|
||||
olduid = ::syscall(SYS_geteuid);
|
||||
oldgid = ::syscall(SYS_getegid);
|
||||
newuid = _newuid;
|
||||
newgid = _newgid;
|
||||
if(!initialized)
|
||||
{
|
||||
currentuid = ::syscall(SYS_geteuid);
|
||||
currentgid = ::syscall(SYS_getegid);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if(newgid != oldgid)
|
||||
::syscall(SYS_setregid,-1,newgid);
|
||||
if(newuid != olduid)
|
||||
if(newuid == currentuid && newgid == currentgid)
|
||||
return;
|
||||
|
||||
if(currentuid != 0)
|
||||
{
|
||||
::syscall(SYS_setreuid,-1,0);
|
||||
::syscall(SYS_setregid,-1,0);
|
||||
}
|
||||
|
||||
if(newgid)
|
||||
{
|
||||
::syscall(SYS_setregid,-1,newgid);
|
||||
initgroups(newuid,newgid);
|
||||
}
|
||||
|
||||
if(newuid)
|
||||
::syscall(SYS_setreuid,-1,newuid);
|
||||
}
|
||||
|
||||
~SetResetGuard()
|
||||
currentuid = newuid;
|
||||
currentgid = newgid;
|
||||
}
|
||||
};
|
||||
|
||||
struct SetRootGuard
|
||||
{
|
||||
SetRootGuard() :
|
||||
prevuid(currentuid),
|
||||
prevgid(currentgid)
|
||||
{
|
||||
if(olduid != newuid)
|
||||
::syscall(SYS_setreuid,-1,olduid);
|
||||
if(oldgid != newgid)
|
||||
::syscall(SYS_setregid,-1,oldgid);
|
||||
Set(0,0);
|
||||
}
|
||||
|
||||
uid_t olduid;
|
||||
gid_t oldgid;
|
||||
uid_t newuid;
|
||||
gid_t newgid;
|
||||
~SetRootGuard()
|
||||
{
|
||||
Set(prevuid,prevgid);
|
||||
}
|
||||
|
||||
const uid_t prevuid;
|
||||
const gid_t prevgid;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,36 +22,32 @@
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<gid_t> gid_t_vector;
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
namespace ugid
|
||||
{
|
||||
struct SetResetGuard
|
||||
__thread uid_t currentuid = 0;
|
||||
__thread gid_t currentgid = 0;
|
||||
__thread bool initialized = false;
|
||||
|
||||
void
|
||||
init()
|
||||
{
|
||||
SetResetGuard(const uid_t _newuid,
|
||||
const gid_t _newgid)
|
||||
{
|
||||
pthread_getugid_np(&olduid,&oldgid);
|
||||
newuid = _newuid;
|
||||
newgid = _newgid;
|
||||
}
|
||||
|
||||
if(newgid != oldgid || newuid != olduid)
|
||||
pthread_setugid_np(newuid,newgid);
|
||||
}
|
||||
|
||||
~SetResetGuard()
|
||||
{
|
||||
if(newgid != oldgid || newuid != olduid)
|
||||
pthread_setugid_np(newuid,newgid);
|
||||
}
|
||||
|
||||
uid_t olduid;
|
||||
gid_t oldgid;
|
||||
uid_t newuid;
|
||||
gid_t newgid;
|
||||
};
|
||||
int
|
||||
setgroups(const gid_t_vector &gidlist)
|
||||
{
|
||||
return ::syscall(SYS_setgroups,gidlist.size(),&gidlist[0]);
|
||||
}
|
||||
}
|
||||
}
|
107
src/ugid_rwlock.hpp
Normal file
107
src/ugid_rwlock.hpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
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()
|
||||
{
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -22,47 +22,43 @@
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<gid_t> gid_t_vector;
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
namespace ugid
|
||||
{
|
||||
struct SetResetGuard
|
||||
uid_t currentuid;
|
||||
gid_t currentgid;
|
||||
pthread_rwlock_t rwlock;
|
||||
|
||||
void
|
||||
init()
|
||||
{
|
||||
SetResetGuard(const uid_t _newuid,
|
||||
const gid_t _newgid)
|
||||
{
|
||||
pthread_mutex_lock(&lock);
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
olduid = ::geteuid();
|
||||
oldgid = ::getegid();
|
||||
newuid = _newuid;
|
||||
newgid = _newgid;
|
||||
pthread_rwlockattr_init(&attr);
|
||||
# if defined PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
|
||||
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
|
||||
# endif
|
||||
|
||||
if(newgid != oldgid)
|
||||
setegid(newgid);
|
||||
if(newuid != olduid)
|
||||
seteuid(newuid);
|
||||
}
|
||||
pthread_rwlock_init(&rwlock,&attr);
|
||||
|
||||
~SetResetGuard()
|
||||
{
|
||||
if(olduid != newuid)
|
||||
seteuid(newuid);
|
||||
if(oldgid != newgid)
|
||||
setegid(newgid);
|
||||
}
|
||||
currentuid = ::geteuid();
|
||||
currentgid = ::getegid();
|
||||
}
|
||||
|
||||
uid_t olduid;
|
||||
gid_t oldgid;
|
||||
uid_t newuid;
|
||||
gid_t newgid;
|
||||
|
||||
static pthread_mutex_t lock;
|
||||
};
|
||||
int
|
||||
setgroups(const gid_t_vector &gidlist)
|
||||
{
|
||||
return ::setgroups(gidlist.size(),&gidlist[0]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -74,10 +74,10 @@ namespace mergerfs
|
|||
int
|
||||
unlink(const char *fusepath)
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _unlink(config.unlink,
|
||||
config.srcmounts,
|
||||
|
|
|
@ -77,10 +77,10 @@ namespace mergerfs
|
|||
utimens(const char *fusepath,
|
||||
const timespec ts[2])
|
||||
{
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
const fuse_context *fc = fuse_get_context();
|
||||
const Config &config = Config::get(fc);
|
||||
const ugid::Set ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _utimens(config.utimens,
|
||||
config.srcmounts,
|
||||
|
|
Loading…
Reference in New Issue
Block a user