Browse Source

audio-pkt: Fix out-of-bound memory access in audio_pkt_write

Add checks in the function call audio_pkt_write, whether the given buffer is
of sufficient length or not. If buffer size is less than required size, return
an error.

Change-Id: Ia4ef36f2465ef9d0f424e02c71ca9c9a578e1885
Signed-off-by: Sivanagaraju S <[email protected]>
Sivanagaraju S 2 years ago
parent
commit
bd49c54f57
1 changed files with 25 additions and 5 deletions
  1. 25 5
      ipc/audio-pkt.c

+ 25 - 5
ipc/audio-pkt.c

@@ -336,12 +336,19 @@ int audpkt_chk_and_update_physical_addr(struct audio_gpr_pkt *gpr_pkt)
 ssize_t audio_pkt_write(struct file *file, const char __user *buf,
 			size_t count, loff_t *ppos)
 {
-	struct audio_pkt_priv *ap_priv = file->private_data;
-	struct audio_pkt_device *audpkt_dev = ap_priv->ap_dev;
+	struct audio_pkt_priv *ap_priv = NULL;
+	struct audio_pkt_device *audpkt_dev = NULL;
 	struct gpr_hdr *audpkt_hdr = NULL;
 	void *kbuf;
 	int ret;
 
+	if (file == NULL || file->private_data == NULL || buf == NULL) {
+		AUDIO_PKT_ERR("invalid parameters\n");
+		return -EINVAL;
+	}
+	ap_priv = file->private_data;
+	audpkt_dev = ap_priv->ap_dev;
+
 	if (!audpkt_dev)  {
 		AUDIO_PKT_ERR("invalid device handle\n");
 		return -EINVAL;
@@ -355,6 +362,10 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf,
 		return -ENETRESET;
 	}
 	mutex_unlock(&ap_priv->lock);
+	if (count < sizeof(struct gpr_hdr)) {
+		AUDIO_PKT_ERR("Invalid count %zu\n", count);
+		return  -EINVAL;
+	}
 
 	kbuf = memdup_user(buf, count);
 	if (IS_ERR(kbuf))
@@ -370,10 +381,15 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf,
 	}
 
 	if (audpkt_hdr->opcode == APM_CMD_SHARED_MEM_MAP_REGIONS) {
+		if (count < sizeof(struct audio_gpr_pkt)) {
+			AUDIO_PKT_ERR("Invalid count %zu\n", count);
+			ret = -EINVAL;
+			goto free_kbuf;
+		}
 		ret = audpkt_chk_and_update_physical_addr((struct audio_gpr_pkt *) audpkt_hdr);
 		if (ret < 0) {
 			AUDIO_PKT_ERR("Update Physical Address Failed -%d\n", ret);
-		        return ret;
+			goto free_kbuf;
 		}
 	}
 
@@ -381,11 +397,15 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf,
 		ret = -ERESTARTSYS;
 		goto free_kbuf;
 	}
+	if (count < sizeof(struct gpr_pkt )) {
+		AUDIO_PKT_ERR("Invalid count %zu\n", count);
+		ret = -EINVAL;
+		mutex_unlock(&audpkt_dev->lock);
+		goto free_kbuf;
+	}
 	ret = gpr_send_pkt(ap_priv->adev,(struct gpr_pkt *) kbuf);
 	if (ret < 0) {
 		AUDIO_PKT_ERR("APR Send Packet Failed ret -%d\n", ret);
-		mutex_unlock(&audpkt_dev->lock);
-		return ret;
 	}
 	mutex_unlock(&audpkt_dev->lock);