From 2854f53b8b3780a3edc4711fdeb10221cb156c11 Mon Sep 17 00:00:00 2001
From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date: Tue, 19 Dec 2017 14:22:22 +0200
Subject: [PATCH] Clean up IPC of the launch control

Merged user_wq and kernel_wq into single wq instance. Replaced raw
buffer with struct sgx_launch_request instance in order to simplify the
code and avoid unnecessary copies.  Removed buf_lock. It is not needed
because kernel and user space parts take turns by having separate wait
conditions.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/platform/x86/intel_sgx/sgx_le.c | 63 +++++++++++++++------------------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/platform/x86/intel_sgx/sgx_le.c b/drivers/platform/x86/intel_sgx/sgx_le.c
index 842d4e03dd27..f196c7a4b609 100644
--- a/drivers/platform/x86/intel_sgx/sgx_le.c
+++ b/drivers/platform/x86/intel_sgx/sgx_le.c
@@ -72,12 +72,10 @@ struct sgx_le_ctx {
 	struct mutex hash_lock;
 	struct mutex launch_lock;
 	struct rw_semaphore users;
-	wait_queue_head_t kernel_wq;
-	wait_queue_head_t user_wq;
-	struct mutex buf_lock;
+	wait_queue_head_t wq;
 	bool kernel_read;
 	bool user_read;
-	u8 buf[PAGE_SIZE];
+	struct sgx_launch_request req;
 };
 
 struct sgx_le_ctx sgx_le_ctx;
@@ -88,14 +86,17 @@ static ssize_t sgx_le_ctx_fops_read(struct file *filp, char __user *buf,
 	struct sgx_le_ctx *ctx = filp->private_data;
 	int ret;
 
-	ret = wait_event_interruptible(ctx->user_wq, ctx->user_read);
+	if (count != sizeof(ctx->req)) {
+		pr_crit("intel_sgx: %s: invalid count %lu\n", __func__, count);
+		return -EIO;
+	}
+
+	ret = wait_event_interruptible(ctx->wq, ctx->user_read);
 	if (ret)
 		return -EINTR;
 
-	mutex_lock(&ctx->buf_lock);
-	ret = copy_to_user(buf, ctx->buf, count);
+	ret = copy_to_user(buf, &ctx->req, count);
 	ctx->user_read = false;
-	mutex_unlock(&ctx->buf_lock);
 
 	return ret ? ret : count;
 }
@@ -106,12 +107,15 @@ static ssize_t sgx_le_ctx_fops_write(struct file *filp, const char __user *buf,
 	struct sgx_le_ctx *ctx = filp->private_data;
 	int ret;
 
-	mutex_lock(&ctx->buf_lock);
-	ret = copy_from_user(ctx->buf, buf, count);
+	if (count != sizeof(ctx->req.token)) {
+		pr_crit("intel_sgx: %s: invalid count %lu\n", __func__, count);
+		return -EIO;
+	}
+
+	ret = copy_from_user(&ctx->req.token, buf, count);
 	if (!ret)
 		ctx->kernel_read = true;
-	wake_up_interruptible(&ctx->kernel_wq);
-	mutex_unlock(&ctx->buf_lock);
+	wake_up_interruptible(&ctx->wq);
 
 	return ret ? ret : count;
 }
@@ -241,9 +245,7 @@ int sgx_le_init(struct sgx_le_ctx *ctx)
 	mutex_init(&ctx->hash_lock);
 	mutex_init(&ctx->launch_lock);
 	init_rwsem(&ctx->users);
-	init_waitqueue_head(&ctx->kernel_wq);
-	init_waitqueue_head(&ctx->user_wq);
-	mutex_init(&ctx->buf_lock);
+	init_waitqueue_head(&ctx->wq);
 
 	return 0;
 }
@@ -257,7 +259,6 @@ void sgx_le_exit(struct sgx_le_ctx *ctx)
 
 static int __sgx_le_get_token(struct sgx_le_ctx *ctx,
 			      const struct sgx_encl *encl,
-			      struct sgx_launch_request *req,
 			      struct sgx_einittoken *token)
 {
 	ssize_t ret;
@@ -265,22 +266,15 @@ static int __sgx_le_get_token(struct sgx_le_ctx *ctx,
 	if (!ctx->tgid)
 		return -EIO;
 
-	/* write request */
-	mutex_lock(&ctx->buf_lock);
-	memcpy(ctx->buf, req, sizeof(*req));
 	ctx->user_read = true;
-	wake_up_interruptible(&ctx->user_wq);
-	mutex_unlock(&ctx->buf_lock);
+	wake_up_interruptible(&ctx->wq);
 
-	/* read token */
-	ret = wait_event_interruptible(ctx->kernel_wq, ctx->kernel_read);
+	ret = wait_event_interruptible(ctx->wq, ctx->kernel_read);
 	if (ret)
 		return -EINTR;
 
-	mutex_lock(&ctx->buf_lock);
-	memcpy(token, ctx->buf, sizeof(*token));
+	memcpy(token, &ctx->req.token, sizeof(*token));
 	ctx->kernel_read = false;
-	mutex_unlock(&ctx->buf_lock);
 
 	return 0;
 }
@@ -290,27 +284,28 @@ int sgx_le_get_token(struct sgx_le_ctx *ctx,
 		     const struct sgx_sigstruct *sigstruct,
 		     struct sgx_einittoken *token)
 {
-	struct sgx_launch_request req;
+	u8 mrsigner[32];
 	int ret;
 
 	mutex_lock(&ctx->hash_lock);
-	ret = sgx_get_key_hash(ctx->tfm, sigstruct->modulus, &req.mrsigner);
+	ret = sgx_get_key_hash(ctx->tfm, sigstruct->modulus, mrsigner);
 	if (ret) {
 		mutex_unlock(&ctx->hash_lock);
 		return ret;
 	}
-	if (!memcmp(&req.mrsigner, sgx_le_pubkeyhash, 32)) {
+	if (!memcmp(mrsigner, sgx_le_pubkeyhash, 32)) {
 		mutex_unlock(&ctx->hash_lock);
 		return 0;
 	}
 	mutex_unlock(&ctx->hash_lock);
 
-	memcpy(&req.mrenclave, sigstruct->body.mrenclave, 32);
-	req.attributes = encl->attributes;
-	req.xfrm = encl->xfrm;
-
 	mutex_lock(&ctx->launch_lock);
-	ret = __sgx_le_get_token(ctx, encl, &req, token);
+	memcpy(&ctx->req.mrenclave, sigstruct->body.mrenclave, 32);
+	memcpy(&ctx->req.mrsigner, mrsigner, 32);
+	ctx->req.attributes = encl->attributes;
+	ctx->req.xfrm = encl->xfrm;
+	memset(&ctx->req.token, 0, sizeof(ctx->req.token));
+	ret = __sgx_le_get_token(ctx, encl, token);
 	mutex_unlock(&ctx->launch_lock);
 
 	return ret;
-- 
2.14.1

