efi: Fix a race and a buffer overflow while reading efivars via sysfs
[platform/kernel/linux-rpi.git] / drivers / firmware / efi / efivars.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Originally from efivars.c,
4  *
5  * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
6  * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
7  *
8  * This code takes all variables accessible from EFI runtime and
9  *  exports them via sysfs
10  */
11
12 #include <linux/efi.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/ucs2_string.h>
16 #include <linux/compat.h>
17
18 #define EFIVARS_VERSION "0.08"
19 #define EFIVARS_DATE "2004-May-17"
20
21 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
22 MODULE_DESCRIPTION("sysfs interface to EFI Variables");
23 MODULE_LICENSE("GPL");
24 MODULE_VERSION(EFIVARS_VERSION);
25 MODULE_ALIAS("platform:efivars");
26
27 LIST_HEAD(efivar_sysfs_list);
28 EXPORT_SYMBOL_GPL(efivar_sysfs_list);
29
30 static struct kset *efivars_kset;
31
32 static struct bin_attribute *efivars_new_var;
33 static struct bin_attribute *efivars_del_var;
34
35 struct compat_efi_variable {
36         efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
37         efi_guid_t    VendorGuid;
38         __u32         DataSize;
39         __u8          Data[1024];
40         __u32         Status;
41         __u32         Attributes;
42 } __packed;
43
44 struct efivar_attribute {
45         struct attribute attr;
46         ssize_t (*show) (struct efivar_entry *entry, char *buf);
47         ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
48 };
49
50 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
51 struct efivar_attribute efivar_attr_##_name = { \
52         .attr = {.name = __stringify(_name), .mode = _mode}, \
53         .show = _show, \
54         .store = _store, \
55 };
56
57 #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
58 #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
59
60 /*
61  * Prototype for sysfs creation function
62  */
63 static int
64 efivar_create_sysfs_entry(struct efivar_entry *new_var);
65
66 static ssize_t
67 efivar_guid_read(struct efivar_entry *entry, char *buf)
68 {
69         struct efi_variable *var = &entry->var;
70         char *str = buf;
71
72         if (!entry || !buf)
73                 return 0;
74
75         efi_guid_to_str(&var->VendorGuid, str);
76         str += strlen(str);
77         str += sprintf(str, "\n");
78
79         return str - buf;
80 }
81
82 static ssize_t
83 efivar_attr_read(struct efivar_entry *entry, char *buf)
84 {
85         struct efi_variable *var = &entry->var;
86         unsigned long size = sizeof(var->Data);
87         char *str = buf;
88         int ret;
89
90         if (!entry || !buf)
91                 return -EINVAL;
92
93         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
94         var->DataSize = size;
95         if (ret)
96                 return -EIO;
97
98         if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
99                 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
100         if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
101                 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
102         if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
103                 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
104         if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
105                 str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
106         if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
107                 str += sprintf(str,
108                         "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
109         if (var->Attributes &
110                         EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
111                 str += sprintf(str,
112                         "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
113         if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
114                 str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
115         return str - buf;
116 }
117
118 static ssize_t
119 efivar_size_read(struct efivar_entry *entry, char *buf)
120 {
121         struct efi_variable *var = &entry->var;
122         unsigned long size = sizeof(var->Data);
123         char *str = buf;
124         int ret;
125
126         if (!entry || !buf)
127                 return -EINVAL;
128
129         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
130         var->DataSize = size;
131         if (ret)
132                 return -EIO;
133
134         str += sprintf(str, "0x%lx\n", var->DataSize);
135         return str - buf;
136 }
137
138 static ssize_t
139 efivar_data_read(struct efivar_entry *entry, char *buf)
140 {
141         struct efi_variable *var = &entry->var;
142         unsigned long size = sizeof(var->Data);
143         int ret;
144
145         if (!entry || !buf)
146                 return -EINVAL;
147
148         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
149         var->DataSize = size;
150         if (ret)
151                 return -EIO;
152
153         memcpy(buf, var->Data, var->DataSize);
154         return var->DataSize;
155 }
156
157 static inline int
158 sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
159              unsigned long size, u32 attributes, u8 *data)
160 {
161         /*
162          * If only updating the variable data, then the name
163          * and guid should remain the same
164          */
165         if (memcmp(name, var->VariableName, sizeof(var->VariableName)) ||
166                 efi_guidcmp(vendor, var->VendorGuid)) {
167                 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
168                 return -EINVAL;
169         }
170
171         if ((size <= 0) || (attributes == 0)){
172                 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
173                 return -EINVAL;
174         }
175
176         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
177             efivar_validate(vendor, name, data, size) == false) {
178                 printk(KERN_ERR "efivars: Malformed variable content\n");
179                 return -EINVAL;
180         }
181
182         return 0;
183 }
184
185 static void
186 copy_out_compat(struct efi_variable *dst, struct compat_efi_variable *src)
187 {
188         memcpy(dst->VariableName, src->VariableName, EFI_VAR_NAME_LEN);
189         memcpy(dst->Data, src->Data, sizeof(src->Data));
190
191         dst->VendorGuid = src->VendorGuid;
192         dst->DataSize = src->DataSize;
193         dst->Attributes = src->Attributes;
194 }
195
196 /*
197  * We allow each variable to be edited via rewriting the
198  * entire efi variable structure.
199  */
200 static ssize_t
201 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
202 {
203         struct efi_variable *new_var, *var = &entry->var;
204         efi_char16_t *name;
205         unsigned long size;
206         efi_guid_t vendor;
207         u32 attributes;
208         u8 *data;
209         int err;
210
211         if (in_compat_syscall()) {
212                 struct compat_efi_variable *compat;
213
214                 if (count != sizeof(*compat))
215                         return -EINVAL;
216
217                 compat = (struct compat_efi_variable *)buf;
218                 attributes = compat->Attributes;
219                 vendor = compat->VendorGuid;
220                 name = compat->VariableName;
221                 size = compat->DataSize;
222                 data = compat->Data;
223
224                 err = sanity_check(var, name, vendor, size, attributes, data);
225                 if (err)
226                         return err;
227
228                 copy_out_compat(&entry->var, compat);
229         } else {
230                 if (count != sizeof(struct efi_variable))
231                         return -EINVAL;
232
233                 new_var = (struct efi_variable *)buf;
234
235                 attributes = new_var->Attributes;
236                 vendor = new_var->VendorGuid;
237                 name = new_var->VariableName;
238                 size = new_var->DataSize;
239                 data = new_var->Data;
240
241                 err = sanity_check(var, name, vendor, size, attributes, data);
242                 if (err)
243                         return err;
244
245                 memcpy(&entry->var, new_var, count);
246         }
247
248         err = efivar_entry_set(entry, attributes, size, data, NULL);
249         if (err) {
250                 printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
251                 return -EIO;
252         }
253
254         return count;
255 }
256
257 static ssize_t
258 efivar_show_raw(struct efivar_entry *entry, char *buf)
259 {
260         struct efi_variable *var = &entry->var;
261         struct compat_efi_variable *compat;
262         unsigned long datasize = sizeof(var->Data);
263         size_t size;
264         int ret;
265
266         if (!entry || !buf)
267                 return 0;
268
269         ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
270         var->DataSize = datasize;
271         if (ret)
272                 return -EIO;
273
274         if (in_compat_syscall()) {
275                 compat = (struct compat_efi_variable *)buf;
276
277                 size = sizeof(*compat);
278                 memcpy(compat->VariableName, var->VariableName,
279                         EFI_VAR_NAME_LEN);
280                 memcpy(compat->Data, var->Data, sizeof(compat->Data));
281
282                 compat->VendorGuid = var->VendorGuid;
283                 compat->DataSize = var->DataSize;
284                 compat->Attributes = var->Attributes;
285         } else {
286                 size = sizeof(*var);
287                 memcpy(buf, var, size);
288         }
289
290         return size;
291 }
292
293 /*
294  * Generic read/write functions that call the specific functions of
295  * the attributes...
296  */
297 static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
298                                 char *buf)
299 {
300         struct efivar_entry *var = to_efivar_entry(kobj);
301         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
302         ssize_t ret = -EIO;
303
304         if (!capable(CAP_SYS_ADMIN))
305                 return -EACCES;
306
307         if (efivar_attr->show) {
308                 ret = efivar_attr->show(var, buf);
309         }
310         return ret;
311 }
312
313 static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
314                                 const char *buf, size_t count)
315 {
316         struct efivar_entry *var = to_efivar_entry(kobj);
317         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
318         ssize_t ret = -EIO;
319
320         if (!capable(CAP_SYS_ADMIN))
321                 return -EACCES;
322
323         if (efivar_attr->store)
324                 ret = efivar_attr->store(var, buf, count);
325
326         return ret;
327 }
328
329 static const struct sysfs_ops efivar_attr_ops = {
330         .show = efivar_attr_show,
331         .store = efivar_attr_store,
332 };
333
334 static void efivar_release(struct kobject *kobj)
335 {
336         struct efivar_entry *var = to_efivar_entry(kobj);
337         kfree(var);
338 }
339
340 static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
341 static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
342 static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
343 static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
344 static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
345
346 static struct attribute *def_attrs[] = {
347         &efivar_attr_guid.attr,
348         &efivar_attr_size.attr,
349         &efivar_attr_attributes.attr,
350         &efivar_attr_data.attr,
351         &efivar_attr_raw_var.attr,
352         NULL,
353 };
354
355 static struct kobj_type efivar_ktype = {
356         .release = efivar_release,
357         .sysfs_ops = &efivar_attr_ops,
358         .default_attrs = def_attrs,
359 };
360
361 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
362                              struct bin_attribute *bin_attr,
363                              char *buf, loff_t pos, size_t count)
364 {
365         struct compat_efi_variable *compat = (struct compat_efi_variable *)buf;
366         struct efi_variable *new_var = (struct efi_variable *)buf;
367         struct efivar_entry *new_entry;
368         bool need_compat = in_compat_syscall();
369         efi_char16_t *name;
370         unsigned long size;
371         u32 attributes;
372         u8 *data;
373         int err;
374
375         if (!capable(CAP_SYS_ADMIN))
376                 return -EACCES;
377
378         if (need_compat) {
379                 if (count != sizeof(*compat))
380                         return -EINVAL;
381
382                 attributes = compat->Attributes;
383                 name = compat->VariableName;
384                 size = compat->DataSize;
385                 data = compat->Data;
386         } else {
387                 if (count != sizeof(*new_var))
388                         return -EINVAL;
389
390                 attributes = new_var->Attributes;
391                 name = new_var->VariableName;
392                 size = new_var->DataSize;
393                 data = new_var->Data;
394         }
395
396         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
397             efivar_validate(new_var->VendorGuid, name, data,
398                             size) == false) {
399                 printk(KERN_ERR "efivars: Malformed variable content\n");
400                 return -EINVAL;
401         }
402
403         new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
404         if (!new_entry)
405                 return -ENOMEM;
406
407         if (need_compat)
408                 copy_out_compat(&new_entry->var, compat);
409         else
410                 memcpy(&new_entry->var, new_var, sizeof(*new_var));
411
412         err = efivar_entry_set(new_entry, attributes, size,
413                                data, &efivar_sysfs_list);
414         if (err) {
415                 if (err == -EEXIST)
416                         err = -EINVAL;
417                 goto out;
418         }
419
420         if (efivar_create_sysfs_entry(new_entry)) {
421                 printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
422                 kfree(new_entry);
423         }
424         return count;
425
426 out:
427         kfree(new_entry);
428         return err;
429 }
430
431 static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
432                              struct bin_attribute *bin_attr,
433                              char *buf, loff_t pos, size_t count)
434 {
435         struct efi_variable *del_var = (struct efi_variable *)buf;
436         struct compat_efi_variable *compat;
437         struct efivar_entry *entry;
438         efi_char16_t *name;
439         efi_guid_t vendor;
440         int err = 0;
441
442         if (!capable(CAP_SYS_ADMIN))
443                 return -EACCES;
444
445         if (in_compat_syscall()) {
446                 if (count != sizeof(*compat))
447                         return -EINVAL;
448
449                 compat = (struct compat_efi_variable *)buf;
450                 name = compat->VariableName;
451                 vendor = compat->VendorGuid;
452         } else {
453                 if (count != sizeof(*del_var))
454                         return -EINVAL;
455
456                 name = del_var->VariableName;
457                 vendor = del_var->VendorGuid;
458         }
459
460         if (efivar_entry_iter_begin())
461                 return -EINTR;
462         entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true);
463         if (!entry)
464                 err = -EINVAL;
465         else if (__efivar_entry_delete(entry))
466                 err = -EIO;
467
468         if (err) {
469                 efivar_entry_iter_end();
470                 return err;
471         }
472
473         if (!entry->scanning) {
474                 efivar_entry_iter_end();
475                 efivar_unregister(entry);
476         } else
477                 efivar_entry_iter_end();
478
479         /* It's dead Jim.... */
480         return count;
481 }
482
483 /**
484  * efivar_create_sysfs_entry - create a new entry in sysfs
485  * @new_var: efivar entry to create
486  *
487  * Returns 0 on success, negative error code on failure
488  */
489 static int
490 efivar_create_sysfs_entry(struct efivar_entry *new_var)
491 {
492         int short_name_size;
493         char *short_name;
494         unsigned long utf8_name_size;
495         efi_char16_t *variable_name = new_var->var.VariableName;
496         int ret;
497
498         /*
499          * Length of the variable bytes in UTF8, plus the '-' separator,
500          * plus the GUID, plus trailing NUL
501          */
502         utf8_name_size = ucs2_utf8size(variable_name);
503         short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
504
505         short_name = kmalloc(short_name_size, GFP_KERNEL);
506         if (!short_name)
507                 return -ENOMEM;
508
509         ucs2_as_utf8(short_name, variable_name, short_name_size);
510
511         /* This is ugly, but necessary to separate one vendor's
512            private variables from another's.         */
513         short_name[utf8_name_size] = '-';
514         efi_guid_to_str(&new_var->var.VendorGuid,
515                          short_name + utf8_name_size + 1);
516
517         new_var->kobj.kset = efivars_kset;
518
519         ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
520                                    NULL, "%s", short_name);
521         kfree(short_name);
522         if (ret)
523                 return ret;
524
525         kobject_uevent(&new_var->kobj, KOBJ_ADD);
526         if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
527                 efivar_unregister(new_var);
528                 return -EINTR;
529         }
530
531         return 0;
532 }
533
534 static int
535 create_efivars_bin_attributes(void)
536 {
537         struct bin_attribute *attr;
538         int error;
539
540         /* new_var */
541         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
542         if (!attr)
543                 return -ENOMEM;
544
545         attr->attr.name = "new_var";
546         attr->attr.mode = 0200;
547         attr->write = efivar_create;
548         efivars_new_var = attr;
549
550         /* del_var */
551         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
552         if (!attr) {
553                 error = -ENOMEM;
554                 goto out_free;
555         }
556         attr->attr.name = "del_var";
557         attr->attr.mode = 0200;
558         attr->write = efivar_delete;
559         efivars_del_var = attr;
560
561         sysfs_bin_attr_init(efivars_new_var);
562         sysfs_bin_attr_init(efivars_del_var);
563
564         /* Register */
565         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
566         if (error) {
567                 printk(KERN_ERR "efivars: unable to create new_var sysfs file"
568                         " due to error %d\n", error);
569                 goto out_free;
570         }
571
572         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
573         if (error) {
574                 printk(KERN_ERR "efivars: unable to create del_var sysfs file"
575                         " due to error %d\n", error);
576                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
577                 goto out_free;
578         }
579
580         return 0;
581 out_free:
582         kfree(efivars_del_var);
583         efivars_del_var = NULL;
584         kfree(efivars_new_var);
585         efivars_new_var = NULL;
586         return error;
587 }
588
589 static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
590                                      unsigned long name_size, void *data)
591 {
592         struct efivar_entry *entry = data;
593
594         if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
595                 return 0;
596
597         memcpy(entry->var.VariableName, name, name_size);
598         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
599
600         return 1;
601 }
602
603 static void efivar_update_sysfs_entries(struct work_struct *work)
604 {
605         struct efivar_entry *entry;
606         int err;
607
608         /* Add new sysfs entries */
609         while (1) {
610                 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
611                 if (!entry)
612                         return;
613
614                 err = efivar_init(efivar_update_sysfs_entry, entry,
615                                   false, &efivar_sysfs_list);
616                 if (!err)
617                         break;
618
619                 efivar_create_sysfs_entry(entry);
620         }
621
622         kfree(entry);
623 }
624
625 static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
626                                   unsigned long name_size, void *data)
627 {
628         struct efivar_entry *entry;
629
630         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
631         if (!entry)
632                 return -ENOMEM;
633
634         memcpy(entry->var.VariableName, name, name_size);
635         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
636
637         efivar_create_sysfs_entry(entry);
638
639         return 0;
640 }
641
642 static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
643 {
644         int err = efivar_entry_remove(entry);
645
646         if (err)
647                 return err;
648         efivar_unregister(entry);
649         return 0;
650 }
651
652 static void efivars_sysfs_exit(void)
653 {
654         /* Remove all entries and destroy */
655         int err;
656
657         err = __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list,
658                                   NULL, NULL);
659         if (err) {
660                 pr_err("efivars: Failed to destroy sysfs entries\n");
661                 return;
662         }
663
664         if (efivars_new_var)
665                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
666         if (efivars_del_var)
667                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
668         kfree(efivars_new_var);
669         kfree(efivars_del_var);
670         kset_unregister(efivars_kset);
671 }
672
673 int efivars_sysfs_init(void)
674 {
675         struct kobject *parent_kobj = efivars_kobject();
676         int error = 0;
677
678         if (!efi_enabled(EFI_RUNTIME_SERVICES))
679                 return -ENODEV;
680
681         /* No efivars has been registered yet */
682         if (!parent_kobj)
683                 return 0;
684
685         printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
686                EFIVARS_DATE);
687
688         efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
689         if (!efivars_kset) {
690                 printk(KERN_ERR "efivars: Subsystem registration failed.\n");
691                 return -ENOMEM;
692         }
693
694         efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list);
695
696         error = create_efivars_bin_attributes();
697         if (error) {
698                 efivars_sysfs_exit();
699                 return error;
700         }
701
702         INIT_WORK(&efivar_work, efivar_update_sysfs_entries);
703
704         return 0;
705 }
706 EXPORT_SYMBOL_GPL(efivars_sysfs_init);
707
708 module_init(efivars_sysfs_init);
709 module_exit(efivars_sysfs_exit);