Merge branches 'acpi-apei', 'acpi-pmic', 'acpi-video' and 'acpi-dptf'
[sfrench/cifs-2.6.git] / drivers / firmware / efi / test / efi_test.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * EFI Test Driver for Runtime Services
4  *
5  * Copyright(C) 2012-2016 Canonical Ltd.
6  *
7  * This driver exports EFI runtime services interfaces into userspace, which
8  * allow to use and test UEFI runtime services provided by firmware.
9  *
10  */
11
12 #include <linux/miscdevice.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/proc_fs.h>
16 #include <linux/efi.h>
17 #include <linux/security.h>
18 #include <linux/slab.h>
19 #include <linux/uaccess.h>
20
21 #include "efi_test.h"
22
23 MODULE_AUTHOR("Ivan Hu <ivan.hu@canonical.com>");
24 MODULE_DESCRIPTION("EFI Test Driver");
25 MODULE_LICENSE("GPL");
26
27 /*
28  * Count the bytes in 'str', including the terminating NULL.
29  *
30  * Note this function returns the number of *bytes*, not the number of
31  * ucs2 characters.
32  */
33 static inline size_t user_ucs2_strsize(efi_char16_t  __user *str)
34 {
35         efi_char16_t *s = str, c;
36         size_t len;
37
38         if (!str)
39                 return 0;
40
41         /* Include terminating NULL */
42         len = sizeof(efi_char16_t);
43
44         if (get_user(c, s++)) {
45                 /* Can't read userspace memory for size */
46                 return 0;
47         }
48
49         while (c != 0) {
50                 if (get_user(c, s++)) {
51                         /* Can't read userspace memory for size */
52                         return 0;
53                 }
54                 len += sizeof(efi_char16_t);
55         }
56         return len;
57 }
58
59 /*
60  * Allocate a buffer and copy a ucs2 string from user space into it.
61  */
62 static inline int
63 copy_ucs2_from_user_len(efi_char16_t **dst, efi_char16_t __user *src,
64                         size_t len)
65 {
66         efi_char16_t *buf;
67
68         if (!src) {
69                 *dst = NULL;
70                 return 0;
71         }
72
73         if (!access_ok(src, 1))
74                 return -EFAULT;
75
76         buf = memdup_user(src, len);
77         if (IS_ERR(buf)) {
78                 *dst = NULL;
79                 return PTR_ERR(buf);
80         }
81         *dst = buf;
82
83         return 0;
84 }
85
86 /*
87  * Count the bytes in 'str', including the terminating NULL.
88  *
89  * Just a wrap for user_ucs2_strsize
90  */
91 static inline int
92 get_ucs2_strsize_from_user(efi_char16_t __user *src, size_t *len)
93 {
94         if (!access_ok(src, 1))
95                 return -EFAULT;
96
97         *len = user_ucs2_strsize(src);
98         if (*len == 0)
99                 return -EFAULT;
100
101         return 0;
102 }
103
104 /*
105  * Calculate the required buffer allocation size and copy a ucs2 string
106  * from user space into it.
107  *
108  * This function differs from copy_ucs2_from_user_len() because it
109  * calculates the size of the buffer to allocate by taking the length of
110  * the string 'src'.
111  *
112  * If a non-zero value is returned, the caller MUST NOT access 'dst'.
113  *
114  * It is the caller's responsibility to free 'dst'.
115  */
116 static inline int
117 copy_ucs2_from_user(efi_char16_t **dst, efi_char16_t __user *src)
118 {
119         size_t len;
120
121         if (!access_ok(src, 1))
122                 return -EFAULT;
123
124         len = user_ucs2_strsize(src);
125         if (len == 0)
126                 return -EFAULT;
127         return copy_ucs2_from_user_len(dst, src, len);
128 }
129
130 /*
131  * Copy a ucs2 string to a user buffer.
132  *
133  * This function is a simple wrapper around copy_to_user() that does
134  * nothing if 'src' is NULL, which is useful for reducing the amount of
135  * NULL checking the caller has to do.
136  *
137  * 'len' specifies the number of bytes to copy.
138  */
139 static inline int
140 copy_ucs2_to_user_len(efi_char16_t __user *dst, efi_char16_t *src, size_t len)
141 {
142         if (!src)
143                 return 0;
144
145         if (!access_ok(dst, 1))
146                 return -EFAULT;
147
148         return copy_to_user(dst, src, len);
149 }
150
151 static long efi_runtime_get_variable(unsigned long arg)
152 {
153         struct efi_getvariable __user *getvariable_user;
154         struct efi_getvariable getvariable;
155         unsigned long datasize = 0, prev_datasize, *dz;
156         efi_guid_t vendor_guid, *vd = NULL;
157         efi_status_t status;
158         efi_char16_t *name = NULL;
159         u32 attr, *at;
160         void *data = NULL;
161         int rv = 0;
162
163         getvariable_user = (struct efi_getvariable __user *)arg;
164
165         if (copy_from_user(&getvariable, getvariable_user,
166                            sizeof(getvariable)))
167                 return -EFAULT;
168         if (getvariable.data_size &&
169             get_user(datasize, getvariable.data_size))
170                 return -EFAULT;
171         if (getvariable.vendor_guid) {
172                 if (copy_from_user(&vendor_guid, getvariable.vendor_guid,
173                                         sizeof(vendor_guid)))
174                         return -EFAULT;
175                 vd = &vendor_guid;
176         }
177
178         if (getvariable.variable_name) {
179                 rv = copy_ucs2_from_user(&name, getvariable.variable_name);
180                 if (rv)
181                         return rv;
182         }
183
184         at = getvariable.attributes ? &attr : NULL;
185         dz = getvariable.data_size ? &datasize : NULL;
186
187         if (getvariable.data_size && getvariable.data) {
188                 data = kmalloc(datasize, GFP_KERNEL);
189                 if (!data) {
190                         kfree(name);
191                         return -ENOMEM;
192                 }
193         }
194
195         prev_datasize = datasize;
196         status = efi.get_variable(name, vd, at, dz, data);
197         kfree(name);
198
199         if (put_user(status, getvariable.status)) {
200                 rv = -EFAULT;
201                 goto out;
202         }
203
204         if (status != EFI_SUCCESS) {
205                 if (status == EFI_BUFFER_TOO_SMALL) {
206                         if (dz && put_user(datasize, getvariable.data_size)) {
207                                 rv = -EFAULT;
208                                 goto out;
209                         }
210                 }
211                 rv = -EINVAL;
212                 goto out;
213         }
214
215         if (prev_datasize < datasize) {
216                 rv = -EINVAL;
217                 goto out;
218         }
219
220         if (data) {
221                 if (copy_to_user(getvariable.data, data, datasize)) {
222                         rv = -EFAULT;
223                         goto out;
224                 }
225         }
226
227         if (at && put_user(attr, getvariable.attributes)) {
228                 rv = -EFAULT;
229                 goto out;
230         }
231
232         if (dz && put_user(datasize, getvariable.data_size))
233                 rv = -EFAULT;
234
235 out:
236         kfree(data);
237         return rv;
238
239 }
240
241 static long efi_runtime_set_variable(unsigned long arg)
242 {
243         struct efi_setvariable __user *setvariable_user;
244         struct efi_setvariable setvariable;
245         efi_guid_t vendor_guid;
246         efi_status_t status;
247         efi_char16_t *name = NULL;
248         void *data;
249         int rv = 0;
250
251         setvariable_user = (struct efi_setvariable __user *)arg;
252
253         if (copy_from_user(&setvariable, setvariable_user, sizeof(setvariable)))
254                 return -EFAULT;
255         if (copy_from_user(&vendor_guid, setvariable.vendor_guid,
256                                 sizeof(vendor_guid)))
257                 return -EFAULT;
258
259         if (setvariable.variable_name) {
260                 rv = copy_ucs2_from_user(&name, setvariable.variable_name);
261                 if (rv)
262                         return rv;
263         }
264
265         data = memdup_user(setvariable.data, setvariable.data_size);
266         if (IS_ERR(data)) {
267                 kfree(name);
268                 return PTR_ERR(data);
269         }
270
271         status = efi.set_variable(name, &vendor_guid,
272                                 setvariable.attributes,
273                                 setvariable.data_size, data);
274
275         if (put_user(status, setvariable.status)) {
276                 rv = -EFAULT;
277                 goto out;
278         }
279
280         rv = status == EFI_SUCCESS ? 0 : -EINVAL;
281
282 out:
283         kfree(data);
284         kfree(name);
285
286         return rv;
287 }
288
289 static long efi_runtime_get_time(unsigned long arg)
290 {
291         struct efi_gettime __user *gettime_user;
292         struct efi_gettime  gettime;
293         efi_status_t status;
294         efi_time_cap_t cap;
295         efi_time_t efi_time;
296
297         gettime_user = (struct efi_gettime __user *)arg;
298         if (copy_from_user(&gettime, gettime_user, sizeof(gettime)))
299                 return -EFAULT;
300
301         status = efi.get_time(gettime.time ? &efi_time : NULL,
302                               gettime.capabilities ? &cap : NULL);
303
304         if (put_user(status, gettime.status))
305                 return -EFAULT;
306
307         if (status != EFI_SUCCESS)
308                 return -EINVAL;
309
310         if (gettime.capabilities) {
311                 efi_time_cap_t __user *cap_local;
312
313                 cap_local = (efi_time_cap_t *)gettime.capabilities;
314                 if (put_user(cap.resolution, &(cap_local->resolution)) ||
315                         put_user(cap.accuracy, &(cap_local->accuracy)) ||
316                         put_user(cap.sets_to_zero, &(cap_local->sets_to_zero)))
317                         return -EFAULT;
318         }
319         if (gettime.time) {
320                 if (copy_to_user(gettime.time, &efi_time, sizeof(efi_time_t)))
321                         return -EFAULT;
322         }
323
324         return 0;
325 }
326
327 static long efi_runtime_set_time(unsigned long arg)
328 {
329         struct efi_settime __user *settime_user;
330         struct efi_settime settime;
331         efi_status_t status;
332         efi_time_t efi_time;
333
334         settime_user = (struct efi_settime __user *)arg;
335         if (copy_from_user(&settime, settime_user, sizeof(settime)))
336                 return -EFAULT;
337         if (copy_from_user(&efi_time, settime.time,
338                                         sizeof(efi_time_t)))
339                 return -EFAULT;
340         status = efi.set_time(&efi_time);
341
342         if (put_user(status, settime.status))
343                 return -EFAULT;
344
345         return status == EFI_SUCCESS ? 0 : -EINVAL;
346 }
347
348 static long efi_runtime_get_waketime(unsigned long arg)
349 {
350         struct efi_getwakeuptime __user *getwakeuptime_user;
351         struct efi_getwakeuptime getwakeuptime;
352         efi_bool_t enabled, pending;
353         efi_status_t status;
354         efi_time_t efi_time;
355
356         getwakeuptime_user = (struct efi_getwakeuptime __user *)arg;
357         if (copy_from_user(&getwakeuptime, getwakeuptime_user,
358                                 sizeof(getwakeuptime)))
359                 return -EFAULT;
360
361         status = efi.get_wakeup_time(
362                 getwakeuptime.enabled ? (efi_bool_t *)&enabled : NULL,
363                 getwakeuptime.pending ? (efi_bool_t *)&pending : NULL,
364                 getwakeuptime.time ? &efi_time : NULL);
365
366         if (put_user(status, getwakeuptime.status))
367                 return -EFAULT;
368
369         if (status != EFI_SUCCESS)
370                 return -EINVAL;
371
372         if (getwakeuptime.enabled && put_user(enabled,
373                                                 getwakeuptime.enabled))
374                 return -EFAULT;
375
376         if (getwakeuptime.time) {
377                 if (copy_to_user(getwakeuptime.time, &efi_time,
378                                 sizeof(efi_time_t)))
379                         return -EFAULT;
380         }
381
382         return 0;
383 }
384
385 static long efi_runtime_set_waketime(unsigned long arg)
386 {
387         struct efi_setwakeuptime __user *setwakeuptime_user;
388         struct efi_setwakeuptime setwakeuptime;
389         efi_bool_t enabled;
390         efi_status_t status;
391         efi_time_t efi_time;
392
393         setwakeuptime_user = (struct efi_setwakeuptime __user *)arg;
394
395         if (copy_from_user(&setwakeuptime, setwakeuptime_user,
396                                 sizeof(setwakeuptime)))
397                 return -EFAULT;
398
399         enabled = setwakeuptime.enabled;
400         if (setwakeuptime.time) {
401                 if (copy_from_user(&efi_time, setwakeuptime.time,
402                                         sizeof(efi_time_t)))
403                         return -EFAULT;
404
405                 status = efi.set_wakeup_time(enabled, &efi_time);
406         } else
407                 status = efi.set_wakeup_time(enabled, NULL);
408
409         if (put_user(status, setwakeuptime.status))
410                 return -EFAULT;
411
412         return status == EFI_SUCCESS ? 0 : -EINVAL;
413 }
414
415 static long efi_runtime_get_nextvariablename(unsigned long arg)
416 {
417         struct efi_getnextvariablename __user *getnextvariablename_user;
418         struct efi_getnextvariablename getnextvariablename;
419         unsigned long name_size, prev_name_size = 0, *ns = NULL;
420         efi_status_t status;
421         efi_guid_t *vd = NULL;
422         efi_guid_t vendor_guid;
423         efi_char16_t *name = NULL;
424         int rv = 0;
425
426         getnextvariablename_user = (struct efi_getnextvariablename __user *)arg;
427
428         if (copy_from_user(&getnextvariablename, getnextvariablename_user,
429                            sizeof(getnextvariablename)))
430                 return -EFAULT;
431
432         if (getnextvariablename.variable_name_size) {
433                 if (get_user(name_size, getnextvariablename.variable_name_size))
434                         return -EFAULT;
435                 ns = &name_size;
436                 prev_name_size = name_size;
437         }
438
439         if (getnextvariablename.vendor_guid) {
440                 if (copy_from_user(&vendor_guid,
441                                 getnextvariablename.vendor_guid,
442                                 sizeof(vendor_guid)))
443                         return -EFAULT;
444                 vd = &vendor_guid;
445         }
446
447         if (getnextvariablename.variable_name) {
448                 size_t name_string_size = 0;
449
450                 rv = get_ucs2_strsize_from_user(
451                                 getnextvariablename.variable_name,
452                                 &name_string_size);
453                 if (rv)
454                         return rv;
455                 /*
456                  * The name_size may be smaller than the real buffer size where
457                  * variable name located in some use cases. The most typical
458                  * case is passing a 0 to get the required buffer size for the
459                  * 1st time call. So we need to copy the content from user
460                  * space for at least the string size of variable name, or else
461                  * the name passed to UEFI may not be terminated as we expected.
462                  */
463                 rv = copy_ucs2_from_user_len(&name,
464                                 getnextvariablename.variable_name,
465                                 prev_name_size > name_string_size ?
466                                 prev_name_size : name_string_size);
467                 if (rv)
468                         return rv;
469         }
470
471         status = efi.get_next_variable(ns, name, vd);
472
473         if (put_user(status, getnextvariablename.status)) {
474                 rv = -EFAULT;
475                 goto out;
476         }
477
478         if (status != EFI_SUCCESS) {
479                 if (status == EFI_BUFFER_TOO_SMALL) {
480                         if (ns && put_user(*ns,
481                                 getnextvariablename.variable_name_size)) {
482                                 rv = -EFAULT;
483                                 goto out;
484                         }
485                 }
486                 rv = -EINVAL;
487                 goto out;
488         }
489
490         if (name) {
491                 if (copy_ucs2_to_user_len(getnextvariablename.variable_name,
492                                                 name, prev_name_size)) {
493                         rv = -EFAULT;
494                         goto out;
495                 }
496         }
497
498         if (ns) {
499                 if (put_user(*ns, getnextvariablename.variable_name_size)) {
500                         rv = -EFAULT;
501                         goto out;
502                 }
503         }
504
505         if (vd) {
506                 if (copy_to_user(getnextvariablename.vendor_guid, vd,
507                                                         sizeof(efi_guid_t)))
508                         rv = -EFAULT;
509         }
510
511 out:
512         kfree(name);
513         return rv;
514 }
515
516 static long efi_runtime_get_nexthighmonocount(unsigned long arg)
517 {
518         struct efi_getnexthighmonotoniccount __user *getnexthighmonocount_user;
519         struct efi_getnexthighmonotoniccount getnexthighmonocount;
520         efi_status_t status;
521         u32 count;
522
523         getnexthighmonocount_user = (struct
524                         efi_getnexthighmonotoniccount __user *)arg;
525
526         if (copy_from_user(&getnexthighmonocount,
527                            getnexthighmonocount_user,
528                            sizeof(getnexthighmonocount)))
529                 return -EFAULT;
530
531         status = efi.get_next_high_mono_count(
532                 getnexthighmonocount.high_count ? &count : NULL);
533
534         if (put_user(status, getnexthighmonocount.status))
535                 return -EFAULT;
536
537         if (status != EFI_SUCCESS)
538                 return -EINVAL;
539
540         if (getnexthighmonocount.high_count &&
541             put_user(count, getnexthighmonocount.high_count))
542                 return -EFAULT;
543
544         return 0;
545 }
546
547 static long efi_runtime_reset_system(unsigned long arg)
548 {
549         struct efi_resetsystem __user *resetsystem_user;
550         struct efi_resetsystem resetsystem;
551         void *data = NULL;
552
553         resetsystem_user = (struct efi_resetsystem __user *)arg;
554         if (copy_from_user(&resetsystem, resetsystem_user,
555                                                 sizeof(resetsystem)))
556                 return -EFAULT;
557         if (resetsystem.data_size != 0) {
558                 data = memdup_user((void *)resetsystem.data,
559                                                 resetsystem.data_size);
560                 if (IS_ERR(data))
561                         return PTR_ERR(data);
562         }
563
564         efi.reset_system(resetsystem.reset_type, resetsystem.status,
565                                 resetsystem.data_size, (efi_char16_t *)data);
566
567         kfree(data);
568         return 0;
569 }
570
571 static long efi_runtime_query_variableinfo(unsigned long arg)
572 {
573         struct efi_queryvariableinfo __user *queryvariableinfo_user;
574         struct efi_queryvariableinfo queryvariableinfo;
575         efi_status_t status;
576         u64 max_storage, remaining, max_size;
577
578         queryvariableinfo_user = (struct efi_queryvariableinfo __user *)arg;
579
580         if (copy_from_user(&queryvariableinfo, queryvariableinfo_user,
581                            sizeof(queryvariableinfo)))
582                 return -EFAULT;
583
584         status = efi.query_variable_info(queryvariableinfo.attributes,
585                                          &max_storage, &remaining, &max_size);
586
587         if (put_user(status, queryvariableinfo.status))
588                 return -EFAULT;
589
590         if (status != EFI_SUCCESS)
591                 return -EINVAL;
592
593         if (put_user(max_storage,
594                      queryvariableinfo.maximum_variable_storage_size))
595                 return -EFAULT;
596
597         if (put_user(remaining,
598                      queryvariableinfo.remaining_variable_storage_size))
599                 return -EFAULT;
600
601         if (put_user(max_size, queryvariableinfo.maximum_variable_size))
602                 return -EFAULT;
603
604         return 0;
605 }
606
607 static long efi_runtime_query_capsulecaps(unsigned long arg)
608 {
609         struct efi_querycapsulecapabilities __user *qcaps_user;
610         struct efi_querycapsulecapabilities qcaps;
611         efi_capsule_header_t *capsules;
612         efi_status_t status;
613         u64 max_size;
614         int i, reset_type;
615         int rv = 0;
616
617         qcaps_user = (struct efi_querycapsulecapabilities __user *)arg;
618
619         if (copy_from_user(&qcaps, qcaps_user, sizeof(qcaps)))
620                 return -EFAULT;
621
622         if (qcaps.capsule_count == ULONG_MAX)
623                 return -EINVAL;
624
625         capsules = kcalloc(qcaps.capsule_count + 1,
626                            sizeof(efi_capsule_header_t), GFP_KERNEL);
627         if (!capsules)
628                 return -ENOMEM;
629
630         for (i = 0; i < qcaps.capsule_count; i++) {
631                 efi_capsule_header_t *c;
632                 /*
633                  * We cannot dereference qcaps.capsule_header_array directly to
634                  * obtain the address of the capsule as it resides in the
635                  * user space
636                  */
637                 if (get_user(c, qcaps.capsule_header_array + i)) {
638                         rv = -EFAULT;
639                         goto out;
640                 }
641                 if (copy_from_user(&capsules[i], c,
642                                 sizeof(efi_capsule_header_t))) {
643                         rv = -EFAULT;
644                         goto out;
645                 }
646         }
647
648         qcaps.capsule_header_array = &capsules;
649
650         status = efi.query_capsule_caps((efi_capsule_header_t **)
651                                         qcaps.capsule_header_array,
652                                         qcaps.capsule_count,
653                                         &max_size, &reset_type);
654
655         if (put_user(status, qcaps.status)) {
656                 rv = -EFAULT;
657                 goto out;
658         }
659
660         if (status != EFI_SUCCESS) {
661                 rv = -EINVAL;
662                 goto out;
663         }
664
665         if (put_user(max_size, qcaps.maximum_capsule_size)) {
666                 rv = -EFAULT;
667                 goto out;
668         }
669
670         if (put_user(reset_type, qcaps.reset_type))
671                 rv = -EFAULT;
672
673 out:
674         kfree(capsules);
675         return rv;
676 }
677
678 static long efi_test_ioctl(struct file *file, unsigned int cmd,
679                                                         unsigned long arg)
680 {
681         switch (cmd) {
682         case EFI_RUNTIME_GET_VARIABLE:
683                 return efi_runtime_get_variable(arg);
684
685         case EFI_RUNTIME_SET_VARIABLE:
686                 return efi_runtime_set_variable(arg);
687
688         case EFI_RUNTIME_GET_TIME:
689                 return efi_runtime_get_time(arg);
690
691         case EFI_RUNTIME_SET_TIME:
692                 return efi_runtime_set_time(arg);
693
694         case EFI_RUNTIME_GET_WAKETIME:
695                 return efi_runtime_get_waketime(arg);
696
697         case EFI_RUNTIME_SET_WAKETIME:
698                 return efi_runtime_set_waketime(arg);
699
700         case EFI_RUNTIME_GET_NEXTVARIABLENAME:
701                 return efi_runtime_get_nextvariablename(arg);
702
703         case EFI_RUNTIME_GET_NEXTHIGHMONOTONICCOUNT:
704                 return efi_runtime_get_nexthighmonocount(arg);
705
706         case EFI_RUNTIME_QUERY_VARIABLEINFO:
707                 return efi_runtime_query_variableinfo(arg);
708
709         case EFI_RUNTIME_QUERY_CAPSULECAPABILITIES:
710                 return efi_runtime_query_capsulecaps(arg);
711
712         case EFI_RUNTIME_RESET_SYSTEM:
713                 return efi_runtime_reset_system(arg);
714         }
715
716         return -ENOTTY;
717 }
718
719 static int efi_test_open(struct inode *inode, struct file *file)
720 {
721         int ret = security_locked_down(LOCKDOWN_EFI_TEST);
722
723         if (ret)
724                 return ret;
725
726         if (!capable(CAP_SYS_ADMIN))
727                 return -EACCES;
728         /*
729          * nothing special to do here
730          * We do accept multiple open files at the same time as we
731          * synchronize on the per call operation.
732          */
733         return 0;
734 }
735
736 static int efi_test_close(struct inode *inode, struct file *file)
737 {
738         return 0;
739 }
740
741 /*
742  *      The various file operations we support.
743  */
744 static const struct file_operations efi_test_fops = {
745         .owner          = THIS_MODULE,
746         .unlocked_ioctl = efi_test_ioctl,
747         .open           = efi_test_open,
748         .release        = efi_test_close,
749         .llseek         = no_llseek,
750 };
751
752 static struct miscdevice efi_test_dev = {
753         MISC_DYNAMIC_MINOR,
754         "efi_test",
755         &efi_test_fops
756 };
757
758 static int __init efi_test_init(void)
759 {
760         int ret;
761
762         ret = misc_register(&efi_test_dev);
763         if (ret) {
764                 pr_err("efi_test: can't misc_register on minor=%d\n",
765                         MISC_DYNAMIC_MINOR);
766                 return ret;
767         }
768
769         return 0;
770 }
771
772 static void __exit efi_test_exit(void)
773 {
774         misc_deregister(&efi_test_dev);
775 }
776
777 module_init(efi_test_init);
778 module_exit(efi_test_exit);