@@ -60,9 +60,11 @@ struct sgx_enclave_add_pages {
* struct sgx_enclave_init - parameter structure for the
* %SGX_IOC_ENCLAVE_INIT ioctl
* @sigstruct: address for the SIGSTRUCT data
+ * @enclave_fd: file handle of the enclave
*/
struct sgx_enclave_init {
__u64 sigstruct;
+ __u64 enclave_fd;
};
/**
@@ -606,9 +606,11 @@ static int sgx_einit(struct sgx_sigstruct *sigstruct, void *token,
return ret;
}
-static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
- void *token)
+static int __sgx_ioc_enclave_init(struct file *filep,
+ struct sgx_sigstruct *sigstruct, void *token)
{
+ struct file *encl_file = filep->private_data;
+ struct sgx_encl *encl = encl_file->private_data;
u64 mrsigner[4];
int ret;
int i;
@@ -656,35 +658,39 @@ static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
sgx_encl_destroy(encl);
ret = -EFAULT;
+ goto err_out;
} else if (ret) {
pr_debug("EINIT returned %d\n", ret);
ret = -EPERM;
- } else {
- atomic_or(SGX_ENCL_INITIALIZED, &encl->flags);
+ goto err_out;
}
+ /* Transfer the ownership of the enclave file to the user space. */
+ ret = get_unused_fd_flags(O_RDWR);
+ if (ret < 0)
+ goto err_out;
+
+ filep->private_data = NULL;
+ fd_install(ret, encl_file);
+
+ atomic_or(SGX_ENCL_INITIALIZED, &encl->flags);
+
err_out:
mutex_unlock(&encl->lock);
return ret;
}
-/**
- * sgx_ioc_enclave_init - handler for %SGX_IOC_ENCLAVE_INIT
- *
- * @filep: open file to /dev/sgx
- * @arg: userspace pointer to a struct sgx_enclave_init instance
- *
- * Flush any outstanding enqueued EADD operations and perform EINIT. The
- * Launch Enclave Public Key Hash MSRs are rewritten as necessary to match
- * the enclave's MRSIGNER, which is caculated from the provided sigstruct.
- *
- * Return:
- * 0 on success,
- * SGX error code on EINIT failure,
- * -errno otherwise
+/*
+ * Initialize the enclave by performing ENCLS[EINIT] and hand over the enclave
+ * file to the user space. The function also checks whether the LE public key
+ * hash MSRs are out of date and updates them as necessary before performing
+ * ENCLS[EINIT].
*/
-static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg)
+static long sgx_ioc_enclave_init(struct file *filep,
+ struct sgx_enclave_init __user *arg)
{
+ struct file *encl_file = filep->private_data;
+ struct sgx_encl *encl = encl_file->private_data;
struct sgx_sigstruct *sigstruct;
struct sgx_enclave_init einit;
struct page *initp_page;
@@ -708,12 +714,16 @@ static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg)
if (copy_from_user(sigstruct, (void __user *)einit.sigstruct,
sizeof(*sigstruct))) {
ret = -EFAULT;
- goto out;
+ goto err;
}
- ret = sgx_encl_init(encl, sigstruct, token);
+ ret = __sgx_ioc_enclave_init(filep, sigstruct, token);
+ if (ret < 0)
+ goto err;
-out:
+ ret = put_user((uint64_t)ret, &arg->enclave_fd);
+
+err:
kunmap(initp_page);
__free_page(initp_page);
return ret;
@@ -785,7 +795,7 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
ret = sgx_ioc_enclave_add_pages(encl, (void __user *)arg);
break;
case SGX_IOC_ENCLAVE_INIT:
- ret = sgx_ioc_enclave_init(encl, (void __user *)arg);
+ ret = sgx_ioc_enclave_init(filep, (void __user *)arg);
break;
case SGX_IOC_ENCLAVE_SET_ATTRIBUTE:
ret = sgx_ioc_enclave_set_attribute(encl, (void __user *)arg);
@@ -27,8 +27,11 @@ void encl_delete(struct encl *encl)
if (encl->bin)
munmap(encl->bin, encl->bin_size);
- if (encl->fd)
- close(encl->fd);
+ if (encl->encl_fd)
+ close(encl->encl_fd);
+
+ if (encl->dev_fd)
+ close(encl->dev_fd);
if (encl->segment_tbl)
free(encl->segment_tbl);
@@ -88,7 +91,7 @@ static bool encl_ioc_create(struct encl *encl)
secs->size = encl->encl_size;
ioc.src = (unsigned long)secs;
- rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_CREATE, &ioc);
+ rc = ioctl(encl->dev_fd, SGX_IOC_ENCLAVE_CREATE, &ioc);
if (rc) {
fprintf(stderr, "SGX_IOC_ENCLAVE_CREATE failed: errno=%d\n",
errno);
@@ -114,7 +117,7 @@ static bool encl_ioc_add_pages(struct encl *encl, struct encl_segment *seg)
ioc.secinfo = (unsigned long)&secinfo;
ioc.flags = SGX_PAGE_MEASURE;
- rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_ADD_PAGES, &ioc);
+ rc = ioctl(encl->dev_fd, SGX_IOC_ENCLAVE_ADD_PAGES, &ioc);
if (rc) {
fprintf(stderr, "SGX_IOC_ENCLAVE_ADD_PAGES failed: errno=%d.\n",
errno);
@@ -145,7 +148,7 @@ bool encl_load(const char *path, struct encl *encl)
goto err;
}
- encl->fd = ret;
+ encl->dev_fd = ret;
if (!encl_map_bin(path, encl))
goto err;
@@ -271,12 +274,13 @@ bool encl_build(struct encl *encl)
}
ioc.sigstruct = (uint64_t)&encl->sigstruct;
- ret = ioctl(encl->fd, SGX_IOC_ENCLAVE_INIT, &ioc);
+ ret = ioctl(encl->dev_fd, SGX_IOC_ENCLAVE_INIT, &ioc);
if (ret) {
fprintf(stderr, "SGX_IOC_ENCLAVE_INIT failed: errno=%d\n",
errno);
return false;
}
+ encl->encl_fd = ioc.enclave_fd;
return true;
}
@@ -149,7 +149,8 @@ int main(int argc, char *argv[], char *envp[])
struct encl_segment *seg = &encl.segment_tbl[i];
addr = mmap((void *)encl.encl_base + seg->offset, seg->size,
- seg->prot, MAP_SHARED | MAP_FIXED, encl.fd, 0);
+ seg->prot, MAP_SHARED | MAP_FIXED, encl.encl_fd,
+ 0);
if (addr == MAP_FAILED) {
fprintf(stderr, "mmap() failed, errno=%d.\n", errno);
return false;
@@ -14,7 +14,8 @@ struct encl_segment {
};
struct encl {
- int fd;
+ int dev_fd;
+ int encl_fd;
void *bin;
off_t bin_size;
void *src;
Add a new output parameter, @enclave_fd, to struct sgx_enclave_init, which will receive a file descriptor pointing the enclave file whose ownership is transferred to the user space. While doing this, replace the comment prepending sgx_ioc_enclave_init() with a regular (not kdoc) comment given that it was out of date and the function is internal. Cc: luto@kernel.org Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: Casey Schaufler <casey@schaufler-ca.com> Cc: Haitao Huang <haitao.huang@linux.intel.com> Cc: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- arch/x86/include/uapi/asm/sgx.h | 2 ++ arch/x86/kernel/cpu/sgx/ioctl.c | 56 ++++++++++++++++++------------ tools/testing/selftests/sgx/load.c | 16 +++++---- tools/testing/selftests/sgx/main.c | 3 +- tools/testing/selftests/sgx/main.h | 3 +- 5 files changed, 49 insertions(+), 31 deletions(-)