forked from oscarlab/graphene-sgx-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gsgx_ioctl_1_7.c
173 lines (146 loc) · 4.56 KB
/
gsgx_ioctl_1_7.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
* (C) Copyright 2013 Intel Corporation
* Author: Jarkko Sakkinen <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/highmem.h>
#include <linux/miscdevice.h>
#include <linux/vmalloc.h>
#include <linux/security.h>
#include <asm/tlbflush.h>
#include "gsgx.h"
#if SDK_DRIVER_VERSION == KERNEL_VERSION(1, 7, 0)
struct file *isgx_dev;
static long enclave_create(struct file *filep, void * arg)
{
struct gsgx_enclave_create *createp = arg;
struct sgx_enclave_create isgx_create;
isgx_create.src = createp->src;
filep->private_data = (void *) createp->src;
return KSYM(isgx_ioctl_enclave_create)(filep, SGX_IOC_ENCLAVE_CREATE,
(unsigned long) &isgx_create);
}
static long enclave_add_pages(struct file *filep, void * arg)
{
struct gsgx_enclave_add_pages *addp = arg;
struct sgx_enclave_add_page isgx_add;
uint64_t off;
int ret = 0;
if (!addp->addr || (addp->addr & (PAGE_SIZE - 1)))
return -EINVAL;
if (!addp->size || (addp->size & (PAGE_SIZE - 1)))
return -EINVAL;
if (!addp->secinfo)
return -EINVAL;
isgx_add.secinfo = addp->secinfo;
for (off = 0 ; off < addp->size ; off += PAGE_SIZE) {
isgx_add.addr = addp->addr + off;
isgx_add.src =
addp->flags & GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC ?
addp->user_addr : addp->user_addr + off;
isgx_add.mrmask =
addp->flags & GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND ?
0 : ~0;
ret = KSYM(isgx_ioctl_enclave_add_page)(filep,
SGX_IOC_ENCLAVE_ADD_PAGE, (unsigned long) &isgx_add);
if (ret < 0)
break;
}
return ret;
}
static long enclave_init(struct file *filep, void * arg)
{
struct gsgx_enclave_init *initp = arg;
struct sgx_enclave_init isgx_init;
isgx_init.addr = initp->addr;
isgx_init.sigstruct = initp->sigstruct;
isgx_init.einittoken = initp->einittoken;
return KSYM(isgx_ioctl_enclave_init)(filep, SGX_IOC_ENCLAVE_INIT,
(unsigned long) &isgx_init);
}
long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
char data[256];
long (*handler) (struct file *filp, void *arg) = NULL;
long ret;
switch (cmd) {
case GSGX_IOCTL_ENCLAVE_CREATE:
handler = enclave_create;
break;
case GSGX_IOCTL_ENCLAVE_ADD_PAGES:
handler = enclave_add_pages;
break;
case GSGX_IOCTL_ENCLAVE_INIT:
handler = enclave_init;
break;
default:
return -EINVAL;
}
if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd)))
return -EFAULT;
ret = handler(filep, (void *) data);
if (!ret && (cmd & IOC_OUT)) {
if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd)))
return -EFAULT;
}
return ret;
}
int gsgx_mmap(struct file *file, struct vm_area_struct *vma)
{
return KSYM(isgx_mmap)(file, vma);
}
unsigned long gsgx_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
if (file->private_data == (void *) GSGX_ENCLAVE_CREATE_NO_ADDR) {
unsigned long unmapped_addr =
KSYM(isgx_get_unmapped_area)(file, addr, len,
pgoff, flags);
file->private_data = (void *) unmapped_addr;
return unmapped_addr;
} else {
unsigned long unmapped_addr = (unsigned long) file->private_data;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma = find_vma(mm, unmapped_addr);
if (vma && vma->vm_start <= len)
return -EINVAL;
return unmapped_addr;
}
}
IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
struct file *filep, unsigned int cmd, unsigned long arg);
IMPORT_KSYM_PROTO(isgx_ioctl_enclave_init, long,
struct file *filep, unsigned int cmd, unsigned long arg);
IMPORT_KSYM_PROTO(isgx_ioctl_enclave_add_page, long,
struct file *filep, unsigned int cmd, unsigned long arg);
IMPORT_KSYM(isgx_enclave_release);
IMPORT_KSYM_PROTO(isgx_mmap, int, struct file *, struct vm_area_struct *);
IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
struct file *, unsigned long, unsigned long,
unsigned long, unsigned long);
int gsgx_lookup_ksyms(void)
{
int ret;
if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_create)))
return ret;
if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_init)))
return ret;
if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_add_page)))
return ret;
if ((ret = LOOKUP_KSYM(isgx_enclave_release)))
return ret;
if ((ret = LOOKUP_KSYM(isgx_mmap)))
return ret;
if ((ret = LOOKUP_KSYM(isgx_get_unmapped_area)))
return ret;
return 0;
}
#endif /* SGX_DRIVER_VERSION == 1.7 */