diff options
author | Alex Shi <alex.shi@linaro.org> | 2016-03-18 11:41:51 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2016-03-18 16:01:49 +0800 |
commit | 70e00db9eb8ffc4dcaf5f035ec6a4440ba428794 (patch) | |
tree | ea67e279adedc950c3d4d8e98546b3823a2b3e93 /fs/efivarfs/file.c | |
parent | 34e0913e457f8469667faf5fa600447aa93371cf (diff) | |
parent | dfbed80c63bb8d965067da3a6dbcc4682edcce0c (diff) |
Merge remote-tracking branch 'lts/linux-3.14.y' into linux-linaro-lsk-v3.14lsk-v3.14-16.03linux-linaro-lsk-v3.14
Conflicts:
Most of conflicts are due to efivar_validate() change which
introduced a new parameter to check efi guid.
I added efi guid for this change in sanity_check()/efivar_create()
in drivers/firmware/efi/efivars.c
and keep new efivar_validate() in drivers/firmware/efi/vars.c,
since it's newer than LSK version.
nothing need mentioned in include/linux/efi.h
Diffstat (limited to 'fs/efivarfs/file.c')
-rw-r--r-- | fs/efivarfs/file.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c index 8dd524f32284..08f105a06fbf 100644 --- a/fs/efivarfs/file.c +++ b/fs/efivarfs/file.c @@ -10,6 +10,7 @@ #include <linux/efi.h> #include <linux/fs.h> #include <linux/slab.h> +#include <linux/mount.h> #include "internal.h" @@ -108,9 +109,79 @@ out_free: return size; } +static int +efivarfs_ioc_getxflags(struct file *file, void __user *arg) +{ + struct inode *inode = file->f_mapping->host; + unsigned int i_flags; + unsigned int flags = 0; + + i_flags = inode->i_flags; + if (i_flags & S_IMMUTABLE) + flags |= FS_IMMUTABLE_FL; + + 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; + int error; + + if (!inode_owner_or_capable(inode)) + return -EACCES; + + if (copy_from_user(&flags, arg, sizeof(flags))) + return -EFAULT; + + if (flags & ~FS_IMMUTABLE_FL) + return -EOPNOTSUPP; + + if (!capable(CAP_LINUX_IMMUTABLE)) + return -EPERM; + + if (flags & FS_IMMUTABLE_FL) + i_flags |= S_IMMUTABLE; + + + error = mnt_want_write_file(file); + if (error) + return error; + + mutex_lock(&inode->i_mutex); + inode->i_flags &= ~S_IMMUTABLE; + inode->i_flags |= i_flags; + mutex_unlock(&inode->i_mutex); + + mnt_drop_write_file(file); + + return 0; +} + +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, }; |