Эх сурвалжийг харах

driver: eSE: Fix possible use after free

Shared variable is accessed without any mutual exclusion,
it may result into overwriting memory address and cause
invalid write access to buffer after free or invalid free.

Convert shared variable to local as it's usage was limited
with in API itself, it will avoid overwriting memory address
by another thread as all of them will have their own copy.

Change-Id: I36692313396f6c60e1be4479711feb14bb92ae4c
Signed-off-by: Gaurav Singhal <[email protected]>
Abhishek Dhumal 3 жил өмнө
parent
commit
92e090c560

+ 17 - 20
qti/ese_cold_reset.c

@@ -140,6 +140,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 {
 {
 	int ret;
 	int ret;
 	struct ese_ioctl_arg ioctl_arg;
 	struct ese_ioctl_arg ioctl_arg;
+	struct ese_cold_reset_arg *cold_reset_arg = NULL;
 
 
 	if (!arg) {
 	if (!arg) {
 		dev_err(nfc_dev->nfc_device, "arg is invalid\n");
 		dev_err(nfc_dev->nfc_device, "arg is invalid\n");
@@ -154,12 +155,11 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
-	nfc_dev->cold_reset.arg = kzalloc(sizeof(struct ese_cold_reset_arg),
-							GFP_KERNEL);
-	if (!nfc_dev->cold_reset.arg)
+	cold_reset_arg = kzalloc(sizeof(struct ese_cold_reset_arg), GFP_KERNEL);
+	if (!cold_reset_arg)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	ret = copy_struct_from_user(nfc_dev->cold_reset.arg,
+	ret = copy_struct_from_user(cold_reset_arg,
 				sizeof(struct ese_cold_reset_arg),
 				sizeof(struct ese_cold_reset_arg),
 				u64_to_user_ptr(ioctl_arg.buf),
 				u64_to_user_ptr(ioctl_arg.buf),
 				sizeof(struct ese_cold_reset_arg));
 				sizeof(struct ese_cold_reset_arg));
@@ -171,7 +171,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 		goto err;
 		goto err;
 	}
 	}
 
 
-	switch (nfc_dev->cold_reset.arg->sub_cmd) {
+	switch (cold_reset_arg->sub_cmd) {
 
 
 	case ESE_COLD_RESET_DO:
 	case ESE_COLD_RESET_DO:
 
 
@@ -180,11 +180,11 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 		 * source is same as the one which enabled protection.
 		 * source is same as the one which enabled protection.
 		 */
 		 */
 		if (nfc_dev->cold_reset.is_crp_en &&
 		if (nfc_dev->cold_reset.is_crp_en &&
-			(nfc_dev->cold_reset.arg->src !=
+			(cold_reset_arg->src !=
 				nfc_dev->cold_reset.last_src_ese_prot)) {
 				nfc_dev->cold_reset.last_src_ese_prot)) {
 			dev_err(nfc_dev->nfc_device,
 			dev_err(nfc_dev->nfc_device,
 				"cold reset from %d denied, protection is on\n",
 				"cold reset from %d denied, protection is on\n",
-						nfc_dev->cold_reset.arg->src);
+				cold_reset_arg->src);
 			ret = -EACCES;
 			ret = -EACCES;
 			goto err;
 			goto err;
 		}
 		}
@@ -207,7 +207,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 	case ESE_COLD_RESET_PROTECT_EN:
 	case ESE_COLD_RESET_PROTECT_EN:
 
 
 		if (nfc_dev->cold_reset.is_crp_en) {
 		if (nfc_dev->cold_reset.is_crp_en) {
-			if (nfc_dev->cold_reset.arg->src !=
+			if (cold_reset_arg->src !=
 				nfc_dev->cold_reset.last_src_ese_prot) {
 				nfc_dev->cold_reset.last_src_ese_prot) {
 				dev_err(nfc_dev->nfc_device,
 				dev_err(nfc_dev->nfc_device,
 					"ese protection enable denied\n");
 					"ese protection enable denied\n");
@@ -224,7 +224,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 	case ESE_COLD_RESET_PROTECT_DIS:
 	case ESE_COLD_RESET_PROTECT_DIS:
 
 
 		if (nfc_dev->cold_reset.is_crp_en &&
 		if (nfc_dev->cold_reset.is_crp_en &&
-			nfc_dev->cold_reset.arg->src !=
+			cold_reset_arg->src !=
 				nfc_dev->cold_reset.last_src_ese_prot) {
 				nfc_dev->cold_reset.last_src_ese_prot) {
 			pr_err("ese cold reset protection disable denied\n");
 			pr_err("ese cold reset protection disable denied\n");
 			ret = -EACCES;
 			ret = -EACCES;
@@ -243,8 +243,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 		nfc_dev->cold_reset.cmd_len = NCI_HDR_LEN +
 		nfc_dev->cold_reset.cmd_len = NCI_HDR_LEN +
 						COLD_RESET_PROT_CMD_PL_LEN;
 						COLD_RESET_PROT_CMD_PL_LEN;
 		nfc_dev->cold_reset.rsp_len = COLD_RESET_PROT_RSP_LEN;
 		nfc_dev->cold_reset.rsp_len = COLD_RESET_PROT_RSP_LEN;
-		if (nfc_dev->cold_reset.arg->sub_cmd ==
-						ESE_COLD_RESET_PROTECT_EN)
+		if (cold_reset_arg->sub_cmd == ESE_COLD_RESET_PROTECT_EN)
 			nfc_dev->cold_reset.cmd_buf[3] = 0x1;
 			nfc_dev->cold_reset.cmd_buf[3] = 0x1;
 		else
 		else
 			nfc_dev->cold_reset.cmd_buf[3] = 0x0;
 			nfc_dev->cold_reset.cmd_buf[3] = 0x0;
@@ -253,7 +252,7 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 
 
 	default:
 	default:
 		pr_err("%s invalid ese ioctl sub cmd %d\n", __func__,
 		pr_err("%s invalid ese ioctl sub cmd %d\n", __func__,
-					nfc_dev->cold_reset.arg->sub_cmd);
+					cold_reset_arg->sub_cmd);
 		ret = -ENOIOCTLCMD;
 		ret = -ENOIOCTLCMD;
 		goto err;
 		goto err;
 	}
 	}
@@ -314,23 +313,21 @@ int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
 		nfc_dev->nfc_disable_intr(nfc_dev);
 		nfc_dev->nfc_disable_intr(nfc_dev);
 	}
 	}
 
 
-	if (nfc_dev->cold_reset.arg->sub_cmd == ESE_COLD_RESET_PROTECT_EN) {
+	if (cold_reset_arg->sub_cmd == ESE_COLD_RESET_PROTECT_EN) {
 		nfc_dev->cold_reset.is_crp_en = true;
 		nfc_dev->cold_reset.is_crp_en = true;
-		nfc_dev->cold_reset.last_src_ese_prot =
-						nfc_dev->cold_reset.arg->src;
-	} else if (nfc_dev->cold_reset.arg->sub_cmd ==
-						ESE_COLD_RESET_PROTECT_DIS) {
+		nfc_dev->cold_reset.last_src_ese_prot = cold_reset_arg->src;
+	} else if (cold_reset_arg->sub_cmd == ESE_COLD_RESET_PROTECT_DIS) {
 		nfc_dev->cold_reset.is_crp_en = false;
 		nfc_dev->cold_reset.is_crp_en = false;
 		nfc_dev->cold_reset.last_src_ese_prot =
 		nfc_dev->cold_reset.last_src_ese_prot =
 						ESE_COLD_RESET_ORIGIN_NONE;
 						ESE_COLD_RESET_ORIGIN_NONE;
 	} else
 	} else
-		pr_debug("ese cmd is %d\n", nfc_dev->cold_reset.arg->sub_cmd);
+		pr_debug("ese cmd is %d\n", cold_reset_arg->sub_cmd);
 
 
 	ret = nfc_dev->cold_reset.status;
 	ret = nfc_dev->cold_reset.status;
 err:
 err:
 	kfree(nfc_dev->cold_reset.cmd_buf);
 	kfree(nfc_dev->cold_reset.cmd_buf);
-	kfree(nfc_dev->cold_reset.arg);
-	nfc_dev->cold_reset.arg = NULL;
+	kfree(cold_reset_arg);
+	cold_reset_arg = NULL;
 	nfc_dev->cold_reset.cmd_buf = NULL;
 	nfc_dev->cold_reset.cmd_buf = NULL;
 
 
 	return ret;
 	return ret;

+ 0 - 1
qti/ese_cold_reset.h

@@ -61,7 +61,6 @@ struct ese_ioctl_arg {
 struct cold_reset {
 struct cold_reset {
 	wait_queue_head_t read_wq;
 	wait_queue_head_t read_wq;
 	char *cmd_buf;
 	char *cmd_buf;
-	struct ese_cold_reset_arg *arg;
 	uint16_t cmd_len;
 	uint16_t cmd_len;
 	uint16_t rsp_len;
 	uint16_t rsp_len;
 	/* Source of last ese protection command */
 	/* Source of last ese protection command */