Blame view
fs/efivarfs/file.c
3.76 KB
d68772b7c efivarfs: Move to... |
1 2 3 4 5 6 7 8 9 10 11 |
/* * Copyright (C) 2012 Red Hat, Inc. * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/efi.h> #include <linux/fs.h> |
20b4fb485 Merge branch 'for... |
12 |
#include <linux/slab.h> |
ed8b0de5a efi: Make efivarf... |
13 |
#include <linux/mount.h> |
d68772b7c efivarfs: Move to... |
14 15 |
#include "internal.h" |
d68772b7c efivarfs: Move to... |
16 17 18 19 20 21 22 23 |
static ssize_t efivarfs_file_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct efivar_entry *var = file->private_data; void *data; u32 attributes; struct inode *inode = file->f_mapping->host; unsigned long datasize = count - sizeof(attributes); |
aca32b576 efivarfs: 'efivar... |
24 |
ssize_t bytes; |
d68772b7c efivarfs: Move to... |
25 26 27 28 29 30 31 32 33 34 |
bool set = false; if (count < sizeof(attributes)) return -EINVAL; if (copy_from_user(&attributes, userbuf, sizeof(attributes))) return -EFAULT; if (attributes & ~(EFI_VARIABLE_MASK)) return -EINVAL; |
aca32b576 efivarfs: 'efivar... |
35 36 37 |
data = memdup_user(userbuf + sizeof(attributes), datasize); if (IS_ERR(data)) return PTR_ERR(data); |
d68772b7c efivarfs: Move to... |
38 39 40 |
bytes = efivar_entry_set_get_size(var, attributes, &datasize, data, &set); |
3fab70c16 efivarfs: Never r... |
41 42 43 |
if (!set && bytes) { if (bytes == -ENOENT) bytes = -EIO; |
d68772b7c efivarfs: Move to... |
44 |
goto out; |
3fab70c16 efivarfs: Never r... |
45 |
} |
d68772b7c efivarfs: Move to... |
46 47 48 |
if (bytes == -ENOENT) { drop_nlink(inode); |
b583043e9 kill f_dentry uses |
49 50 |
d_delete(file->f_path.dentry); dput(file->f_path.dentry); |
d68772b7c efivarfs: Move to... |
51 |
} else { |
5955102c9 wrappers for ->i_... |
52 |
inode_lock(inode); |
d68772b7c efivarfs: Move to... |
53 |
i_size_write(inode, datasize + sizeof(attributes)); |
5955102c9 wrappers for ->i_... |
54 |
inode_unlock(inode); |
d68772b7c efivarfs: Move to... |
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
} bytes = count; out: kfree(data); return bytes; } static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct efivar_entry *var = file->private_data; unsigned long datasize = 0; u32 attributes; void *data; ssize_t size = 0; int err; err = efivar_entry_size(var, &datasize); |
3fab70c16 efivarfs: Never r... |
76 77 78 79 80 81 82 83 |
/* * efivarfs represents uncommitted variables with * zero-length files. Reading them should return EOF. */ if (err == -ENOENT) return 0; else if (err) |
d68772b7c efivarfs: Move to... |
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
return err; data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); if (!data) return -ENOMEM; size = efivar_entry_get(var, &attributes, &datasize, data + sizeof(attributes)); if (size) goto out_free; memcpy(data, &attributes, sizeof(attributes)); size = simple_read_from_buffer(userbuf, count, ppos, data, datasize + sizeof(attributes)); out_free: kfree(data); return size; } |
ed8b0de5a efi: Make efivarf... |
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
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; inode_lock(inode); inode_set_flags(inode, i_flags, S_IMMUTABLE); inode_unlock(inode); mnt_drop_write_file(file); return 0; } |
6c5450ef6 efivarfs: Make ef... |
156 |
static long |
ed8b0de5a efi: Make efivarf... |
157 158 159 160 161 162 163 164 165 166 167 168 169 |
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; } |
d68772b7c efivarfs: Move to... |
170 |
const struct file_operations efivarfs_file_operations = { |
f53f292ee Merge remote-trac... |
171 |
.open = simple_open, |
d68772b7c efivarfs: Move to... |
172 173 174 |
.read = efivarfs_file_read, .write = efivarfs_file_write, .llseek = no_llseek, |
ed8b0de5a efi: Make efivarf... |
175 |
.unlocked_ioctl = efivarfs_file_ioctl, |
d68772b7c efivarfs: Move to... |
176 |
}; |