Browse Source

securemsm-kernel: smcinvoke: Call object release sync once before adding to queue

call release tz object in sync manner
only in case of EBUSY add
object in to post process list, so that we can retry
and process it later in a seprate kthread.

Change-Id: I2158b3faa5c41d2f10ed532c50c9c6b113961c57
Nitin LNU 2 years ago
parent
commit
b87455c99c
1 changed files with 79 additions and 42 deletions
  1. 79 42
      smcinvoke/smcinvoke.c

+ 79 - 42
smcinvoke/smcinvoke.c

@@ -539,17 +539,45 @@ static void smcinvoke_shmbridge_post_process(void)
 	} while (1);
 }
 
-static int smcinvoke_object_post_process(void)
+static int smcinvoke_release_tz_object(struct qtee_shm *in_shm, struct qtee_shm *out_shm,
+		uint32_t tzhandle, uint32_t context_type)
 {
-	struct smcinvoke_object_release_pending_list *entry = NULL;
-	struct list_head *pos;
 	int ret = 0;
 	bool release_handles;
-	uint32_t context_type;
 	uint8_t *in_buf = NULL;
-	uint8_t *out_buf = NULL;
-	struct smcinvoke_cmd_req req = {0};
+        uint8_t *out_buf = NULL;
 	struct smcinvoke_msg_hdr hdr = {0};
+	struct smcinvoke_cmd_req req = {0};
+
+	in_buf = in_shm->vaddr;
+	out_buf = out_shm->vaddr;
+	hdr.tzhandle = tzhandle;
+	hdr.op = OBJECT_OP_RELEASE;
+	hdr.counts = 0;
+	*(struct smcinvoke_msg_hdr *)in_buf = hdr;
+
+	ret = prepare_send_scm_msg(in_buf, in_shm->paddr,
+			SMCINVOKE_TZ_MIN_BUF_SIZE, out_buf, out_shm->paddr,
+			SMCINVOKE_TZ_MIN_BUF_SIZE, &req, NULL,
+			&release_handles, context_type, in_shm, out_shm);
+	process_piggyback_data(out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE);
+	if (ret) {
+		pr_err("Failed to release object(0x%x), ret:%d\n",
+				hdr.tzhandle, ret);
+	} else {
+		pr_debug("Released object(0x%x) successfully.\n",
+				hdr.tzhandle);
+	}
+
+	return ret;
+}
+
+
+static int smcinvoke_object_post_process(void)
+{
+	struct smcinvoke_object_release_pending_list *entry = NULL;
+	struct list_head *pos;
+	int ret = 0;
 	struct qtee_shm in_shm = {0}, out_shm = {0};
 
 	ret = qtee_shmbridge_allocate_shm(SMCINVOKE_TZ_MIN_BUF_SIZE, &in_shm);
@@ -574,37 +602,19 @@ static int smcinvoke_object_post_process(void)
 		}
 		pos = g_object_postprocess.next;
 		entry = list_entry(pos, struct smcinvoke_object_release_pending_list, list);
-		if (entry) {
-			in_buf = in_shm.vaddr;
-			out_buf = out_shm.vaddr;
-			hdr.tzhandle = entry->data.tzhandle;
-			hdr.op = OBJECT_OP_RELEASE;
-			hdr.counts = 0;
-			*(struct smcinvoke_msg_hdr *)in_buf = hdr;
-			context_type = entry->data.context_type;
-		} else {
-			pr_err("entry is NULL, pos:%#llx\n", (uint64_t)pos);
-		}
+
 		list_del(pos);
