diff mbox series

[4/4] x86/sgx: Hand over the enclave file to the user space

Message ID 20200331114432.7593-5-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Migrate enclave mapping to an anonymous inode | expand

Commit Message

Jarkko Sakkinen March 31, 2020, 11:44 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h
index e196cfd44b70..62f990c0a295 100644
--- a/arch/x86/include/uapi/asm/sgx.h
+++ b/arch/x86/include/uapi/asm/sgx.h
@@ -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;
 };
 
 /**
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 891aa9395907..b25e18622c02 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -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);
diff --git a/tools/testing/selftests/sgx/load.c b/tools/testing/selftests/sgx/load.c
index 53c565347e9e..ee5792f98162 100644
--- a/tools/testing/selftests/sgx/load.c
+++ b/tools/testing/selftests/sgx/load.c
@@ -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;
 }
diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c
index 9238cce47f77..17bf57909435 100644
--- a/tools/testing/selftests/sgx/main.c
+++ b/tools/testing/selftests/sgx/main.c
@@ -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;
diff --git a/tools/testing/selftests/sgx/main.h b/tools/testing/selftests/sgx/main.h
index 6e1ae292bd25..cf0d4cf20fb0 100644
--- a/tools/testing/selftests/sgx/main.h
+++ b/tools/testing/selftests/sgx/main.h
@@ -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;