From: Darrick J. Wong <djwong@xxxxxxxxxx> In "kernel" mode (aka allow_others + default_permissions), the kernel enforces all the access control for us. Therefore, we don't need to do any checking of our own. Create a purpose-built helper to detect this situation and turn off all the access controlling. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- misc/fuse2fs.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index a10491d19f54a9..8451cabfb19110 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -491,6 +491,18 @@ static inline int is_superuser(struct fuse2fs *ff, struct fuse_context *ctxt) return ctxt->uid == 0; } +static inline int want_check_owner(struct fuse2fs *ff, + struct fuse_context *ctxt) +{ + /* + * The kernel is responsible for access control, so we allow anything + * that the superuser can do. + */ + if (ff->kernel) + return 0; + return !is_superuser(ff, ctxt); +} + static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask) { struct fuse_context *ctxt = fuse_get_context(); @@ -523,6 +535,10 @@ static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask) (inode.i_flags & EXT2_IMMUTABLE_FL)) return -EACCES; + /* If kernel is responsible for mode and acl checks, we're done. */ + if (ff->kernel) + return 0; + /* Figure out what root's allowed to do */ if (is_superuser(ff, ctxt)) { /* Non-file access always ok */ @@ -1808,7 +1824,7 @@ static int op_chmod(const char *path, mode_t mode goto out; } - if (!is_superuser(ff, ctxt) && ctxt->uid != inode_uid(inode)) { + if (want_check_owner(ff, ctxt) && ctxt->uid != inode_uid(inode)) { ret = -EPERM; goto out; } @@ -1875,7 +1891,7 @@ static int op_chown(const char *path, uid_t owner, gid_t group /* FUSE seems to feed us ~0 to mean "don't change" */ if (owner != (uid_t) ~0) { /* Only root gets to change UID. */ - if (!is_superuser(ff, ctxt) && + if (want_check_owner(ff, ctxt) && !(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) { ret = -EPERM; goto out; @@ -1886,7 +1902,7 @@ static int op_chown(const char *path, uid_t owner, gid_t group if (group != (gid_t) ~0) { /* Only root or the owner get to change GID. */ - if (!is_superuser(ff, ctxt) && + if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid) { ret = -EPERM; goto out; @@ -3051,7 +3067,7 @@ static int ioctl_setflags(struct fuse2fs *ff, struct fuse2fs_file_handle *fh, if (err) return translate_error(fs, fh->ino, err); - if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid) + if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid) return -EPERM; ret = set_iflags(&inode, flags); @@ -3107,7 +3123,7 @@ static int ioctl_setversion(struct fuse2fs *ff, struct fuse2fs_file_handle *fh, if (err) return translate_error(fs, fh->ino, err); - if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid) + if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid) return -EPERM; inode.i_generation = generation; @@ -3213,7 +3229,7 @@ static int ioctl_fssetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh, if (err) return translate_error(fs, fh->ino, err); - if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid) + if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid) return -EPERM; ret = set_iflags(&inode, flags);