mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
inode: make init and permission helpers idmapped mount aware
The inode_owner_or_capable() helper determines whether the caller is the owner of the inode or is capable with respect to that inode. Allow it to handle idmapped mounts. If the inode is accessed through an idmapped mount it according to the mount's user namespace. Afterwards the checks are identical to non-idmapped mounts. If the initial user namespace is passed nothing changes so non-idmapped mounts will see identical behavior as before. Similarly, allow the inode_init_owner() helper to handle idmapped mounts. It initializes a new inode on idmapped mounts by mapping the fsuid and fsgid of the caller from the mount's user namespace. If the initial user namespace is passed nothing changes so non-idmapped mounts will see identical behavior as before. Link: https://lore.kernel.org/r/20210121131959.646623-7-christian.brauner@ubuntu.com Cc: Christoph Hellwig <hch@lst.de> Cc: David Howells <dhowells@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: James Morris <jamorris@linux.microsoft.com> Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
+1
-1
@@ -258,7 +258,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return -EOPNOTSUPP;
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
if (value) {
|
||||
/* update the cached acl value */
|
||||
|
||||
+1
-1
@@ -251,7 +251,7 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
inode_init_owner(inode, NULL, mode);
|
||||
inode_init_owner(&init_user_ns,inode, NULL, mode);
|
||||
inode->i_blocks = 0;
|
||||
inode->i_rdev = rdev;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
|
||||
|
||||
@@ -87,7 +87,7 @@ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
/* Make sure a caller can chmod. */
|
||||
if (ia_valid & ATTR_MODE) {
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
/* Also check the setgid bit! */
|
||||
if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
|
||||
@@ -98,7 +98,7 @@ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
/* Check for setting the inode time. */
|
||||
if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
|
||||
if (IS_IMMUTABLE(inode))
|
||||
return -EPERM;
|
||||
|
||||
if (!inode_owner_or_capable(inode)) {
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode)) {
|
||||
error = inode_permission(&init_user_ns, inode,
|
||||
MAY_WRITE);
|
||||
if (error)
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
}
|
||||
set_bit(ino, info->si_imap);
|
||||
info->si_freei--;
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
||||
inode->i_blocks = 0;
|
||||
inode->i_op = &bfs_file_inops;
|
||||
|
||||
+1
-1
@@ -6190,7 +6190,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
||||
if (ret != 0)
|
||||
goto fail_unlock;
|
||||
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
inode_set_bytes(inode, 0);
|
||||
|
||||
inode->i_mtime = current_time(inode);
|
||||
|
||||
+5
-5
@@ -213,7 +213,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
|
||||
const char *comp = NULL;
|
||||
u32 binode_flags;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
if (btrfs_root_readonly(root))
|
||||
@@ -429,7 +429,7 @@ static int btrfs_ioctl_fssetxattr(struct file *file, void __user *arg)
|
||||
unsigned old_i_flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
if (btrfs_root_readonly(root))
|
||||
@@ -1862,7 +1862,7 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
|
||||
btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
|
||||
"Snapshot src from another FS");
|
||||
ret = -EXDEV;
|
||||
} else if (!inode_owner_or_capable(src_inode)) {
|
||||
} else if (!inode_owner_or_capable(&init_user_ns, src_inode)) {
|
||||
/*
|
||||
* Subvolume creation is not restricted, but snapshots
|
||||
* are limited to own subvolumes only
|
||||
@@ -1982,7 +1982,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
|
||||
u64 flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
ret = mnt_want_write_file(file);
|
||||
@@ -4453,7 +4453,7 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
|
||||
int ret = 0;
|
||||
int received_uuid_changed;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
ret = mnt_want_write_file(file);
|
||||
|
||||
@@ -62,7 +62,7 @@ struct inode *btrfs_new_test_inode(void)
|
||||
BTRFS_I(inode)->location.type = BTRFS_INODE_ITEM_KEY;
|
||||
BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
||||
BTRFS_I(inode)->location.offset = 0;
|
||||
inode_init_owner(inode, NULL, S_IFREG);
|
||||
inode_init_owner(&init_user_ns, inode, NULL, S_IFREG);
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
+1
-1
@@ -465,7 +465,7 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
|
||||
return -EFAULT;
|
||||
policy.version = version;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
ret = mnt_want_write_file(filp);
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
|
||||
unsigned int oldflags = efivarfs_getflags(inode);
|
||||
int error;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (copy_from_user(&flags, arg, sizeof(flags)))
|
||||
|
||||
+1
-1
@@ -551,7 +551,7 @@ got:
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = dir->i_gid;
|
||||
} else
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
|
||||
inode->i_ino = ino;
|
||||
inode->i_blocks = 0;
|
||||
|
||||
+3
-3
@@ -39,7 +39,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode)) {
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode)) {
|
||||
ret = -EACCES;
|
||||
goto setflags_out;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ setflags_out:
|
||||
case EXT2_IOC_SETVERSION: {
|
||||
__u32 generation;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
ret = mnt_want_write_file(filp);
|
||||
if (ret)
|
||||
@@ -117,7 +117,7 @@ setversion_out:
|
||||
if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
|
||||
return -ENOTTY;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (get_user(rsv_window_size, (int __user *)arg))
|
||||
|
||||
+1
-1
@@ -972,7 +972,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = dir->i_gid;
|
||||
} else
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
|
||||
if (ext4_has_feature_project(sb) &&
|
||||
ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT))
|
||||
|
||||
+8
-7
@@ -139,7 +139,8 @@ static long swap_inode_boot_loader(struct super_block *sb,
|
||||
}
|
||||
|
||||
if (IS_RDONLY(inode) || IS_APPEND(inode) || IS_IMMUTABLE(inode) ||
|
||||
!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) {
|
||||
!inode_owner_or_capable(&init_user_ns, inode) ||
|
||||
!capable(CAP_SYS_ADMIN)) {
|
||||
err = -EPERM;
|
||||
goto journal_err_out;
|
||||
}
|
||||
@@ -829,7 +830,7 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
case FS_IOC_SETFLAGS: {
|
||||
int err;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (get_user(flags, (int __user *) arg))
|
||||
@@ -871,7 +872,7 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
__u32 generation;
|
||||
int err;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
if (ext4_has_metadata_csum(inode->i_sb)) {
|
||||
@@ -1010,7 +1011,7 @@ mext_out:
|
||||
case EXT4_IOC_MIGRATE:
|
||||
{
|
||||
int err;
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
err = mnt_want_write_file(filp);
|
||||
@@ -1032,7 +1033,7 @@ mext_out:
|
||||
case EXT4_IOC_ALLOC_DA_BLKS:
|
||||
{
|
||||
int err;
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
err = mnt_want_write_file(filp);
|
||||
@@ -1217,7 +1218,7 @@ resizefs_out:
|
||||
|
||||
case EXT4_IOC_CLEAR_ES_CACHE:
|
||||
{
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
ext4_clear_inode_es(inode);
|
||||
return 0;
|
||||
@@ -1263,7 +1264,7 @@ resizefs_out:
|
||||
return -EFAULT;
|
||||
|
||||
/* Make sure caller has proper permission */
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (fa.fsx_xflags & ~EXT4_SUPPORTED_FS_XFLAGS)
|
||||
|
||||
+7
-7
@@ -1961,7 +1961,7 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
|
||||
u32 iflags;
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (get_user(fsflags, (int __user *)arg))
|
||||
@@ -2008,7 +2008,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
@@ -2075,7 +2075,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
|
||||
struct inode *inode = file_inode(filp);
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
ret = mnt_want_write_file(filp);
|
||||
@@ -2117,7 +2117,7 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
|
||||
struct inode *inode = file_inode(filp);
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
@@ -2152,7 +2152,7 @@ static int f2fs_ioc_release_volatile_write(struct file *filp)
|
||||
struct inode *inode = file_inode(filp);
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
ret = mnt_want_write_file(filp);
|
||||
@@ -2181,7 +2181,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
|
||||
struct inode *inode = file_inode(filp);
|
||||
int ret;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
ret = mnt_want_write_file(filp);
|
||||
@@ -3158,7 +3158,7 @@ static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
|
||||
return -EFAULT;
|
||||
|
||||
/* Make sure caller has proper permission */
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EACCES;
|
||||
|
||||
if (fa.fsx_xflags & ~F2FS_SUPPORTED_XFLAGS)
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
|
||||
|
||||
nid_free = true;
|
||||
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
|
||||
inode->i_ino = ino;
|
||||
inode->i_blocks = 0;
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
|
||||
unsigned char old_advise = F2FS_I(inode)->i_advise;
|
||||
unsigned char new_advise;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
if (value == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
|
||||
|
||||
/* O_NOATIME can only be set by the owner or superuser */
|
||||
if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME))
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
return -EPERM;
|
||||
|
||||
/* required for strict SunOS emulation */
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
|
||||
goto out;
|
||||
|
||||
error = -EACCES;
|
||||
if (!inode_owner_or_capable(inode))
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode))
|
||||
goto out;
|
||||
|
||||
error = 0;
|
||||
|
||||
+1
-1
@@ -376,7 +376,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
|
||||
return NULL;
|
||||
|
||||
inode->i_ino = sbi->next_cnid++;
|
||||
inode_init_owner(inode, dir, mode);
|
||||
inode_init_owner(&init_user_ns, inode, dir, mode);
|
||||
set_nlink(inode, 1);
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
||||
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (!inode_owner_or_capable(inode)) {
|
||||
if (!inode_owner_or_capable(&init_user_ns, inode)) {
|
||||
err = -EACCES;
|
||||
goto out_drop_write;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user