diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | src/bindfs.c | 131 | ||||
-rw-r--r-- | src/usermap.c | 24 | ||||
-rw-r--r-- | src/usermap.h | 14 | ||||
-rwxr-xr-x | tests/common.rb | 2 | ||||
-rwxr-xr-x | tests/test_bindfs.rb | 22 |
6 files changed, 78 insertions, 119 deletions
@@ -1,3 +1,7 @@ +2012-05-18 Martin Pärtel <martin dot partel at gmail dot com> + + * Fixed regression of --create-as-user. Added test case. + 2012-04-05 Martin Pärtel <martin dot partel at gmail dot com> * Made -ouse_ino and -oreaddir_ino the default to diff --git a/src/bindfs.c b/src/bindfs.c index 3bda72f..b0cd9a0 100644 --- a/src/bindfs.c +++ b/src/bindfs.c @@ -68,7 +68,7 @@ #include "misc.h" /* SETTINGS */ -static struct settings { +static struct Settings { const char *progname; struct permchain *permchain; /* permission bit rules. see permchain.h */ uid_t new_uid; /* user-specified uid */ @@ -143,9 +143,12 @@ static int is_mirrored_user(uid_t uid); /* Processes the virtual path to a real path. Don't free() the result. */ static const char *process_path(const char *path); -/* The common parts of getattr and fgetattr */ +/* The common parts of getattr and fgetattr. */ static int getattr_common(const char *path, struct stat *stbuf); +/* Chowns a new file if necessary. */ +static void chown_new_file(const char *path, struct fuse_context *fc, int (*chown_func)(const char*, uid_t, gid_t)); + /* FUSE callbacks */ static void *bindfs_init(); @@ -240,8 +243,8 @@ static int getattr_common(const char *procpath, struct stat *stbuf) stbuf->st_ctime = stbuf->st_mtime; /* Possibly map user/group */ - stbuf->st_uid = usermap_get_uid(settings.usermap, stbuf->st_uid); - stbuf->st_gid = usermap_get_gid(settings.usermap, stbuf->st_gid); + stbuf->st_uid = usermap_get_uid_or_default(settings.usermap, stbuf->st_uid, stbuf->st_uid); + stbuf->st_gid = usermap_get_gid_or_default(settings.usermap, stbuf->st_gid, stbuf->st_gid); /* Report user-defined owner/group if specified */ if (settings.new_uid != -1) @@ -280,6 +283,34 @@ static int getattr_common(const char *procpath, struct stat *stbuf) return 0; } +static void chown_new_file(const char *path, struct fuse_context *fc, int (*chown_func)(const char*, uid_t, gid_t)) +{ + uid_t file_owner; + gid_t file_group; + + if (settings.create_policy == CREATE_AS_USER) { + file_owner = fc->uid; + file_group = fc->gid; + } else { + file_owner = -1; + file_group = -1; + } + + file_owner = usermap_get_uid_or_default(settings.usermap_reverse, fc->uid, file_owner); + file_group = usermap_get_gid_or_default(settings.usermap_reverse, fc->gid, file_group); + + if (settings.create_for_uid != -1) + file_owner = settings.create_for_uid; + if (settings.create_for_gid != -1) + file_group = settings.create_for_gid; + + if ((file_owner != -1) || (file_group != -1)) { + if (chown_func(path, file_owner, file_group) == -1) { + DPRINTF("Failed to chown new file or directory (%d)", errno); + } + } +} + static void *bindfs_init() { assert(settings.permchain != NULL); @@ -392,8 +423,6 @@ static int bindfs_mknod(const char *path, mode_t mode, dev_t rdev) { int res; struct fuse_context *fc; - uid_t file_owner; - gid_t file_group; path = process_path(path); @@ -407,25 +436,7 @@ static int bindfs_mknod(const char *path, mode_t mode, dev_t rdev) return -errno; fc = fuse_get_context(); - - if (settings.create_policy == CREATE_AS_USER) { - file_owner = fc->uid; - file_group = fc->gid; - } - - file_owner = usermap_get_uid_or_none(settings.usermap_reverse, fc->uid); - file_group = usermap_get_gid_or_none(settings.usermap_reverse, fc->gid); - - if (settings.create_for_uid != -1) - file_owner = settings.create_for_uid; - if (settings.create_for_gid != -1) - file_group = settings.create_for_gid; - - if ((file_owner != -1) || (file_group != -1)) { - if (chown(path, file_owner, file_group) == -1) { - DPRINTF("Failed to chown new device node (%d)", errno); - } - } + chown_new_file(path, fc, &chown); return 0; } @@ -434,8 +445,6 @@ static int bindfs_mkdir(const char *path, mode_t mode) { int res; struct fuse_context *fc; - uid_t file_owner; - gid_t file_group; path = process_path(path); @@ -447,25 +456,7 @@ static int bindfs_mkdir(const char *path, mode_t mode) return -errno; fc = fuse_get_context(); - - if (settings.create_policy == CREATE_AS_USER) { - file_owner = fc->uid; - file_group = fc->gid; - } - - file_owner = usermap_get_uid_or_none(settings.usermap_reverse, fc->uid); - file_group = usermap_get_gid_or_none(settings.usermap_reverse, fc->gid); - - if (settings.create_for_uid != -1) - file_owner = settings.create_for_uid; - if (settings.create_for_gid != -1) - file_group = settings.create_for_gid; - - if ((file_owner != -1) || (file_group != -1)) { - if (chown(path, file_owner, file_group) == -1) { - DPRINTF("Failed to chown new directory (%d)", errno); - } - } + chown_new_file(path, fc, &chown); return 0; } @@ -500,8 +491,6 @@ static int bindfs_symlink(const char *from, const char *to) { int res; struct fuse_context *fc; - uid_t file_owner; - gid_t file_group; to = process_path(to); @@ -510,25 +499,7 @@ static int bindfs_symlink(const char *from, const char *to) return -errno; fc = fuse_get_context(); - - if (settings.create_policy == CREATE_AS_USER) { - file_owner = fc->uid; - file_group = fc->gid; - } - - file_owner = usermap_get_uid_or_none(settings.usermap_reverse, fc->uid); - file_group = usermap_get_gid_or_none(settings.usermap_reverse, fc->gid); - - if (settings.create_for_uid != -1) - file_owner = settings.create_for_uid; - if (settings.create_for_gid != -1) - file_group = settings.create_for_gid; - - if ((file_owner != -1) || (file_group != -1)) { - if (lchown(to, file_owner, file_group) == -1) { - DPRINTF("Failed to lchown new symlink (%d)", errno); - } - } + chown_new_file(to, fc, &lchown); return 0; } @@ -615,7 +586,7 @@ static int bindfs_chown(const char *path, uid_t uid, gid_t gid) if (uid != -1) { switch (settings.chown_policy) { case CHOWN_NORMAL: - uid = usermap_get_uid(settings.usermap_reverse, uid); + uid = usermap_get_uid_or_default(settings.usermap_reverse, uid, uid); break; case CHOWN_IGNORE: uid = -1; @@ -628,7 +599,7 @@ static int bindfs_chown(const char *path, uid_t uid, gid_t gid) if (gid != -1) { switch (settings.chgrp_policy) { case CHGRP_NORMAL: - gid = usermap_get_gid(settings.usermap_reverse, gid); + gid = usermap_get_gid_or_default(settings.usermap_reverse, gid, gid); break; case CHGRP_IGNORE: gid = -1; @@ -691,8 +662,6 @@ static int bindfs_create(const char *path, mode_t mode, struct fuse_file_info *f { int fd; struct fuse_context *fc; - uid_t file_owner; - gid_t file_group; path = process_path(path); @@ -704,25 +673,7 @@ static int bindfs_create(const char *path, mode_t mode, struct fuse_file_info *f return -errno; fc = fuse_get_context(); - - if (settings.create_policy == CREATE_AS_USER) { - file_owner = fc->uid; - file_group = fc->gid; - } - - file_owner = usermap_get_uid_or_none(settings.usermap_reverse, fc->uid); - file_group = usermap_get_gid_or_none(settings.usermap_reverse, fc->gid); - - if (settings.create_for_uid != -1) - file_owner = settings.create_for_uid; - if (settings.create_for_gid != -1) - file_group = settings.create_for_gid; - - if ((file_owner != -1) || (file_group != -1)) { - if (chown(path, file_owner, file_group) == -1) { - DPRINTF("Failed to chown new file (%d)", errno); - } - } + chown_new_file(path, fc, &chown); fi->fh = fd; return 0; diff --git a/src/usermap.c b/src/usermap.c index b900296..0cffa33 100644 --- a/src/usermap.c +++ b/src/usermap.c @@ -48,7 +48,7 @@ UsermapStatus usermap_add_uid(UserMap *map, uid_t from, uid_t to) map->user_from = (uid_t*)realloc(map->user_from, map->user_capacity * sizeof(uid_t)); map->user_to = (uid_t*)realloc(map->user_to, map->user_capacity * sizeof(uid_t)); } - if (usermap_get_uid(map, from) != from) { + if (usermap_get_uid_or_default(map, from, -1) != -1) { return usermap_status_duplicate_key; } i = map->user_size; @@ -69,7 +69,7 @@ UsermapStatus usermap_add_gid(UserMap *map, gid_t from, gid_t to) map->group_from = (gid_t*)realloc(map->group_from, map->group_capacity * sizeof(gid_t)); map->group_to = (gid_t*)realloc(map->group_to, map->group_capacity * sizeof(gid_t)); } - if (usermap_get_gid(map, from) != from) { + if (usermap_get_gid_or_default(map, from, -1) != -1) { return usermap_status_duplicate_key; } i = map->group_size; @@ -88,19 +88,7 @@ const char* usermap_errorstr(UsermapStatus status) } } -uid_t usermap_get_uid(UserMap *map, uid_t u) -{ - uid_t result = usermap_get_uid_or_none(map, u); - return (result != -1 ? result : u); -} - -gid_t usermap_get_gid(UserMap *map, gid_t g) -{ - gid_t result = usermap_get_gid_or_none(map, g); - return (result != -1 ? result : g); -} - -uid_t usermap_get_uid_or_none(UserMap *map, uid_t u) +uid_t usermap_get_uid_or_default(UserMap *map, uid_t u, uid_t deflt) { int i; for (i = 0; i < map->user_size; ++i) { @@ -108,10 +96,10 @@ uid_t usermap_get_uid_or_none(UserMap *map, uid_t u) return map->user_to[i]; } } - return -1; + return deflt; } -gid_t usermap_get_gid_or_none(UserMap *map, gid_t g) +gid_t usermap_get_gid_or_default(UserMap *map, gid_t g, gid_t deflt) { int i; for (i = 0; i < map->group_size; ++i) { @@ -119,5 +107,5 @@ gid_t usermap_get_gid_or_none(UserMap *map, gid_t g) return map->group_to[i]; } } - return -1; + return deflt; } diff --git a/src/usermap.h b/src/usermap.h index 8a74bb1..9c1387e 100644 --- a/src/usermap.h +++ b/src/usermap.h @@ -45,16 +45,10 @@ UsermapStatus usermap_add_gid(UserMap *map, gid_t from, gid_t to); const char* usermap_errorstr(UsermapStatus status); -/* Returns the uid that u is mapped to, or u if none. */ -uid_t usermap_get_uid(UserMap *map, uid_t u); +/* Returns the uid that u is mapped to, or deflt if none. */ +uid_t usermap_get_uid_or_default(UserMap *map, uid_t u, uid_t deflt); -/* Returns the gid that g is mapped to, or g if none. */ -gid_t usermap_get_gid(UserMap *map, gid_t g); - -/* Returns the uid that u is mapped to, or -1 if none. */ -uid_t usermap_get_uid_or_none(UserMap *map, uid_t u); - -/* Returns the gid that g is mapped to, or -1 if none. */ -gid_t usermap_get_gid_or_none(UserMap *map, gid_t g); +/* Returns the gid that g is mapped to, or deflt if none. */ +gid_t usermap_get_gid_or_default(UserMap *map, gid_t g, gid_t deflt); #endif diff --git a/tests/common.rb b/tests/common.rb index ac1ef43..7174257 100755 --- a/tests/common.rb +++ b/tests/common.rb @@ -18,7 +18,7 @@ # along with bindfs. If not, see <http://www.gnu.org/licenses/>. # -require 'fileutils.rb' +require 'fileutils' include FileUtils # Set the default umask for all tests diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb index ff1ee24..1f78250 100755 --- a/tests/test_bindfs.rb +++ b/tests/test_bindfs.rb @@ -74,6 +74,28 @@ testenv("-u nobody -m #{Process.uid} -p 0600,u+D") do assert { File.stat('mnt/file').uid == Process.uid } end +root_testenv("", :title => "--create-as-user should be default for root") do + chmod(0777, 'src') + `su -c 'touch mnt/file' nobody` + `su -c 'mkdir mnt/dir' nobody` + `su -c 'ln -sf /tmp/foo mnt/lnk' nobody` + + assert { File.stat('mnt/file').uid == nobody_uid } + assert { File.stat('mnt/file').gid == nogroup_gid } + assert { File.stat('src/file').uid == nobody_uid } + assert { File.stat('src/file').gid == nogroup_gid } + + assert { File.stat('mnt/dir').uid == nobody_uid } + assert { File.stat('mnt/dir').gid == nogroup_gid } + assert { File.stat('src/dir').uid == nobody_uid } + assert { File.stat('src/dir').gid == nogroup_gid } + + assert { File.lstat('mnt/lnk').uid == nobody_uid } + assert { File.lstat('mnt/lnk').gid == nogroup_gid } + assert { File.lstat('src/lnk').uid == nobody_uid } + assert { File.lstat('src/lnk').gid == nogroup_gid } +end + testenv("--create-with-perms=og=r:ogd+x") do touch('src/file') mkdir('src/dir') |