Linux 6.9-rc1
[linux-2.6-microblaze.git] / fs / ioctl.c
index 80ac36a..1d5abfd 100644 (file)
@@ -109,9 +109,6 @@ static int ioctl_fibmap(struct file *filp, int __user *p)
  * Returns 0 on success, -errno on error, 1 if this was the last
  * extent that will fit in user array.
  */
-#define SET_UNKNOWN_FLAGS      (FIEMAP_EXTENT_DELALLOC)
-#define SET_NO_UNMOUNTED_IO_FLAGS      (FIEMAP_EXTENT_DATA_ENCRYPTED)
-#define SET_NOT_ALIGNED_FLAGS  (FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
 int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
                            u64 phys, u64 len, u32 flags)
 {
@@ -127,6 +124,10 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
        if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
                return 1;
 
+#define SET_UNKNOWN_FLAGS      (FIEMAP_EXTENT_DELALLOC)
+#define SET_NO_UNMOUNTED_IO_FLAGS      (FIEMAP_EXTENT_DATA_ENCRYPTED)
+#define SET_NOT_ALIGNED_FLAGS  (FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
+
        if (flags & SET_UNKNOWN_FLAGS)
                flags |= FIEMAP_EXTENT_UNKNOWN;
        if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
@@ -396,8 +397,8 @@ static int ioctl_fsfreeze(struct file *filp)
 
        /* Freeze */
        if (sb->s_op->freeze_super)
-               return sb->s_op->freeze_super(sb);
-       return freeze_super(sb);
+               return sb->s_op->freeze_super(sb, FREEZE_HOLDER_USERSPACE);
+       return freeze_super(sb, FREEZE_HOLDER_USERSPACE);
 }
 
 static int ioctl_fsthaw(struct file *filp)
@@ -409,8 +410,8 @@ static int ioctl_fsthaw(struct file *filp)
 
        /* Thaw */
        if (sb->s_op->thaw_super)
-               return sb->s_op->thaw_super(sb);
-       return thaw_super(sb);
+               return sb->s_op->thaw_super(sb, FREEZE_HOLDER_USERSPACE);
+       return thaw_super(sb, FREEZE_HOLDER_USERSPACE);
 }
 
 static int ioctl_file_dedupe_range(struct file *file,
@@ -651,7 +652,7 @@ static int fileattr_set_prepare(struct inode *inode,
 
 /**
  * vfs_fileattr_set - change miscellaneous file attributes
- * @mnt_userns:        user namespace of the mount
+ * @idmap:     idmap of the mount
  * @dentry:    the object to change
  * @fa:                fileattr pointer
  *
@@ -665,7 +666,7 @@ static int fileattr_set_prepare(struct inode *inode,
  *
  * Return: 0 on success, or a negative error on failure.
  */
-int vfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry,
+int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
                     struct fileattr *fa)
 {
        struct inode *inode = d_inode(dentry);
@@ -675,7 +676,7 @@ int vfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (!inode->i_op->fileattr_set)
                return -ENOIOCTLCMD;
 
-       if (!inode_owner_or_capable(mnt_userns, inode))
+       if (!inode_owner_or_capable(idmap, inode))
                return -EPERM;
 
        inode_lock(inode);
@@ -693,7 +694,7 @@ int vfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry,
                }
                err = fileattr_set_prepare(inode, &old_ma, fa);
                if (!err)
-                       err = inode->i_op->fileattr_set(mnt_userns, dentry, fa);
+                       err = inode->i_op->fileattr_set(idmap, dentry, fa);
        }
        inode_unlock(inode);
 
@@ -714,7 +715,7 @@ static int ioctl_getflags(struct file *file, unsigned int __user *argp)
 
 static int ioctl_setflags(struct file *file, unsigned int __user *argp)
 {
-       struct user_namespace *mnt_userns = file_mnt_user_ns(file);
+       struct mnt_idmap *idmap = file_mnt_idmap(file);
        struct dentry *dentry = file->f_path.dentry;
        struct fileattr fa;
        unsigned int flags;
@@ -725,7 +726,7 @@ static int ioctl_setflags(struct file *file, unsigned int __user *argp)
                err = mnt_want_write_file(file);
                if (!err) {
                        fileattr_fill_flags(&fa, flags);
-                       err = vfs_fileattr_set(mnt_userns, dentry, &fa);
+                       err = vfs_fileattr_set(idmap, dentry, &fa);
                        mnt_drop_write_file(file);
                }
        }
@@ -746,7 +747,7 @@ static int ioctl_fsgetxattr(struct file *file, void __user *argp)
 
 static int ioctl_fssetxattr(struct file *file, void __user *argp)
 {
-       struct user_namespace *mnt_userns = file_mnt_user_ns(file);
+       struct mnt_idmap *idmap = file_mnt_idmap(file);
        struct dentry *dentry = file->f_path.dentry;
        struct fileattr fa;
        int err;
@@ -755,13 +756,40 @@ static int ioctl_fssetxattr(struct file *file, void __user *argp)
        if (!err) {
                err = mnt_want_write_file(file);
                if (!err) {
-                       err = vfs_fileattr_set(mnt_userns, dentry, &fa);
+                       err = vfs_fileattr_set(idmap, dentry, &fa);
                        mnt_drop_write_file(file);
                }
        }
        return err;
 }
 
+static int ioctl_getfsuuid(struct file *file, void __user *argp)
+{
+       struct super_block *sb = file_inode(file)->i_sb;
+       struct fsuuid2 u = { .len = sb->s_uuid_len, };
+
+       if (!sb->s_uuid_len)
+               return -ENOIOCTLCMD;
+
+       memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
+
+       return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
+}
+
+static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
+{
+       struct super_block *sb = file_inode(file)->i_sb;
+
+       if (!strlen(sb->s_sysfs_name))
+               return -ENOIOCTLCMD;
+
+       struct fs_sysfs_path u = {};
+
+       u.len = scnprintf(u.name, sizeof(u.name), "%s/%s", sb->s_type->name, sb->s_sysfs_name);
+
+       return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
+}
+
 /*
  * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
@@ -844,6 +872,12 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
        case FS_IOC_FSSETXATTR:
                return ioctl_fssetxattr(filp, argp);
 
+       case FS_IOC_GETFSUUID:
+               return ioctl_getfsuuid(filp, argp);
+
+       case FS_IOC_GETFSSYSFSPATH:
+               return ioctl_get_fs_sysfs_path(filp, argp);
+
        default:
                if (S_ISREG(inode->i_mode))
                        return file_ioctl(filp, cmd, argp);
@@ -877,6 +911,9 @@ out:
 #ifdef CONFIG_COMPAT
 /**
  * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
+ * @file: The file to operate on.
+ * @cmd: The ioctl command number.
+ * @arg: The argument to the ioctl.
  *
  * This is not normally called as a function, but instead set in struct
  * file_operations as
@@ -916,8 +953,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
        if (!f.file)
                return -EBADF;
 
-       /* RED-PEN how should LSM module know it's handling 32bit? */
-       error = security_file_ioctl(f.file, cmd, arg);
+       error = security_file_ioctl_compat(f.file, cmd, arg);
        if (error)
                goto out;