File Index
Files and directories
Sign in
FILE

efi_test.c

File preview with syntax highlighting.

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