1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2016-20 Intel Corporation. */
3
4 #include <asm/mman.h>
5 #include <asm/sgx.h>
6 #include <linux/mman.h>
7 #include <linux/delay.h>
8 #include <linux/file.h>
9 #include <linux/hashtable.h>
10 #include <linux/highmem.h>
11 #include <linux/ratelimit.h>
12 #include <linux/sched/signal.h>
13 #include <linux/shmem_fs.h>
14 #include <linux/slab.h>
15 #include <linux/suspend.h>
16 #include "driver.h"
17 #include "encl.h"
18 #include "encls.h"
19
sgx_encl_grow(struct sgx_encl * encl)20 static struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl)
21 {
22 struct sgx_va_page *va_page = NULL;
23 void *err;
24
25 BUILD_BUG_ON(SGX_VA_SLOT_COUNT !=
26 (SGX_ENCL_PAGE_VA_OFFSET_MASK >> 3) + 1);
27
28 if (!(encl->page_cnt % SGX_VA_SLOT_COUNT)) {
29 va_page = kzalloc(sizeof(*va_page), GFP_KERNEL);
30 if (!va_page)
31 return ERR_PTR(-ENOMEM);
32
33 va_page->epc_page = sgx_alloc_va_page();
34 if (IS_ERR(va_page->epc_page)) {
35 err = ERR_CAST(va_page->epc_page);
36 kfree(va_page);
37 return err;
38 }
39
40 WARN_ON_ONCE(encl->page_cnt % SGX_VA_SLOT_COUNT);
41 }
42 encl->page_cnt++;
43 return va_page;
44 }
45
sgx_encl_shrink(struct sgx_encl * encl,struct sgx_va_page * va_page)46 static void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page)
47 {
48 encl->page_cnt--;
49
50 if (va_page) {
51 sgx_encl_free_epc_page(va_page->epc_page);
52 list_del(&va_page->list);
53 kfree(va_page);
54 }
55 }
56
sgx_encl_create(struct sgx_encl * encl,struct sgx_secs * secs)57 static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
58 {
59 struct sgx_epc_page *secs_epc;
60 struct sgx_va_page *va_page;
61 struct sgx_pageinfo pginfo;
62 struct sgx_secinfo secinfo;
63 unsigned long encl_size;
64 struct file *backing;
65 long ret;
66
67 va_page = sgx_encl_grow(encl);
68 if (IS_ERR(va_page))
69 return PTR_ERR(va_page);
70 else if (va_page)
71 list_add(&va_page->list, &encl->va_pages);
72 /* else the tail page of the VA page list had free slots. */
73
74 /* The extra page goes to SECS. */
75 encl_size = secs->size + PAGE_SIZE;
76
77 backing = shmem_file_setup("SGX backing", encl_size + (encl_size >> 5),
78 VM_NORESERVE);
79 if (IS_ERR(backing)) {
80 ret = PTR_ERR(backing);
81 goto err_out_shrink;
82 }
83
84 encl->backing = backing;
85
86 secs_epc = sgx_alloc_epc_page(&encl->secs, true);
87 if (IS_ERR(secs_epc)) {
88 ret = PTR_ERR(secs_epc);
89 goto err_out_backing;
90 }
91
92 encl->secs.epc_page = secs_epc;
93
94 pginfo.addr = 0;
95 pginfo.contents = (unsigned long)secs;
96 pginfo.metadata = (unsigned long)&secinfo;
97 pginfo.secs = 0;
98 memset(&secinfo, 0, sizeof(secinfo));
99
100 ret = __ecreate((void *)&pginfo, sgx_get_epc_virt_addr(secs_epc));
101 if (ret) {
102 ret = -EIO;
103 goto err_out;
104 }
105
106 if (secs->attributes & SGX_ATTR_DEBUG)
107 set_bit(SGX_ENCL_DEBUG, &encl->flags);
108
109 encl->secs.encl = encl;
110 encl->base = secs->base;
111 encl->size = secs->size;
112 encl->attributes = secs->attributes;
113 encl->attributes_mask = SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | SGX_ATTR_KSS;
114
115 /* Set only after completion, as encl->lock has not been taken. */
116 set_bit(SGX_ENCL_CREATED, &encl->flags);
117
118 return 0;
119
120 err_out:
121 sgx_encl_free_epc_page(encl->secs.epc_page);
122 encl->secs.epc_page = NULL;
123
124 err_out_backing:
125 fput(encl->backing);
126 encl->backing = NULL;
127
128 err_out_shrink:
129 sgx_encl_shrink(encl, va_page);
130
131 return ret;
132 }
133
134 /**
135 * sgx_ioc_enclave_create() - handler for %SGX_IOC_ENCLAVE_CREATE
136 * @encl: An enclave pointer.
137 * @arg: The ioctl argument.
138 *
139 * Allocate kernel data structures for the enclave and invoke ECREATE.
140 *
141 * Return:
142 * - 0: Success.
143 * - -EIO: ECREATE failed.
144 * - -errno: POSIX error.
145 */
sgx_ioc_enclave_create(struct sgx_encl * encl,void __user * arg)146 static long sgx_ioc_enclave_create(struct sgx_encl *encl, void __user *arg)
147 {
148 struct sgx_enclave_create create_arg;
149 void *secs;
150 int ret;
151
152 if (test_bit(SGX_ENCL_CREATED, &encl->flags))
153 return -EINVAL;
154
155 if (copy_from_user(&create_arg, arg, sizeof(create_arg)))
156 return -EFAULT;
157
158 secs = kmalloc(PAGE_SIZE, GFP_KERNEL);
159 if (!secs)
160 return -ENOMEM;
161
162 if (copy_from_user(secs, (void __user *)create_arg.src, PAGE_SIZE))
163 ret = -EFAULT;
164 else
165 ret = sgx_encl_create(encl, secs);
166
167 kfree(secs);
168 return ret;
169 }
170
sgx_encl_page_alloc(struct sgx_encl * encl,unsigned long offset,u64 secinfo_flags)171 static struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
172 unsigned long offset,
173 u64 secinfo_flags)
174 {
175 struct sgx_encl_page *encl_page;
176 unsigned long prot;
177
178 encl_page = kzalloc(sizeof(*encl_page), GFP_KERNEL);
179 if (!encl_page)
180 return ERR_PTR(-ENOMEM);
181
182 encl_page->desc = encl->base + offset;
183 encl_page->encl = encl;
184
185 prot = _calc_vm_trans(secinfo_flags, SGX_SECINFO_R, PROT_READ) |
186 _calc_vm_trans(secinfo_flags, SGX_SECINFO_W, PROT_WRITE) |
187 _calc_vm_trans(secinfo_flags, SGX_SECINFO_X, PROT_EXEC);
188
189 /*
190 * TCS pages must always RW set for CPU access while the SECINFO
191 * permissions are *always* zero - the CPU ignores the user provided
192 * values and silently overwrites them with zero permissions.
193 */
194 if ((secinfo_flags & SGX_SECINFO_PAGE_TYPE_MASK) == SGX_SECINFO_TCS)
195 prot |= PROT_READ | PROT_WRITE;
196
197 /* Calculate maximum of the VM flags for the page. */
198 encl_page->vm_max_prot_bits = calc_vm_prot_bits(prot, 0);
199
200 return encl_page;
201 }
202
sgx_validate_secinfo(struct sgx_secinfo * secinfo)203 static int sgx_validate_secinfo(struct sgx_secinfo *secinfo)
204 {
205 u64 perm = secinfo->flags & SGX_SECINFO_PERMISSION_MASK;
206 u64 pt = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK;
207
208 if (pt != SGX_SECINFO_REG && pt != SGX_SECINFO_TCS)
209 return -EINVAL;
210
211 if ((perm & SGX_SECINFO_W) && !(perm & SGX_SECINFO_R))
212 return -EINVAL;
213
214 /*
215 * CPU will silently overwrite the permissions as zero, which means
216 * that we need to validate it ourselves.
217 */
218 if (pt == SGX_SECINFO_TCS && perm)
219 return -EINVAL;
220
221 if (secinfo->flags & SGX_SECINFO_RESERVED_MASK)
222 return -EINVAL;
223
224 if (memchr_inv(secinfo->reserved, 0, sizeof(secinfo->reserved)))
225 return -EINVAL;
226
227 return 0;
228 }
229
__sgx_encl_add_page(struct sgx_encl * encl,struct sgx_encl_page * encl_page,struct sgx_epc_page * epc_page,struct sgx_secinfo * secinfo,unsigned long src)230 static int __sgx_encl_add_page(struct sgx_encl *encl,
231 struct sgx_encl_page *encl_page,
232 struct sgx_epc_page *epc_page,
233 struct sgx_secinfo *secinfo, unsigned long src)
234 {
235 struct sgx_pageinfo pginfo;
236 struct vm_area_struct *vma;
237 struct page *src_page;
238 int ret;
239
240 /* Deny noexec. */
241 vma = find_vma(current->mm, src);
242 if (!vma)
243 return -EFAULT;
244
245 if (!(vma->vm_flags & VM_MAYEXEC))
246 return -EACCES;
247
248 ret = get_user_pages(src, 1, 0, &src_page, NULL);
249 if (ret < 1)
250 return -EFAULT;
251
252 pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page);
253 pginfo.addr = encl_page->desc & PAGE_MASK;
254 pginfo.metadata = (unsigned long)secinfo;
255 pginfo.contents = (unsigned long)kmap_atomic(src_page);
256
257 ret = __eadd(&pginfo, sgx_get_epc_virt_addr(epc_page));
258
259 kunmap_atomic((void *)pginfo.contents);
260 put_page(src_page);
261
262 return ret ? -EIO : 0;
263 }
264
265 /*
266 * If the caller requires measurement of the page as a proof for the content,
267 * use EEXTEND to add a measurement for 256 bytes of the page. Repeat this
268 * operation until the entire page is measured."
269 */
__sgx_encl_extend(struct sgx_encl * encl,struct sgx_epc_page * epc_page)270 static int __sgx_encl_extend(struct sgx_encl *encl,
271 struct sgx_epc_page *epc_page)
272 {
273 unsigned long offset;
274 int ret;
275
276 for (offset = 0; offset < PAGE_SIZE; offset += SGX_EEXTEND_BLOCK_SIZE) {
277 ret = __eextend(sgx_get_epc_virt_addr(encl->secs.epc_page),
278 sgx_get_epc_virt_addr(epc_page) + offset);
279 if (ret) {
280 if (encls_failed(ret))
281 ENCLS_WARN(ret, "EEXTEND");
282
283 return -EIO;
284 }
285 }
286
287 return 0;
288 }
289
sgx_encl_add_page(struct sgx_encl * encl,unsigned long src,unsigned long offset,struct sgx_secinfo * secinfo,unsigned long flags)290 static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long src,
291 unsigned long offset, struct sgx_secinfo *secinfo,
292 unsigned long flags)
293 {
294 struct sgx_encl_page *encl_page;
295 struct sgx_epc_page *epc_page;
296 struct sgx_va_page *va_page;
297 int ret;
298
299 encl_page = sgx_encl_page_alloc(encl, offset, secinfo->flags);
300 if (IS_ERR(encl_page))
301 return PTR_ERR(encl_page);
302
303 epc_page = sgx_alloc_epc_page(encl_page, true);
304 if (IS_ERR(epc_page)) {
305 kfree(encl_page);
306 return PTR_ERR(epc_page);
307 }
308
309 va_page = sgx_encl_grow(encl);
310 if (IS_ERR(va_page)) {
311 ret = PTR_ERR(va_page);
312 goto err_out_free;
313 }
314
315 mmap_read_lock(current->mm);
316 mutex_lock(&encl->lock);
317
318 /*
319 * Adding to encl->va_pages must be done under encl->lock. Ditto for
320 * deleting (via sgx_encl_shrink()) in the error path.
321 */
322 if (va_page)
323 list_add(&va_page->list, &encl->va_pages);
324
325 /*
326 * Insert prior to EADD in case of OOM. EADD modifies MRENCLAVE, i.e.
327 * can't be gracefully unwound, while failure on EADD/EXTEND is limited
328 * to userspace errors (or kernel/hardware bugs).
329 */
330 ret = xa_insert(&encl->page_array, PFN_DOWN(encl_page->desc),
331 encl_page, GFP_KERNEL);
332 if (ret)
333 goto err_out_unlock;
334
335 ret = __sgx_encl_add_page(encl, encl_page, epc_page, secinfo,
336 src);
337 if (ret)
338 goto err_out;
339
340 /*
341 * Complete the "add" before doing the "extend" so that the "add"
342 * isn't in a half-baked state in the extremely unlikely scenario
343 * the enclave will be destroyed in response to EEXTEND failure.
344 */
345 encl_page->encl = encl;
346 encl_page->epc_page = epc_page;
347 encl->secs_child_cnt++;
348
349 if (flags & SGX_PAGE_MEASURE) {
350 ret = __sgx_encl_extend(encl, epc_page);
351 if (ret)
352 goto err_out;
353 }
354
355 sgx_mark_page_reclaimable(encl_page->epc_page);
356 mutex_unlock(&encl->lock);
357 mmap_read_unlock(current->mm);
358 return ret;
359
360 err_out:
361 xa_erase(&encl->page_array, PFN_DOWN(encl_page->desc));
362
363 err_out_unlock:
364 sgx_encl_shrink(encl, va_page);
365 mutex_unlock(&encl->lock);
366 mmap_read_unlock(current->mm);
367
368 err_out_free:
369 sgx_encl_free_epc_page(epc_page);
370 kfree(encl_page);
371
372 return ret;
373 }
374
375 /**
376 * sgx_ioc_enclave_add_pages() - The handler for %SGX_IOC_ENCLAVE_ADD_PAGES
377 * @encl: an enclave pointer
378 * @arg: a user pointer to a struct sgx_enclave_add_pages instance
379 *
380 * Add one or more pages to an uninitialized enclave, and optionally extend the
381 * measurement with the contents of the page. The SECINFO and measurement mask
382 * are applied to all pages.
383 *
384 * A SECINFO for a TCS is required to always contain zero permissions because
385 * CPU silently zeros them. Allowing anything else would cause a mismatch in
386 * the measurement.
387 *
388 * mmap()'s protection bits are capped by the page permissions. For each page
389 * address, the maximum protection bits are computed with the following
390 * heuristics:
391 *
392 * 1. A regular page: PROT_R, PROT_W and PROT_X match the SECINFO permissions.
393 * 2. A TCS page: PROT_R | PROT_W.
394 *
395 * mmap() is not allowed to surpass the minimum of the maximum protection bits
396 * within the given address range.
397 *
398 * The function deinitializes kernel data structures for enclave and returns
399 * -EIO in any of the following conditions:
400 *
401 * - Enclave Page Cache (EPC), the physical memory holding enclaves, has
402 * been invalidated. This will cause EADD and EEXTEND to fail.
403 * - If the source address is corrupted somehow when executing EADD.
404 *
405 * Return:
406 * - 0: Success.
407 * - -EACCES: The source page is located in a noexec partition.
408 * - -ENOMEM: Out of EPC pages.
409 * - -EINTR: The call was interrupted before data was processed.
410 * - -EIO: Either EADD or EEXTEND failed because invalid source address
411 * or power cycle.
412 * - -errno: POSIX error.
413 */
sgx_ioc_enclave_add_pages(struct sgx_encl * encl,void __user * arg)414 static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg)
415 {
416 struct sgx_enclave_add_pages add_arg;
417 struct sgx_secinfo secinfo;
418 unsigned long c;
419 int ret;
420
421 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) ||
422 test_bit(SGX_ENCL_INITIALIZED, &encl->flags))
423 return -EINVAL;
424
425 if (copy_from_user(&add_arg, arg, sizeof(add_arg)))
426 return -EFAULT;
427
428 if (!IS_ALIGNED(add_arg.offset, PAGE_SIZE) ||
429 !IS_ALIGNED(add_arg.src, PAGE_SIZE))
430 return -EINVAL;
431
432 if (!add_arg.length || add_arg.length & (PAGE_SIZE - 1))
433 return -EINVAL;
434
435 if (add_arg.offset + add_arg.length - PAGE_SIZE >= encl->size)
436 return -EINVAL;
437
438 if (copy_from_user(&secinfo, (void __user *)add_arg.secinfo,
439 sizeof(secinfo)))
440 return -EFAULT;
441
442 if (sgx_validate_secinfo(&secinfo))
443 return -EINVAL;
444
445 for (c = 0 ; c < add_arg.length; c += PAGE_SIZE) {
446 if (signal_pending(current)) {
447 if (!c)
448 ret = -ERESTARTSYS;
449
450 break;
451 }
452
453 if (need_resched())
454 cond_resched();
455
456 ret = sgx_encl_add_page(encl, add_arg.src + c, add_arg.offset + c,
457 &secinfo, add_arg.flags);
458 if (ret)
459 break;
460 }
461
462 add_arg.count = c;
463
464 if (copy_to_user(arg, &add_arg, sizeof(add_arg)))
465 return -EFAULT;
466
467 return ret;
468 }
469
__sgx_get_key_hash(struct crypto_shash * tfm,const void * modulus,void * hash)470 static int __sgx_get_key_hash(struct crypto_shash *tfm, const void *modulus,
471 void *hash)
472 {
473 SHASH_DESC_ON_STACK(shash, tfm);
474
475 shash->tfm = tfm;
476
477 return crypto_shash_digest(shash, modulus, SGX_MODULUS_SIZE, hash);
478 }
479
sgx_get_key_hash(const void * modulus,void * hash)480 static int sgx_get_key_hash(const void *modulus, void *hash)
481 {
482 struct crypto_shash *tfm;
483 int ret;
484
485 tfm = crypto_alloc_shash("sha256", 0, CRYPTO_ALG_ASYNC);
486 if (IS_ERR(tfm))
487 return PTR_ERR(tfm);
488
489 ret = __sgx_get_key_hash(tfm, modulus, hash);
490
491 crypto_free_shash(tfm);
492 return ret;
493 }
494
sgx_encl_init(struct sgx_encl * encl,struct sgx_sigstruct * sigstruct,void * token)495 static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
496 void *token)
497 {
498 u64 mrsigner[4];
499 int i, j;
500 void *addr;
501 int ret;
502
503 /*
504 * Deny initializing enclaves with attributes (namely provisioning)
505 * that have not been explicitly allowed.
506 */
507 if (encl->attributes & ~encl->attributes_mask)
508 return -EACCES;
509
510 /*
511 * Attributes should not be enforced *only* against what's available on
512 * platform (done in sgx_encl_create) but checked and enforced against
513 * the mask for enforcement in sigstruct. For example an enclave could
514 * opt to sign with AVX bit in xfrm, but still be loadable on a platform
515 * without it if the sigstruct->body.attributes_mask does not turn that
516 * bit on.
517 */
518 if (sigstruct->body.attributes & sigstruct->body.attributes_mask &
519 sgx_attributes_reserved_mask)
520 return -EINVAL;
521
522 if (sigstruct->body.miscselect & sigstruct->body.misc_mask &
523 sgx_misc_reserved_mask)
524 return -EINVAL;
525
526 if (sigstruct->body.xfrm & sigstruct->body.xfrm_mask &
527 sgx_xfrm_reserved_mask)
528 return -EINVAL;
529
530 ret = sgx_get_key_hash(sigstruct->modulus, mrsigner);
531 if (ret)
532 return ret;
533
534 mutex_lock(&encl->lock);
535
536 /*
537 * ENCLS[EINIT] is interruptible because it has such a high latency,
538 * e.g. 50k+ cycles on success. If an IRQ/NMI/SMI becomes pending,
539 * EINIT may fail with SGX_UNMASKED_EVENT so that the event can be
540 * serviced.
541 */
542 for (i = 0; i < SGX_EINIT_SLEEP_COUNT; i++) {
543 for (j = 0; j < SGX_EINIT_SPIN_COUNT; j++) {
544 addr = sgx_get_epc_virt_addr(encl->secs.epc_page);
545
546 preempt_disable();
547
548 sgx_update_lepubkeyhash(mrsigner);
549
550 ret = __einit(sigstruct, token, addr);
551
552 preempt_enable();
553
554 if (ret == SGX_UNMASKED_EVENT)
555 continue;
556 else
557 break;
558 }
559
560 if (ret != SGX_UNMASKED_EVENT)
561 break;
562
563 msleep_interruptible(SGX_EINIT_SLEEP_TIME);
564
565 if (signal_pending(current)) {
566 ret = -ERESTARTSYS;
567 goto err_out;
568 }
569 }
570
571 if (encls_faulted(ret)) {
572 if (encls_failed(ret))
573 ENCLS_WARN(ret, "EINIT");
574
575 ret = -EIO;
576 } else if (ret) {
577 pr_debug("EINIT returned %d\n", ret);
578 ret = -EPERM;
579 } else {
580 set_bit(SGX_ENCL_INITIALIZED, &encl->flags);
581 }
582
583 err_out:
584 mutex_unlock(&encl->lock);
585 return ret;
586 }
587
588 /**
589 * sgx_ioc_enclave_init() - handler for %SGX_IOC_ENCLAVE_INIT
590 * @encl: an enclave pointer
591 * @arg: userspace pointer to a struct sgx_enclave_init instance
592 *
593 * Flush any outstanding enqueued EADD operations and perform EINIT. The
594 * Launch Enclave Public Key Hash MSRs are rewritten as necessary to match
595 * the enclave's MRSIGNER, which is caculated from the provided sigstruct.
596 *
597 * Return:
598 * - 0: Success.
599 * - -EPERM: Invalid SIGSTRUCT.
600 * - -EIO: EINIT failed because of a power cycle.
601 * - -errno: POSIX error.
602 */
sgx_ioc_enclave_init(struct sgx_encl * encl,void __user * arg)603 static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg)
604 {
605 struct sgx_sigstruct *sigstruct;
606 struct sgx_enclave_init init_arg;
607 void *token;
608 int ret;
609
610 if (!test_bit(SGX_ENCL_CREATED, &encl->flags) ||
611 test_bit(SGX_ENCL_INITIALIZED, &encl->flags))
612 return -EINVAL;
613
614 if (copy_from_user(&init_arg, arg, sizeof(init_arg)))
615 return -EFAULT;
616
617 /*
618 * 'sigstruct' must be on a page boundary and 'token' on a 512 byte
619 * boundary. kmalloc() will give this alignment when allocating
620 * PAGE_SIZE bytes.
621 */
622 sigstruct = kmalloc(PAGE_SIZE, GFP_KERNEL);
623 if (!sigstruct)
624 return -ENOMEM;
625
626 token = (void *)((unsigned long)sigstruct + PAGE_SIZE / 2);
627 memset(token, 0, SGX_LAUNCH_TOKEN_SIZE);
628
629 if (copy_from_user(sigstruct, (void __user *)init_arg.sigstruct,
630 sizeof(*sigstruct))) {
631 ret = -EFAULT;
632 goto out;
633 }
634
635 /*
636 * A legacy field used with Intel signed enclaves. These used to mean
637 * regular and architectural enclaves. The CPU only accepts these values
638 * but they do not have any other meaning.
639 *
640 * Thus, reject any other values.
641 */
642 if (sigstruct->header.vendor != 0x0000 &&
643 sigstruct->header.vendor != 0x8086) {
644 ret = -EINVAL;
645 goto out;
646 }
647
648 ret = sgx_encl_init(encl, sigstruct, token);
649
650 out:
651 kfree(sigstruct);
652 return ret;
653 }
654
655 /**
656 * sgx_ioc_enclave_provision() - handler for %SGX_IOC_ENCLAVE_PROVISION
657 * @encl: an enclave pointer
658 * @arg: userspace pointer to a struct sgx_enclave_provision instance
659 *
660 * Allow ATTRIBUTE.PROVISION_KEY for an enclave by providing a file handle to
661 * /dev/sgx_provision.
662 *
663 * Return:
664 * - 0: Success.
665 * - -errno: Otherwise.
666 */
sgx_ioc_enclave_provision(struct sgx_encl * encl,void __user * arg)667 static long sgx_ioc_enclave_provision(struct sgx_encl *encl, void __user *arg)
668 {
669 struct sgx_enclave_provision params;
670
671 if (copy_from_user(¶ms, arg, sizeof(params)))
672 return -EFAULT;
673
674 return sgx_set_attribute(&encl->attributes_mask, params.fd);
675 }
676
sgx_ioctl(struct file * filep,unsigned int cmd,unsigned long arg)677 long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
678 {
679 struct sgx_encl *encl = filep->private_data;
680 int ret;
681
682 if (test_and_set_bit(SGX_ENCL_IOCTL, &encl->flags))
683 return -EBUSY;
684
685 switch (cmd) {
686 case SGX_IOC_ENCLAVE_CREATE:
687 ret = sgx_ioc_enclave_create(encl, (void __user *)arg);
688 break;
689 case SGX_IOC_ENCLAVE_ADD_PAGES:
690 ret = sgx_ioc_enclave_add_pages(encl, (void __user *)arg);
691 break;
692 case SGX_IOC_ENCLAVE_INIT:
693 ret = sgx_ioc_enclave_init(encl, (void __user *)arg);
694 break;
695 case SGX_IOC_ENCLAVE_PROVISION:
696 ret = sgx_ioc_enclave_provision(encl, (void __user *)arg);
697 break;
698 default:
699 ret = -ENOIOCTLCMD;
700 break;
701 }
702
703 clear_bit(SGX_ENCL_IOCTL, &encl->flags);
704 return ret;
705 }
706