diag: Add safeguards to prevent Integer Underflow and Memory Leak
At certain areas in the Diag driver, Integer overflow can occur.
Also, there is a possible memory leak in when a user space
program makes a ioctl call. This change fixes these issues.
Change-Id: I37e2b2d1f02983011a1db5f163354af4090f76f0
CRs-Fixed: 416995
CRs-Fixed: 416758
CRs-Fixed: 416953
Signed-off-by: Ravi Aravamudhan <aravamud@codeaurora.org>
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 2bc0de3..36292b9 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -385,6 +385,10 @@
/* remove UID from user space pkt before sending to peripheral */
buf = buf + 4;
+ if (len < 4) {
+ pr_err("diag: dci: integer underflow\n");
+ return -EIO;
+ }
len = len - 4;
mutex_lock(&driver->dci_mutex);
/* prepare DCI packet */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 2024cf4..13e52df 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -691,8 +691,10 @@
return -ENOMEM;
}
if (copy_from_user(dci_params, (void *)ioarg,
- sizeof(struct diag_dci_client_tbl)))
+ sizeof(struct diag_dci_client_tbl))) {
+ kfree(dci_params);
return -EFAULT;
+ }
mutex_lock(&driver->dci_mutex);
if (!(driver->num_dci_client))
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++)
@@ -724,8 +726,8 @@
break;
}
}
- mutex_unlock(&driver->dci_mutex);
kfree(dci_params);
+ mutex_unlock(&driver->dci_mutex);
return driver->dci_client_id;
} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
success = -1;
@@ -1197,6 +1199,10 @@
if (pkt_type == USER_SPACE_DATA_TYPE) {
err = copy_from_user(driver->user_space_data, buf + 4,
payload_size);
+ if (err) {
+ pr_err("diag: copy failed for user space data\n");
+ return -EIO;
+ }
/* Check for proc_type */
remote_proc = diag_get_remote(*(int *)driver->user_space_data);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 4ec222b..7f4edd1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -611,13 +611,15 @@
int packet_type = 1, i, cmd_code;
unsigned char *temp = buf;
int data_type;
+ int mask_ret;
#if defined(CONFIG_DIAG_OVER_USB)
unsigned char *ptr;
#endif
/* Check if the command is a supported mask command */
- if (diag_process_apps_masks(buf, len) == 0)
- return 0;
+ mask_ret = diag_process_apps_masks(buf, len);
+ if (mask_ret <= 0)
+ return mask_ret;
/* Check for registered clients and forward packet to apropriate proc */
cmd_code = (int)(*(char *)buf);
@@ -991,10 +993,16 @@
ret = diag_hdlc_decode(&hdlc);
- if (ret)
+ if (hdlc.dest_idx < 3) {
+ pr_err("diag: Integer underflow in hdlc processing\n");
+ return;
+ }
+ if (ret) {
type = diag_process_apps_pkt(driver->hdlc_buf,
hdlc.dest_idx - 3);
- else if (driver->debug_flag) {
+ if (type < 0)
+ return;
+ } else if (driver->debug_flag) {
printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
" errors or partial packet received, packet"
" length = %d\n", len);