-		kfree_sensitive(entry);
 		mutex_unlock(&object_postprocess_lock);
 
 		if (entry) {
 			do {
-				ret = prepare_send_scm_msg(in_buf, in_shm.paddr,
-					SMCINVOKE_TZ_MIN_BUF_SIZE, out_buf, out_shm.paddr,
-					SMCINVOKE_TZ_MIN_BUF_SIZE, &req, NULL,
-					&release_handles, context_type, &in_shm, &out_shm);
-				process_piggyback_data(out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE);
-				if (ret) {
-					pr_err("Failed to release object(0x%x), ret:%d\n",
-								hdr.tzhandle, ret);
-				} else {
-					pr_debug("Released object(0x%x) successfully.\n",
-									hdr.tzhandle);
-				}
+				ret = smcinvoke_release_tz_object(&in_shm, &out_shm,
+					       	entry->data.tzhandle,  entry->data.context_type);
 			} while (-EBUSY == ret);
+		} else {
+			pr_err("entry is NULL, pos:%#llx\n", (uint64_t)pos);
 		}
+		kfree_sensitive(entry);
 	} while (1);
 
 out:
@@ -3010,6 +3020,7 @@ int smcinvoke_release_filp(struct file *filp)
 	struct smcinvoke_file_data *file_data = filp->private_data;
 	uint32_t tzhandle = 0;
 	struct smcinvoke_object_release_pending_list *entry = NULL;
+	struct qtee_shm in_shm = {0}, out_shm = {0};
 
 	trace_smcinvoke_release_filp(current->files, filp,
 			file_count(filp), file_data->context_type);
@@ -3021,29 +3032,55 @@ int smcinvoke_release_filp(struct file *filp)
 
 	tzhandle = file_data->tzhandle;
 	/* Root object is special in sense it is indestructible */
-	if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ)
+	if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ) {
+		if (!tzhandle)
+			pr_err("tzhandle not valid in object release\n");
 		goto out;
+	}
 
-	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-	if (!entry) {
-		ret = -ENOMEM;
+	ret = qtee_shmbridge_allocate_shm(SMCINVOKE_TZ_MIN_BUF_SIZE, &in_shm);
+	if (ret) {
+		pr_err("shmbridge alloc failed for in msg in object release"
+				"with ret %d\n", ret);
 		goto out;
 	}
 
-	entry->data.tzhandle = tzhandle;
-	entry->data.context_type = file_data->context_type;
-	mutex_lock(&object_postprocess_lock);
-	list_add_tail(&entry->list, &g_object_postprocess);
-	mutex_unlock(&object_postprocess_lock);
-	pr_debug("Object release list: added a handle:0x%lx\n", tzhandle);
-	__wakeup_postprocess_kthread(&smcinvoke[OBJECT_WORKER_THREAD]);
+	ret = qtee_shmbridge_allocate_shm(SMCINVOKE_TZ_MIN_BUF_SIZE, &out_shm);
+	if (ret) {
+		pr_err("shmbridge alloc failed for out msg in object release"
+				"with ret:%d\n", ret);
+		goto out;
+	}
+
+	ret = smcinvoke_release_tz_object(&in_shm, &out_shm,
+		tzhandle, file_data->context_type);
+
+	if (-EBUSY == ret) {
+		pr_debug("failed to release handle in sync adding to list\n");
+		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+		if (!entry) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		ret = 0;
+		entry->data.tzhandle = tzhandle;
+		entry->data.context_type = file_data->context_type;
+		mutex_lock(&object_postprocess_lock);
+		list_add_tail(&entry->list, &g_object_postprocess);
+		mutex_unlock(&object_postprocess_lock);
+		pr_debug("Object release list: added a handle:0x%lx\n", tzhandle);
+		__wakeup_postprocess_kthread(&smcinvoke[OBJECT_WORKER_THREAD]);
+	}
 
 out:
+	qtee_shmbridge_free_shm(&in_shm);
+	qtee_shmbridge_free_shm(&out_shm);
 	kfree(filp->private_data);
 	filp->private_data = NULL;
 
+	if (ret != 0)
+		pr_err ("Object release failed with ret %d\n", ret);
 	return ret;
-
 }
 
 int smcinvoke_release_from_kernel_client(int fd)