Skip to content

Commit 888d249

Browse files
jarkkojssuryasaimadhu
authored andcommitted
x86/sgx: Add SGX_IOC_ENCLAVE_CREATE
Add an ioctl() that performs the ECREATE function of the ENCLS instruction, which creates an SGX Enclave Control Structure (SECS). Although the SECS is an in-memory data structure, it is present in enclave memory and is not directly accessible by software. Co-developed-by: Sean Christopherson <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Tested-by: Jethro Beekman <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 3fe0778 commit 888d249

File tree

8 files changed

+180
-0
lines changed

8 files changed

+180
-0
lines changed

Documentation/userspace-api/ioctl/ioctl-number.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ Code Seq# Include File Comments
323323
324324
0xA3 90-9F linux/dtlk.h
325325
0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem
326+
0xA4 00-1F uapi/asm/sgx.h <mailto:[email protected]>
326327
0xAA 00-3F linux/uapi/linux/userfaultfd.h
327328
0xAB 00-1F linux/nbd.h
328329
0xAC 00-1F linux/raw.h

arch/x86/include/uapi/asm/sgx.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+
/*
3+
* Copyright(c) 2016-20 Intel Corporation.
4+
*/
5+
#ifndef _UAPI_ASM_X86_SGX_H
6+
#define _UAPI_ASM_X86_SGX_H
7+
8+
#include <linux/types.h>
9+
#include <linux/ioctl.h>
10+
11+
#define SGX_MAGIC 0xA4
12+
13+
#define SGX_IOC_ENCLAVE_CREATE \
14+
_IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create)
15+
16+
/**
17+
* struct sgx_enclave_create - parameter structure for the
18+
* %SGX_IOC_ENCLAVE_CREATE ioctl
19+
* @src: address for the SECS page data
20+
*/
21+
struct sgx_enclave_create {
22+
__u64 src;
23+
};
24+
25+
#endif /* _UAPI_ASM_X86_SGX_H */

arch/x86/kernel/cpu/sgx/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
obj-y += \
22
driver.o \
33
encl.o \
4+
ioctl.o \
45
main.o

arch/x86/kernel/cpu/sgx/driver.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,22 @@ static unsigned long sgx_get_unmapped_area(struct file *file,
8888
return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
8989
}
9090

91+
#ifdef CONFIG_COMPAT
92+
static long sgx_compat_ioctl(struct file *filep, unsigned int cmd,
93+
unsigned long arg)
94+
{
95+
return sgx_ioctl(filep, cmd, arg);
96+
}
97+
#endif
98+
9199
static const struct file_operations sgx_encl_fops = {
92100
.owner = THIS_MODULE,
93101
.open = sgx_open,
94102
.release = sgx_release,
103+
.unlocked_ioctl = sgx_ioctl,
104+
#ifdef CONFIG_COMPAT
105+
.compat_ioctl = sgx_compat_ioctl,
106+
#endif
95107
.mmap = sgx_mmap,
96108
.get_unmapped_area = sgx_get_unmapped_area,
97109
};

arch/x86/kernel/cpu/sgx/driver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
#include <linux/rwsem.h>
1010
#include <linux/sched.h>
1111
#include <linux/workqueue.h>
12+
#include <uapi/asm/sgx.h>
1213
#include "sgx.h"
1314

15+
long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
16+
1417
int sgx_drv_init(void);
1518

1619
#endif /* __ARCH_X86_SGX_DRIVER_H__ */

arch/x86/kernel/cpu/sgx/encl.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf)
4646
struct sgx_encl_page *entry;
4747
unsigned long phys_addr;
4848
struct sgx_encl *encl;
49+
unsigned long pfn;
4950
vm_fault_t ret;
5051

5152
encl = vma->vm_private_data;
@@ -61,6 +62,13 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf)
6162

6263
phys_addr = sgx_get_epc_phys_addr(entry->epc_page);
6364

