mirror of https://github.com/trapexit/mergerfs.git
Browse Source
Rework credential handling to support chroot & idmap
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.
53 changed files with 670 additions and 566 deletions
-
1Makefile
-
19libfuse/lib/fuse_lowlevel.cpp
-
102src/caps.cpp
-
6src/caps.hpp
-
4src/fs_attr_linux.icpp
-
75src/fs_clonepath.cpp
-
5src/fs_clonepath.hpp
-
2src/fs_is_rofs.hpp
-
50src/fs_mkdir_as.hpp
-
35src/fs_mkdir_as_root.hpp
-
48src/fs_mkdirat.hpp
-
50src/fs_mknod_as.hpp
-
2src/fs_movefile_and_open.cpp
-
50src/fs_open_as.hpp
-
48src/fs_symlink_as.hpp
-
3src/fuse_access.cpp
-
1src/fuse_chmod.cpp
-
3src/fuse_chown.cpp
-
33src/fuse_create.cpp
-
2src/fuse_getattr.cpp
-
2src/fuse_getxattr.cpp
-
4src/fuse_init.cpp
-
6src/fuse_ioctl.cpp
-
9src/fuse_link.cpp
-
2src/fuse_listxattr.cpp
-
39src/fuse_mkdir.cpp
-
39src/fuse_mknod.cpp
-
2src/fuse_open.cpp
-
4src/fuse_passthrough.hpp
-
2src/fuse_readdir_cor.cpp
-
10src/fuse_readdir_cosr.cpp
-
7src/fuse_readdir_cosr_getdents.icpp
-
7src/fuse_readdir_cosr_readdir.icpp
-
3src/fuse_readdir_seq.cpp
-
3src/fuse_readlink.cpp
-
2src/fuse_removexattr.cpp
-
12src/fuse_rename.cpp
-
1src/fuse_rmdir.cpp
-
2src/fuse_setxattr.cpp
-
1src/fuse_statfs.cpp
-
4src/fuse_statx_supported.icpp
-
64src/fuse_symlink.cpp
-
3src/fuse_truncate.cpp
-
3src/fuse_unlink.cpp
-
3src/fuse_utimens.cpp
-
2src/mergerfs.cpp
-
2src/policy_ff.cpp
-
33src/ugid.cpp
-
113src/ugid.hpp
-
128src/ugid_linux.hpp
-
34src/ugid_linux.icpp
-
106src/ugid_rwlock.hpp
-
45src/ugid_rwlock.icpp
@ -0,0 +1,102 @@ |
|||
#include "caps.hpp"
|
|||
|
|||
#if defined __linux__
|
|||
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <unistd.h>
|
|||
#include <sys/prctl.h>
|
|||
#include <sys/types.h>
|
|||
#include <sys/stat.h>
|
|||
#include <sys/syscall.h>
|
|||
#include <fcntl.h>
|
|||
#include <errno.h>
|
|||
#include <string.h>
|
|||
#include <grp.h>
|
|||
#include <linux/capability.h>
|
|||
#include <linux/securebits.h>
|
|||
|
|||
|
|||
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
|
|||
@ -0,0 +1,6 @@ |
|||
#pragma once
|
|||
|
|||
namespace caps |
|||
{ |
|||
int setup(); |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
#pragma once
|
|||
|
|||
#include "fs_mkdir.hpp"
|
|||
|
|||
|
|||
#if defined __linux__
|
|||
#include "ugid.hpp"
|
|||
|
|||
namespace fs |
|||
{ |
|||
template<typename T> |
|||
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<typename T> |
|||
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
|
|||
@ -1,35 +0,0 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2021, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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<typename T> |
|||
static |
|||
inline |
|||
int |
|||
mkdir_as_root(const T &path_, |
|||
const mode_t mode_) |
|||
{ |
|||
const ugid::SetRootGuard guard; |
|||
|
|||
return fs::mkdir(path_,mode_); |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
#pragma once
|
|||
|
|||
#include "to_neg_errno.hpp"
|
|||
#include "fs_path.hpp"
|
|||
|
|||
#include <fcntl.h>
|
|||
#include <sys/stat.h>
|
|||
|
|||
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_); |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
#pragma once
|
|||
|
|||
#include "fs_mknod.hpp"
|
|||
|
|||
|
|||
#if defined __linux__
|
|||
#include "ugid.hpp"
|
|||
|
|||
namespace fs |
|||
{ |
|||
template<typename T> |
|||
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<typename T> |
|||
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
|
|||
@ -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
|
|||
@ -0,0 +1,48 @@ |
|||
#pragma once
|
|||
|
|||
#include "fs_symlink.hpp"
|
|||
|
|||
|
|||
#if defined __linux__
|
|||
#include "ugid.hpp"
|
|||
|
|||
namespace fs |
|||
{ |
|||
template<typename T> |
|||
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<typename T> |
|||
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
|
|||
@ -1,33 +1,8 @@ |
|||
/*
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <unistd.h>
|
|||
|
|||
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; |
|||
} |
|||
@ -1,128 +0,0 @@ |
|||
/*
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <assert.h>
|
|||
#include <sys/stat.h>
|
|||
#include <sys/syscall.h>
|
|||
#include <sys/types.h>
|
|||
#include <unistd.h>
|
|||
|
|||
#include <grp.h>
|
|||
#include <pwd.h>
|
|||
|
|||
#include <map>
|
|||
#include <vector>
|
|||
|
|||
#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
|
|||
@ -1,34 +0,0 @@ |
|||
/* |
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <stdlib.h> |
|||
#include <sys/syscall.h> |
|||
#include <sys/types.h> |
|||
#include <unistd.h> |
|||
|
|||
#include <vector> |
|||
|
|||
namespace ugid |
|||
{ |
|||
thread_local uid_t currentuid = 0; |
|||
thread_local gid_t currentgid = 0; |
|||
thread_local bool initialized = false; |
|||
|
|||
void |
|||
init() |
|||
{ |
|||
} |
|||
} |
|||
@ -1,106 +0,0 @@ |
|||
/*
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <pthread.h>
|
|||
#include <sys/stat.h>
|
|||
#include <sys/types.h>
|
|||
#include <unistd.h>
|
|||
|
|||
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; |
|||
}; |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
/* |
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <pthread.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <unistd.h> |
|||
|
|||
#include <vector> |
|||
|
|||
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(); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue