drivers: soc: add size check

Add size check to ensure the payload fits inside the declared payload
size to prevent loss of data when copying.

References: CVE-2017-0451

CRs-Fixed: 2009224
Signed-off-by: Siena Richard <sienar@codeaurora.org>
Change-Id: I4275c626605272941143b54a7b8861b25f8e750a
diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c
index 85359d6..5d70c16 100644
--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c
+++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c
@@ -361,6 +361,9 @@
 	struct voice_svc_prvt *prtd;
 	struct voice_svc_write_msg *data = NULL;
 	uint32_t cmd;
+	struct voice_svc_register *register_data = NULL;
+	struct voice_svc_cmd_request *request_data = NULL;
+	uint32_t request_payload_size;
 
 	pr_debug("%s\n", __func__);
 
@@ -409,12 +412,19 @@
 		 */
 		if (count == (sizeof(struct voice_svc_write_msg) +
 			      sizeof(struct voice_svc_register))) {
-			ret = process_reg_cmd(
-			(struct voice_svc_register *)data->payload, prtd);
+			register_data =
+				(struct voice_svc_register *)data->payload;
+			if (register_data == NULL) {
+				pr_err("%s: register data is NULL", __func__);
+				ret = -EINVAL;
+				goto done;
+			}
+			ret = process_reg_cmd(register_data, prtd);
 			if (!ret)
 				ret = count;
 		} else {
-			pr_err("%s: invalid payload size\n", __func__);
+			pr_err("%s: invalid data payload size for register command\n",
+				__func__);
 			ret = -EINVAL;
 			goto done;
 		}
@@ -423,16 +433,37 @@
 		/*
 		 * Check that count reflects the expected size to ensure
 		 * sufficient memory was allocated. Since voice_svc_cmd_request
-		 * has a variable size, check the minimum value count must be.
+		 * has a variable size, check the minimum value count must be to
+		 * parse the message request then check the minimum size to hold
+		 * the payload of the message request.
 		 */
 		if (count >= (sizeof(struct voice_svc_write_msg) +
 			      sizeof(struct voice_svc_cmd_request))) {
-			ret = voice_svc_send_req(
-			(struct voice_svc_cmd_request *)data->payload, prtd);
-			if (!ret)
-				ret = count;
+			request_data =
+				(struct voice_svc_cmd_request *)data->payload;
+			if (request_data == NULL) {
+				pr_err("%s: request data is NULL", __func__);
+				ret = -EINVAL;
+				goto done;
+			}
+
+			request_payload_size = request_data->payload_size;
+
+			if (count >= (sizeof(struct voice_svc_write_msg) +
+				      sizeof(struct voice_svc_cmd_request) +
+				      request_payload_size)) {
+				ret = voice_svc_send_req(request_data, prtd);
+				if (!ret)
+					ret = count;
+			} else {
+				pr_err("%s: invalid request payload size\n",
+					__func__);
+				ret = -EINVAL;
+				goto done;
+			}
 		} else {
-			pr_err("%s: invalid payload size\n", __func__);
+			pr_err("%s: invalid data payload size for request command\n",
+				__func__);
 			ret = -EINVAL;
 			goto done;
 		}