aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--src/bindfs.c131
-rw-r--r--src/usermap.c24
-rw-r--r--src/usermap.h14
-rwxr-xr-xtests/common.rb2
-rwxr-xr-xtests/test_bindfs.rb22
6 files changed, 78 insertions, 119 deletions
diff --git a/ChangeLog b/ChangeLog
index 9d8e986..d2b7104 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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')