diff options
Diffstat (limited to 'fs/ext2/ioctl.c')
| -rw-r--r-- | fs/ext2/ioctl.c | 115 |
1 files changed, 43 insertions, 72 deletions
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 5d46c09863f0..c3fea55b8efa 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * linux/fs/ext2/ioctl.c * @@ -14,85 +15,58 @@ #include <linux/compat.h> #include <linux/mount.h> #include <asm/current.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> +#include <linux/fileattr.h> - -long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +int ext2_fileattr_get(struct dentry *dentry, struct file_kattr *fa) { - struct inode *inode = file_inode(filp); - struct ext2_inode_info *ei = EXT2_I(inode); - unsigned int flags; - unsigned short rsv_window_size; - int ret; + struct ext2_inode_info *ei = EXT2_I(d_inode(dentry)); - ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); + fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE); - switch (cmd) { - case EXT2_IOC_GETFLAGS: - ext2_get_inode_flags(ei); - flags = ei->i_flags & EXT2_FL_USER_VISIBLE; - return put_user(flags, (int __user *) arg); - case EXT2_IOC_SETFLAGS: { - unsigned int oldflags; + return 0; +} - ret = mnt_want_write_file(filp); - if (ret) - return ret; +int ext2_fileattr_set(struct mnt_idmap *idmap, + struct dentry *dentry, struct file_kattr *fa) +{ + struct inode *inode = d_inode(dentry); + struct ext2_inode_info *ei = EXT2_I(inode); - if (!inode_owner_or_capable(inode)) { - ret = -EACCES; - goto setflags_out; - } + if (fileattr_has_fsx(fa)) + return -EOPNOTSUPP; - if (get_user(flags, (int __user *) arg)) { - ret = -EFAULT; - goto setflags_out; - } + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) + return -EPERM; - flags = ext2_mask_flags(inode->i_mode, flags); + ei->i_flags = (ei->i_flags & ~EXT2_FL_USER_MODIFIABLE) | + (fa->flags & EXT2_FL_USER_MODIFIABLE); - mutex_lock(&inode->i_mutex); - /* Is it quota file? Do not allow user to mess with it */ - if (IS_NOQUOTA(inode)) { - mutex_unlock(&inode->i_mutex); - ret = -EPERM; - goto setflags_out; - } - oldflags = ei->i_flags; + ext2_set_inode_flags(inode); + inode_set_ctime_current(inode); + mark_inode_dirty(inode); - /* - * The IMMUTABLE and APPEND_ONLY flags can only be changed by - * the relevant capability. - * - * This test looks nicer. Thanks to Pauline Middelink - */ - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - mutex_unlock(&inode->i_mutex); - ret = -EPERM; - goto setflags_out; - } - } + return 0; +} - flags = flags & EXT2_FL_USER_MODIFIABLE; - flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; - ei->i_flags = flags; - ext2_set_inode_flags(inode); - inode->i_ctime = CURRENT_TIME_SEC; - mutex_unlock(&inode->i_mutex); +long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct ext2_inode_info *ei = EXT2_I(inode); + unsigned short rsv_window_size; + int ret; - mark_inode_dirty(inode); -setflags_out: - mnt_drop_write_file(filp); - return ret; - } + ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); + + switch (cmd) { case EXT2_IOC_GETVERSION: return put_user(inode->i_generation, (int __user *) arg); case EXT2_IOC_SETVERSION: { __u32 generation; - if (!inode_owner_or_capable(inode)) + if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) return -EPERM; ret = mnt_want_write_file(filp); if (ret) @@ -102,10 +76,10 @@ setflags_out: goto setversion_out; } - mutex_lock(&inode->i_mutex); - inode->i_ctime = CURRENT_TIME_SEC; + inode_lock(inode); + inode_set_ctime_current(inode); inode->i_generation = generation; - mutex_unlock(&inode->i_mutex); + inode_unlock(inode); mark_inode_dirty(inode); setversion_out: @@ -125,7 +99,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(&nop_mnt_idmap, inode)) return -EACCES; if (get_user(rsv_window_size, (int __user *)arg)) @@ -153,10 +127,13 @@ setversion_out: if (ei->i_block_alloc_info){ struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; rsv->rsv_goal_size = rsv_window_size; + } else { + ret = -ENOMEM; } + mutex_unlock(&ei->truncate_mutex); mnt_drop_write_file(filp); - return 0; + return ret; } default: return -ENOTTY; @@ -168,12 +145,6 @@ long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { /* These are just misnamed, they actually get/put from/to user an int */ switch (cmd) { - case EXT2_IOC32_GETFLAGS: - cmd = EXT2_IOC_GETFLAGS; - break; - case EXT2_IOC32_SETFLAGS: - cmd = EXT2_IOC_SETFLAGS; - break; case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; |
