1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2012 Red Hat, Inc. 4 * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com> 5 */ 6 7 #include <linux/ctype.h> 8 #include <linux/efi.h> 9 #include <linux/fs.h> 10 #include <linux/fs_context.h> 11 #include <linux/fs_parser.h> 12 #include <linux/module.h> 13 #include <linux/pagemap.h> 14 #include <linux/ucs2_string.h> 15 #include <linux/slab.h> 16 #include <linux/magic.h> 17 #include <linux/statfs.h> 18 19 #include "internal.h" 20 21 LIST_HEAD(efivarfs_list); 22 23 static void efivarfs_evict_inode(struct inode *inode) 24 { 25 clear_inode(inode); 26 } 27 28 static int efivarfs_show_options(struct seq_file *m, struct dentry *root) 29 { 30 struct super_block *sb = root->d_sb; 31 struct efivarfs_fs_info *sbi = sb->s_fs_info; 32 struct efivarfs_mount_opts *opts = &sbi->mount_opts; 33 34 if (!uid_eq(opts->uid, GLOBAL_ROOT_UID)) 35 seq_printf(m, ",uid=%u", 36 from_kuid_munged(&init_user_ns, opts->uid)); 37 if (!gid_eq(opts->gid, GLOBAL_ROOT_GID)) 38 seq_printf(m, ",gid=%u", 39 from_kgid_munged(&init_user_ns, opts->gid)); 40 return 0; 41 } 42 43 static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) 44 { 45 const u32 attr = EFI_VARIABLE_NON_VOLATILE | 46 EFI_VARIABLE_BOOTSERVICE_ACCESS | 47 EFI_VARIABLE_RUNTIME_ACCESS; 48 u64 storage_space, remaining_space, max_variable_size; 49 u64 id = huge_encode_dev(dentry->d_sb->s_dev); 50 efi_status_t status; 51 52 /* Some UEFI firmware does not implement QueryVariableInfo() */ 53 storage_space = remaining_space = 0; 54 if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { 55 status = efivar_query_variable_info(attr, &storage_space, 56 &remaining_space, 57 &max_variable_size); 58 if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) 59 pr_warn_ratelimited("query_variable_info() failed: 0x%lx\n", 60 status); 61 } 62 63 /* 64 * This is not a normal filesystem, so no point in pretending it has a block 65 * size; we declare f_bsize to 1, so that we can then report the exact value 66 * sent by EFI QueryVariableInfo in f_blocks and f_bfree 67 */ 68 buf->f_bsize = 1; 69 buf->f_namelen = NAME_MAX; 70 buf->f_blocks = storage_space; 71 buf->f_bfree = remaining_space; 72 buf->f_type = dentry->d_sb->s_magic; 73 buf->f_fsid = u64_to_fsid(id); 74 75 /* 76 * In f_bavail we declare the free space that the kernel will allow writing 77 * when the storage_paranoia x86 quirk is active. To use more, users 78 * should boot the kernel with efi_no_storage_paranoia. 79 */ 80 if (remaining_space > efivar_reserved_space()) 81 buf->f_bavail = remaining_space - efivar_reserved_space(); 82 else 83 buf->f_bavail = 0; 84 85 return 0; 86 } 87 static const struct super_operations efivarfs_ops = { 88 .statfs = efivarfs_statfs, 89 .drop_inode = generic_delete_inode, 90 .evict_inode = efivarfs_evict_inode, 91 .show_options = efivarfs_show_options, 92 }; 93 94 /* 95 * Compare two efivarfs file names. 96 * 97 * An efivarfs filename is composed of two parts, 98 * 99 * 1. A case-sensitive variable name 100 * 2. A case-insensitive GUID 101 * 102 * So we need to perform a case-sensitive match on part 1 and a 103 * case-insensitive match on part 2. 104 */ 105 static int efivarfs_d_compare(const struct dentry *dentry, 106 unsigned int len, const char *str, 107 const struct qstr *name) 108 { 109 int guid = len - EFI_VARIABLE_GUID_LEN; 110 111 if (name->len != len) 112 return 1; 113 114 /* Case-sensitive compare for the variable name */ 115 if (memcmp(str, name->name, guid)) 116 return 1; 117 118 /* Case-insensitive compare for the GUID */ 119 return strncasecmp(name->name + guid, str + guid, EFI_VARIABLE_GUID_LEN); 120 } 121 122 static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr) 123 { 124 unsigned long hash = init_name_hash(dentry); 125 const unsigned char *s = qstr->name; 126 unsigned int len = qstr->len; 127 128 if (!efivarfs_valid_name(s, len)) 129 return -EINVAL; 130 131 while (len-- > EFI_VARIABLE_GUID_LEN) 132 hash = partial_name_hash(*s++, hash); 133 134 /* GUID is case-insensitive. */ 135 while (len--) 136 hash = partial_name_hash(tolower(*s++), hash); 137 138 qstr->hash = end_name_hash(hash); 139 return 0; 140 } 141 142 static const struct dentry_operations efivarfs_d_ops = { 143 .d_compare = efivarfs_d_compare, 144 .d_hash = efivarfs_d_hash, 145 .d_delete = always_delete_dentry, 146 }; 147 148 static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) 149 { 150 struct dentry *d; 151 struct qstr q; 152 int err; 153 154 q.name = name; 155 q.len = strlen(name); 156 157 err = efivarfs_d_hash(parent, &q); 158 if (err) 159 return ERR_PTR(err); 160 161 d = d_alloc(parent, &q); 162 if (d) 163 return d; 164 165 return ERR_PTR(-ENOMEM); 166 } 167 168 static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, 169 unsigned long name_size, void *data) 170 { 171 struct super_block *sb = (struct super_block *)data; 172 struct efivar_entry *entry; 173 struct inode *inode = NULL; 174 struct dentry *dentry, *root = sb->s_root; 175 unsigned long size = 0; 176 char *name; 177 int len; 178 int err = -ENOMEM; 179 bool is_removable = false; 180 181 if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) 182 return 0; 183 184 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 185 if (!entry) 186 return err; 187 188 memcpy(entry->var.VariableName, name16, name_size); 189 memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 190 191 len = ucs2_utf8size(entry->var.VariableName); 192 193 /* name, plus '-', plus GUID, plus NUL*/ 194 name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); 195 if (!name) 196 goto fail; 197 198 ucs2_as_utf8(name, entry->var.VariableName, len); 199 200 if (efivar_variable_is_removable(entry->var.VendorGuid, name, len)) 201 is_removable = true; 202 203 name[len] = '-'; 204 205 efi_guid_to_str(&entry->var.VendorGuid, name + len + 1); 206 207 name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; 208 209 /* replace invalid slashes like kobject_set_name_vargs does for /sys/firmware/efi/vars. */ 210 strreplace(name, '/', '!'); 211 212 inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0, 213 is_removable); 214 if (!inode) 215 goto fail_name; 216 217 dentry = efivarfs_alloc_dentry(root, name); 218 if (IS_ERR(dentry)) { 219 err = PTR_ERR(dentry); 220 goto fail_inode; 221 } 222 223 __efivar_entry_get(entry, NULL, &size, NULL); 224 __efivar_entry_add(entry, &efivarfs_list); 225 226 /* copied by the above to local storage in the dentry. */ 227 kfree(name); 228 229 inode_lock(inode); 230 inode->i_private = entry; 231 i_size_write(inode, size + sizeof(entry->var.Attributes)); 232 inode_unlock(inode); 233 d_add(dentry, inode); 234 235 return 0; 236 237 fail_inode: 238 iput(inode); 239 fail_name: 240 kfree(name); 241 fail: 242 kfree(entry); 243 return err; 244 } 245 246 static int efivarfs_destroy(struct efivar_entry *entry, void *data) 247 { 248 efivar_entry_remove(entry); 249 kfree(entry); 250 return 0; 251 } 252 253 enum { 254 Opt_uid, Opt_gid, 255 }; 256 257 static const struct fs_parameter_spec efivarfs_parameters[] = { 258 fsparam_u32("uid", Opt_uid), 259 fsparam_u32("gid", Opt_gid), 260 {}, 261 }; 262 263 static int efivarfs_parse_param(struct fs_context *fc, struct fs_parameter *param) 264 { 265 struct efivarfs_fs_info *sbi = fc->s_fs_info; 266 struct efivarfs_mount_opts *opts = &sbi->mount_opts; 267 struct fs_parse_result result; 268 int opt; 269 270 opt = fs_parse(fc, efivarfs_parameters, param, &result); 271 if (opt < 0) 272 return opt; 273 274 switch (opt) { 275 case Opt_uid: 276 opts->uid = make_kuid(current_user_ns(), result.uint_32); 277 if (!uid_valid(opts->uid)) 278 return -EINVAL; 279 break; 280 case Opt_gid: 281 opts->gid = make_kgid(current_user_ns(), result.uint_32); 282 if (!gid_valid(opts->gid)) 283 return -EINVAL; 284 break; 285 default: 286 return -EINVAL; 287 } 288 289 return 0; 290 } 291 292 static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc) 293 { 294 struct inode *inode = NULL; 295 struct dentry *root; 296 int err; 297 298 if (!efivar_is_available()) 299 return -EOPNOTSUPP; 300 301 sb->s_maxbytes = MAX_LFS_FILESIZE; 302 sb->s_blocksize = PAGE_SIZE; 303 sb->s_blocksize_bits = PAGE_SHIFT; 304 sb->s_magic = EFIVARFS_MAGIC; 305 sb->s_op = &efivarfs_ops; 306 sb->s_d_op = &efivarfs_d_ops; 307 sb->s_time_gran = 1; 308 309 if (!efivar_supports_writes()) 310 sb->s_flags |= SB_RDONLY; 311 312 inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true); 313 if (!inode) 314 return -ENOMEM; 315 inode->i_op = &efivarfs_dir_inode_operations; 316 317 root = d_make_root(inode); 318 sb->s_root = root; 319 if (!root) 320 return -ENOMEM; 321 322 INIT_LIST_HEAD(&efivarfs_list); 323 324 err = efivar_init(efivarfs_callback, (void *)sb, true, &efivarfs_list); 325 if (err) 326 efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL); 327 328 return err; 329 } 330 331 static int efivarfs_get_tree(struct fs_context *fc) 332 { 333 return get_tree_single(fc, efivarfs_fill_super); 334 } 335 336 static const struct fs_context_operations efivarfs_context_ops = { 337 .get_tree = efivarfs_get_tree, 338 .parse_param = efivarfs_parse_param, 339 }; 340 341 static int efivarfs_init_fs_context(struct fs_context *fc) 342 { 343 struct efivarfs_fs_info *sfi; 344 345 sfi = kzalloc(sizeof(*sfi), GFP_KERNEL); 346 if (!sfi) 347 return -ENOMEM; 348 349 sfi->mount_opts.uid = GLOBAL_ROOT_UID; 350 sfi->mount_opts.gid = GLOBAL_ROOT_GID; 351 352 fc->s_fs_info = sfi; 353 fc->ops = &efivarfs_context_ops; 354 return 0; 355 } 356 357 static void efivarfs_kill_sb(struct super_block *sb) 358 { 359 kill_litter_super(sb); 360 361 if (!efivar_is_available()) 362 return; 363 364 /* Remove all entries and destroy */ 365 efivar_entry_iter(efivarfs_destroy, &efivarfs_list, NULL); 366 } 367 368 static struct file_system_type efivarfs_type = { 369 .owner = THIS_MODULE, 370 .name = "efivarfs", 371 .init_fs_context = efivarfs_init_fs_context, 372 .kill_sb = efivarfs_kill_sb, 373 .parameters = efivarfs_parameters, 374 }; 375 376 static __init int efivarfs_init(void) 377 { 378 return register_filesystem(&efivarfs_type); 379 } 380 381 static __exit void efivarfs_exit(void) 382 { 383 unregister_filesystem(&efivarfs_type); 384 } 385 386 MODULE_AUTHOR("Matthew Garrett, Jeremy Kerr"); 387 MODULE_DESCRIPTION("EFI Variable Filesystem"); 388 MODULE_LICENSE("GPL"); 389 MODULE_ALIAS_FS("efivarfs"); 390 391 module_init(efivarfs_init); 392 module_exit(efivarfs_exit); 393