Loading fs/efivarfs/file.c +0 −77 Original line number Diff line number Diff line Loading @@ -106,86 +106,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, return size; } static inline unsigned int efivarfs_getflags(struct inode *inode) { unsigned int i_flags; unsigned int flags = 0; i_flags = inode->i_flags; if (i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; return flags; } static int efivarfs_ioc_getxflags(struct file *file, void __user *arg) { struct inode *inode = file->f_mapping->host; unsigned int flags = efivarfs_getflags(inode); if (copy_to_user(arg, &flags, sizeof(flags))) return -EFAULT; return 0; } static int efivarfs_ioc_setxflags(struct file *file, void __user *arg) { struct inode *inode = file->f_mapping->host; unsigned int flags; unsigned int i_flags = 0; unsigned int oldflags = efivarfs_getflags(inode); int error; if (!inode_owner_or_capable(&init_user_ns, inode)) return -EACCES; if (copy_from_user(&flags, arg, sizeof(flags))) return -EFAULT; if (flags & ~FS_IMMUTABLE_FL) return -EOPNOTSUPP; if (flags & FS_IMMUTABLE_FL) i_flags |= S_IMMUTABLE; error = mnt_want_write_file(file); if (error) return error; inode_lock(inode); error = vfs_ioc_setflags_prepare(inode, oldflags, flags); if (error) goto out; inode_set_flags(inode, i_flags, S_IMMUTABLE); out: inode_unlock(inode); mnt_drop_write_file(file); return error; } static long efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p) { void __user *arg = (void __user *)p; switch (cmd) { case FS_IOC_GETFLAGS: return efivarfs_ioc_getxflags(file, arg); case FS_IOC_SETFLAGS: return efivarfs_ioc_setxflags(file, arg); } return -ENOTTY; } const struct file_operations efivarfs_file_operations = { .open = simple_open, .read = efivarfs_file_read, .write = efivarfs_file_write, .llseek = no_llseek, .unlocked_ioctl = efivarfs_file_ioctl, }; fs/efivarfs/inode.c +44 −0 Original line number Diff line number Diff line Loading @@ -10,9 +10,12 @@ #include <linux/kmemleak.h> #include <linux/slab.h> #include <linux/uuid.h> #include <linux/fileattr.h> #include "internal.h" static const struct inode_operations efivarfs_file_inode_operations; struct inode *efivarfs_get_inode(struct super_block *sb, const struct inode *dir, int mode, dev_t dev, bool is_removable) Loading @@ -26,6 +29,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb, inode->i_flags = is_removable ? 0 : S_IMMUTABLE; switch (mode & S_IFMT) { case S_IFREG: inode->i_op = &efivarfs_file_inode_operations; inode->i_fop = &efivarfs_file_operations; break; case S_IFDIR: Loading Loading @@ -138,3 +142,43 @@ const struct inode_operations efivarfs_dir_inode_operations = { .unlink = efivarfs_unlink, .create = efivarfs_create, }; static int efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { unsigned int i_flags; unsigned int flags = 0; i_flags = d_inode(dentry)->i_flags; if (i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; fileattr_fill_flags(fa, flags); return 0; } static int efivarfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry, struct fileattr *fa) { unsigned int i_flags = 0; if (fileattr_has_fsx(fa)) return -EOPNOTSUPP; if (fa->flags & ~FS_IMMUTABLE_FL) return -EOPNOTSUPP; if (fa->flags & FS_IMMUTABLE_FL) i_flags |= S_IMMUTABLE; inode_set_flags(d_inode(dentry), i_flags, S_IMMUTABLE); return 0; } static const struct inode_operations efivarfs_file_inode_operations = { .fileattr_get = efivarfs_fileattr_get, .fileattr_set = efivarfs_fileattr_set, }; Loading
fs/efivarfs/file.c +0 −77 Original line number Diff line number Diff line Loading @@ -106,86 +106,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, return size; } static inline unsigned int efivarfs_getflags(struct inode *inode) { unsigned int i_flags; unsigned int flags = 0; i_flags = inode->i_flags; if (i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; return flags; } static int efivarfs_ioc_getxflags(struct file *file, void __user *arg) { struct inode *inode = file->f_mapping->host; unsigned int flags = efivarfs_getflags(inode); if (copy_to_user(arg, &flags, sizeof(flags))) return -EFAULT; return 0; } static int efivarfs_ioc_setxflags(struct file *file, void __user *arg) { struct inode *inode = file->f_mapping->host; unsigned int flags; unsigned int i_flags = 0; unsigned int oldflags = efivarfs_getflags(inode); int error; if (!inode_owner_or_capable(&init_user_ns, inode)) return -EACCES; if (copy_from_user(&flags, arg, sizeof(flags))) return -EFAULT; if (flags & ~FS_IMMUTABLE_FL) return -EOPNOTSUPP; if (flags & FS_IMMUTABLE_FL) i_flags |= S_IMMUTABLE; error = mnt_want_write_file(file); if (error) return error; inode_lock(inode); error = vfs_ioc_setflags_prepare(inode, oldflags, flags); if (error) goto out; inode_set_flags(inode, i_flags, S_IMMUTABLE); out: inode_unlock(inode); mnt_drop_write_file(file); return error; } static long efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p) { void __user *arg = (void __user *)p; switch (cmd) { case FS_IOC_GETFLAGS: return efivarfs_ioc_getxflags(file, arg); case FS_IOC_SETFLAGS: return efivarfs_ioc_setxflags(file, arg); } return -ENOTTY; } const struct file_operations efivarfs_file_operations = { .open = simple_open, .read = efivarfs_file_read, .write = efivarfs_file_write, .llseek = no_llseek, .unlocked_ioctl = efivarfs_file_ioctl, };
fs/efivarfs/inode.c +44 −0 Original line number Diff line number Diff line Loading @@ -10,9 +10,12 @@ #include <linux/kmemleak.h> #include <linux/slab.h> #include <linux/uuid.h> #include <linux/fileattr.h> #include "internal.h" static const struct inode_operations efivarfs_file_inode_operations; struct inode *efivarfs_get_inode(struct super_block *sb, const struct inode *dir, int mode, dev_t dev, bool is_removable) Loading @@ -26,6 +29,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb, inode->i_flags = is_removable ? 0 : S_IMMUTABLE; switch (mode & S_IFMT) { case S_IFREG: inode->i_op = &efivarfs_file_inode_operations; inode->i_fop = &efivarfs_file_operations; break; case S_IFDIR: Loading Loading @@ -138,3 +142,43 @@ const struct inode_operations efivarfs_dir_inode_operations = { .unlink = efivarfs_unlink, .create = efivarfs_create, }; static int efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { unsigned int i_flags; unsigned int flags = 0; i_flags = d_inode(dentry)->i_flags; if (i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; fileattr_fill_flags(fa, flags); return 0; } static int efivarfs_fileattr_set(struct user_namespace *mnt_userns, struct dentry *dentry, struct fileattr *fa) { unsigned int i_flags = 0; if (fileattr_has_fsx(fa)) return -EOPNOTSUPP; if (fa->flags & ~FS_IMMUTABLE_FL) return -EOPNOTSUPP; if (fa->flags & FS_IMMUTABLE_FL) i_flags |= S_IMMUTABLE; inode_set_flags(d_inode(dentry), i_flags, S_IMMUTABLE); return 0; } static const struct inode_operations efivarfs_file_inode_operations = { .fileattr_get = efivarfs_fileattr_get, .fileattr_set = efivarfs_fileattr_set, };