[Reproducible-commits] [disorderfs] 03/06: Implement multi-user mode
Andrew Ayer
agwa at andrewayer.name
Tue Sep 22 03:34:19 UTC 2015
This is an automated email from the git hooks/post-receive script.
agwa-guest pushed a commit to branch master
in repository disorderfs.
commit 79ee0bd7374e73c35ef58dafe9475fdb61a61ddc
Author: Andrew Ayer <agwa at andrewayer.name>
Date: Mon Sep 21 20:03:38 2015 -0700
Implement multi-user mode
---
disorderfs.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
diff --git a/disorderfs.cpp b/disorderfs.cpp
index 62968a8..16cc4f4 100644
--- a/disorderfs.cpp
+++ b/disorderfs.cpp
@@ -35,6 +35,7 @@
#include <algorithm>
#include <attr/xattr.h>
#include <sys/types.h>
+#include <sys/syscall.h>
#include <stddef.h>
#define DISORDERFS_VERSION "0.2.0"
@@ -43,6 +44,7 @@ namespace {
std::vector<std::string> bare_arguments;
std::string root;
struct Disorderfs_config {
+ bool multi_user{false};
bool shuffle_dirents{false};
bool reverse_dirents{true};
unsigned int pad_blocks{1};
@@ -52,6 +54,97 @@ namespace {
int wrap (int retval) { return retval == -1 ? -errno : 0; }
using Dirents = std::vector<std::string>;
+ int thread_seteuid (uid_t euid)
+ {
+#ifdef SYS_setresuid32
+ return syscall(SYS_setresuid32, static_cast<uid_t>(-1), euid, static_cast<uid_t>(-1));
+#else
+ return syscall(SYS_setresuid, static_cast<uid_t>(-1), euid, static_cast<uid_t>(-1));
+#endif
+ }
+ int thread_setegid (gid_t egid)
+ {
+#ifdef SYS_setresgid32
+ return syscall(SYS_setresgid32, static_cast<gid_t>(-1), egid, static_cast<gid_t>(-1));
+#else
+ return syscall(SYS_setresgid, static_cast<gid_t>(-1), egid, static_cast<gid_t>(-1));
+#endif
+ }
+ int thread_setgroups (size_t size, const gid_t* list)
+ {
+#ifdef SYS_setgroups32
+ return syscall(SYS_setgroups32, size, list);
+#else
+ return syscall(SYS_setgroups, size, list);
+#endif
+ }
+
+ std::vector<gid_t> get_fuse_groups ()
+ {
+ long ngroups_max = sysconf(_SC_NGROUPS_MAX);
+ if (ngroups_max < 0) {
+ ngroups_max = 65536;
+ }
+ std::vector<gid_t> groups(ngroups_max + 1);
+ int ngroups = fuse_getgroups(groups.size(), groups.data());
+ if (ngroups < 0) {
+ std::perror("fuse_getgroups");
+ groups.clear();
+ } else if (static_cast<unsigned int>(ngroups) < groups.size()) {
+ groups.resize(ngroups);
+ }
+ return groups;
+ }
+
+ void drop_privileges ()
+ {
+ const std::vector<gid_t> groups(get_fuse_groups());
+ if (thread_setgroups(groups.size(), groups.data()) == -1) {
+ std::perror("setgroups");
+ std::abort();
+ }
+ if (thread_setegid(fuse_get_context()->gid) == -1) {
+ std::perror("setegid");
+ std::abort();
+ }
+ if (thread_seteuid(fuse_get_context()->uid) == -1) {
+ std::perror("seteuid");
+ std::abort();
+ }
+ }
+
+ void restore_privileges ()
+ {
+ const std::vector<gid_t> groups;
+ if (thread_seteuid(0) == -1) {
+ std::perror("seteuid()");
+ std::abort();
+ }
+ if (thread_setegid(0) == -1) {
+ std::perror("setegid(0)");
+ std::abort();
+ }
+ if (thread_setgroups(groups.size(), groups.data()) == -1) {
+ std::perror("setgroups(0)");
+ std::abort();
+ }
+ }
+
+ struct Guard {
+ Guard ()
+ {
+ if (config.multi_user) {
+ drop_privileges();
+ }
+ }
+ ~Guard ()
+ {
+ if (config.multi_user) {
+ restore_privileges();
+ }
+ }
+ };
+
struct fuse_operations disorderfs_fuse_operations;
enum {
KEY_HELP,
@@ -63,6 +156,8 @@ namespace {
DISORDERFS_OPT("--shuffle-dirents=yes", shuffle_dirents, true),
DISORDERFS_OPT("--reverse-dirents=no", reverse_dirents, false),
DISORDERFS_OPT("--reverse-dirents=yes", reverse_dirents, true),
+ DISORDERFS_OPT("--multi-user=no", multi_user, false),
+ DISORDERFS_OPT("--multi-user=yes", multi_user, true),
DISORDERFS_OPT("--pad-blocks=%i", pad_blocks, 0),
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
@@ -86,6 +181,7 @@ namespace {
std::clog << " --shuffle-dirents=yes|no randomly shuffle dirents? (default: no)" << std::endl;
std::clog << " --reverse-dirents=yes|no reverse dirent order? (default: yes)" << std::endl;
std::clog << " --pad-blocks=N add N to st_blocks (default: 1)" << std::endl;
+ std::clog << " --multi-user=yes|no allow multiple users to access overlay (requires root; default: no)" << std::endl;
std::clog << std::endl;
fuse_opt_add_arg(outargs, "-ho");
fuse_main(outargs->argc, outargs->argv, &disorderfs_fuse_operations, NULL);
@@ -110,6 +206,7 @@ int main (int argc, char** argv)
std::memset(&disorderfs_fuse_operations, '\0', sizeof(disorderfs_fuse_operations));
disorderfs_fuse_operations.getattr = [] (const char* path, struct stat* st) -> int {
+ Guard g;
if (lstat((root + path).c_str(), st) == -1) {
return -errno;
}
@@ -117,6 +214,7 @@ int main (int argc, char** argv)
return 0;
};
disorderfs_fuse_operations.readlink = [] (const char* path, char* buf, size_t sz) -> int {
+ Guard g;
const ssize_t len{readlink((root + path).c_str(), buf, sz - 1)}; // sz > 0, since it includes space for null terminator
if (len == -1) {
return -errno;
@@ -125,36 +223,47 @@ int main (int argc, char** argv)
return 0;
};
disorderfs_fuse_operations.mknod = [] (const char* path, mode_t mode, dev_t dev) -> int {
+ Guard g;
return wrap(mknod((root + path).c_str(), mode, dev));
};
disorderfs_fuse_operations.mkdir = [] (const char* path, mode_t mode) -> int {
+ Guard g;
return wrap(mkdir((root + path).c_str(), mode));
};
disorderfs_fuse_operations.unlink = [] (const char* path) -> int {
+ Guard g;
return wrap(unlink((root + path).c_str()));
};
disorderfs_fuse_operations.rmdir = [] (const char* path) -> int {
+ Guard g;
return wrap(rmdir((root + path).c_str()));
};
disorderfs_fuse_operations.symlink = [] (const char* target, const char* linkpath) -> int {
+ Guard g;
return wrap(symlink(target, (root + linkpath).c_str()));
};
disorderfs_fuse_operations.rename = [] (const char* oldpath, const char* newpath) -> int {
+ Guard g;
return wrap(rename((root + oldpath).c_str(), (root + newpath).c_str()));
};
disorderfs_fuse_operations.link = [] (const char* oldpath, const char* newpath) -> int {
+ Guard g;
return wrap(link((root + oldpath).c_str(), (root + newpath).c_str()));
};
disorderfs_fuse_operations.chmod = [] (const char* path, mode_t mode) -> int {
+ Guard g;
return wrap(chmod((root + path).c_str(), mode));
};
disorderfs_fuse_operations.chown = [] (const char* path, uid_t uid, gid_t gid) -> int {
+ Guard g;
return wrap(lchown((root + path).c_str(), uid, gid));
};
disorderfs_fuse_operations.truncate = [] (const char* path, off_t length) -> int {
+ Guard g;
return wrap(truncate((root + path).c_str(), length));
};
disorderfs_fuse_operations.open = [] (const char* path, struct fuse_file_info* info) -> int {
+ Guard g;
const int fd{open((root + path).c_str(), info->flags)};
if (fd == -1) {
return -errno;
@@ -169,6 +278,7 @@ int main (int argc, char** argv)
return pwrite(info->fh, buf, sz, off);
};
disorderfs_fuse_operations.statfs = [] (const char* path, struct statvfs* f) -> int {
+ Guard g;
return wrap(statvfs((root + path).c_str(), f));
};
/* TODO: flush
@@ -184,20 +294,25 @@ int main (int argc, char** argv)
};
*/
disorderfs_fuse_operations.setxattr = [] (const char* path, const char* name, const char* value, size_t size, int flags) -> int {
+ Guard g;
return wrap(lsetxattr((root + path).c_str(), name, value, size, flags));
};
disorderfs_fuse_operations.getxattr = [] (const char* path, const char* name, char* value, size_t size) -> int {
+ Guard g;
ssize_t res = lgetxattr((root + path).c_str(), name, value, size);
return res >= 0 ? res : -errno;
};
disorderfs_fuse_operations.listxattr = [] (const char* path, char* list, size_t size) -> int {
+ Guard g;
ssize_t res = llistxattr((root + path).c_str(), list, size);
return res >= 0 ? res : -errno;
};
disorderfs_fuse_operations.removexattr = [] (const char* path, const char* name) -> int {
+ Guard g;
return wrap(lremovexattr((root + path).c_str(), name));
};
disorderfs_fuse_operations.opendir = [] (const char* path, struct fuse_file_info* info) -> int {
+ Guard g;
std::unique_ptr<Dirents> dirents{new Dirents};
DIR* d = opendir((root + path).c_str());
@@ -245,6 +360,7 @@ int main (int argc, char** argv)
};
*/
disorderfs_fuse_operations.create = [] (const char* path, mode_t mode, struct fuse_file_info* info) -> int {
+ Guard g;
// XXX: use info->flags?
const int fd{open((root + path).c_str(), info->flags | O_CREAT, mode)};
if (fd == -1) {
@@ -270,6 +386,7 @@ int main (int argc, char** argv)
};
*/
disorderfs_fuse_operations.utimens = [] (const char* path, const struct timespec tv[2]) -> int {
+ Guard g;
return wrap(utimensat(AT_FDCWD, (root + path).c_str(), tv, AT_SYMLINK_NOFOLLOW));
};
/* Not applicable?
@@ -316,6 +433,10 @@ int main (int argc, char** argv)
// Add some of our own hard-coded FUSE options:
fuse_opt_add_arg(&fargs, "-o");
fuse_opt_add_arg(&fargs, "direct_io,atomic_o_trunc,default_permissions"); // XXX: other mount options?
+ if (config.multi_user) {
+ fuse_opt_add_arg(&fargs, "-o");
+ fuse_opt_add_arg(&fargs, "allow_other");
+ }
fuse_opt_add_arg(&fargs, bare_arguments[1].c_str());
return fuse_main(fargs.argc, fargs.argv, &disorderfs_fuse_operations, nullptr);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/disorderfs.git
More information about the Reproducible-commits
mailing list