summaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-02-21 12:18:07 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2018-03-20 12:11:44 -0400
commit8cb08329b0809453722bc12aa912be34355bcb66 (patch)
treeec696907d93471f83261eb66ab9f3f9647e37ed3 /fs/fuse/dir.c
parentc9582eb0ff7d2b560be60eafab29183882cdc82b (diff)
fuse: Support fuse filesystems outside of init_user_ns
In order to support mounts from namespaces other than init_user_ns, fuse must translate uids and gids to/from the userns of the process servicing requests on /dev/fuse. This patch does that, with a couple of restrictions on the namespace: - The userns for the fuse connection is fixed to the namespace from which /dev/fuse is opened. - The namespace must be the same as s_user_ns. These restrictions simplify the implementation by avoiding the need to pass around userns references and by allowing fuse to rely on the checks in setattr_prepare for ownership changes. Either restriction could be relaxed in the future if needed. For cuse the userns used is the opener of /dev/cuse. Semantically the cuse support does not appear safe for unprivileged users. Practically the permissions on /dev/cuse only make it accessible to the global root user. If something slips through the cracks in a user namespace the only users who will be able to use the cuse device are those users mapped into the user namespace. Translation in the posix acl is updated to use the uuser namespace of the filesystem. Avoiding cases which might bypass this translation is handled in a following change. This change is stronlgy based on a similar change from Seth Forshee and Dongsu Park. Cc: Seth Forshee <seth.forshee@canonical.com> Cc: Dongsu Park <dongsu@kinvolk.io> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 7a980b4462d9..cf8a1cd7a62e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -858,8 +858,8 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
858 stat->ino = attr->ino; 858 stat->ino = attr->ino;
859 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 859 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
860 stat->nlink = attr->nlink; 860 stat->nlink = attr->nlink;
861 stat->uid = make_kuid(&init_user_ns, attr->uid); 861 stat->uid = make_kuid(fc->user_ns, attr->uid);
862 stat->gid = make_kgid(&init_user_ns, attr->gid); 862 stat->gid = make_kgid(fc->user_ns, attr->gid);
863 stat->rdev = inode->i_rdev; 863 stat->rdev = inode->i_rdev;
864 stat->atime.tv_sec = attr->atime; 864 stat->atime.tv_sec = attr->atime;
865 stat->atime.tv_nsec = attr->atimensec; 865 stat->atime.tv_nsec = attr->atimensec;
@@ -1475,17 +1475,17 @@ static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
1475 return true; 1475 return true;
1476} 1476}
1477 1477
1478static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, 1478static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1479 bool trust_local_cmtime) 1479 struct fuse_setattr_in *arg, bool trust_local_cmtime)
1480{ 1480{
1481 unsigned ivalid = iattr->ia_valid; 1481 unsigned ivalid = iattr->ia_valid;
1482 1482
1483 if (ivalid & ATTR_MODE) 1483 if (ivalid & ATTR_MODE)
1484 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 1484 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
1485 if (ivalid & ATTR_UID) 1485 if (ivalid & ATTR_UID)
1486 arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); 1486 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
1487 if (ivalid & ATTR_GID) 1487 if (ivalid & ATTR_GID)
1488 arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); 1488 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
1489 if (ivalid & ATTR_SIZE) 1489 if (ivalid & ATTR_SIZE)
1490 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 1490 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
1491 if (ivalid & ATTR_ATIME) { 1491 if (ivalid & ATTR_ATIME) {
@@ -1657,7 +1657,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
1657 1657
1658 memset(&inarg, 0, sizeof(inarg)); 1658 memset(&inarg, 0, sizeof(inarg));
1659 memset(&outarg, 0, sizeof(outarg)); 1659 memset(&outarg, 0, sizeof(outarg));
1660 iattr_to_fattr(attr, &inarg, trust_local_cmtime); 1660 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
1661 if (file) { 1661 if (file) {
1662 struct fuse_file *ff = file->private_data; 1662 struct fuse_file *ff = file->private_data;
1663 inarg.valid |= FATTR_FH; 1663 inarg.valid |= FATTR_FH;