65+
/* Check if another thread got here first to insert the PTE. */
66+
if (!follow_pfn(vma, addr, &pfn)) {
67+
mutex_unlock(&encl->lock);
68+
69+
return VM_FAULT_NOPAGE;
70+
}
71+
6472
ret = vmf_insert_pfn(vma, addr, PFN_DOWN(phys_addr));
6573
if (ret != VM_FAULT_NOPAGE) {
6674
mutex_unlock(&encl->lock);

arch/x86/kernel/cpu/sgx/encl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,16 @@ struct sgx_encl_page {
2626
struct sgx_encl *encl;
2727
};
2828

29+
enum sgx_encl_flags {
30+
SGX_ENCL_IOCTL = BIT(0),
31+
SGX_ENCL_DEBUG = BIT(1),
32+
SGX_ENCL_CREATED = BIT(2),
33+
};
34+
2935
struct sgx_encl {
3036
unsigned long base;
3137
unsigned long size;
38+
unsigned long flags;
3239
unsigned int page_cnt;
3340
unsigned int secs_child_cnt;
3441
struct mutex lock;

arch/x86/kernel/cpu/sgx/ioctl.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright(c) 2016-20 Intel Corporation. */
3+
4+
#include <asm/mman.h>
5+
#include <linux/mman.h>
6+
#include <linux/delay.h>
7+
#include <linux/file.h>
8+
#include <linux/hashtable.h>
9+
#include <linux/highmem.h>
10+
#include <linux/ratelimit.h>
11+
#include <linux/sched/signal.h>
12+
#include <linux/shmem_fs.h>
13+
#include <linux/slab.h>
14+
#include <linux/suspend.h>
15+
#include "driver.h"
16+
#include "encl.h"
17+
#include "encls.h"
18+
19+
static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
20+
{
21+
struct sgx_epc_page *secs_epc;
22+
struct sgx_pageinfo pginfo;
23+
struct sgx_secinfo secinfo;
24+
unsigned long encl_size;
25+
long ret;
26+
27+
/* The extra page goes to SECS. */
28+
encl_size = secs->size + PAGE_SIZE;
29+
30+
secs_epc = __sgx_alloc_epc_page();
31+
if (IS_ERR(secs_epc))
32+
return PTR_ERR(secs_epc);
33+
34+
encl->secs.epc_page = secs_epc;
35+
36+
pginfo.addr = 0;
37+
pginfo.contents = (unsigned long)secs;
38+
pginfo.metadata = (unsigned long)&secinfo;
39+
pginfo.secs = 0;
40+
memset(&secinfo, 0, sizeof(secinfo));
41+
42+
ret = __ecreate((void *)&pginfo, sgx_get_epc_virt_addr(secs_epc));
43+
if (ret) {
44+
ret = -EIO;
45+
goto err_out;
46+
}
47+
48+
if (secs->attributes & SGX_ATTR_DEBUG)
49+
set_bit(SGX_ENCL_DEBUG, &encl->flags);
50+
51+
encl->secs.encl = encl;
52+
encl->base = secs->base;
53+
encl->size = secs->size;
54+
55+
/* Set only after completion, as encl->lock has not been taken. */
56+
set_bit(SGX_ENCL_CREATED, &encl->flags);
57+
58+
return 0;
59+
60+
err_out:
61+
sgx_free_epc_page(encl->secs.epc_page);
62+
encl->secs.epc_page = NULL;
63+
64+
return ret;
65+
}
66+
67+
/**
68+
* sgx_ioc_enclave_create() - handler for %SGX_IOC_ENCLAVE_CREATE
69+
* @encl: An enclave pointer.
70+
* @arg: The ioctl argument.
71+
*
72+
* Allocate kernel data structures for the enclave and invoke ECREATE.
73+
*
74+
* Return:
75+
* - 0: Success.
76+
* - -EIO: ECREATE failed.
77+
* - -errno: POSIX error.
78+
*/
79+
static long sgx_ioc_enclave_create(struct sgx_encl *encl, void __user *arg)
80+
{
81+
struct sgx_enclave_create create_arg;
82+
void *secs;
83+
int ret;
84+
85+
if (test_bit(SGX_ENCL_CREATED, &encl->flags))
86+
return -EINVAL;
87+
88+
if (copy_from_user(&create_arg, arg, sizeof(create_arg)))
89+
return -EFAULT;
90+
91+
secs = kmalloc(PAGE_SIZE, GFP_KERNEL);
92+
if (!secs)
93+
return -ENOMEM;
94+
95+
if (copy_from_user(secs, (void __user *)create_arg.src, PAGE_SIZE))
96+
ret = -EFAULT;
97+
else
98+
ret = sgx_encl_create(encl, secs);
99+
100+
kfree(secs);
101+
return ret;
102+
}
103+
104+
long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
105+
{
106+
struct sgx_encl *encl = filep->private_data;
107+
int ret;
108+
109+
if (test_and_set_bit(SGX_ENCL_IOCTL, &encl->flags))
110+
return -EBUSY;
111+
112+
switch (cmd) {
113+
case SGX_IOC_ENCLAVE_CREATE:
114+
ret = sgx_ioc_enclave_create(encl, (void __user *)arg);
115+
break;
116+
default:
117+
ret = -ENOIOCTLCMD;
118+
break;
119+
}
120+
121+
clear_bit(SGX_ENCL_IOCTL, &encl->flags);
122+
return ret;
123+
}

0 commit comments

Comments
 (0)