diag: Add checks before allocating and freeing memory
Diag driver uses memory pool for internal buffers. This patch adds
checks for freeing the buffer in a specific mode and while allocating
buffer in all modes.
Change-Id: Ib04f4d722c5cd27e5ef39a1ae65dc74bfe0d136e
Signed-off-by: Ravi Aravamudhan <aravamud@codeaurora.org>
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6e70062..2c85c3e 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -131,12 +131,8 @@
mutex_lock(&driver->diagchar_mutex);
if (buf_hdlc) {
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
- if (err) {
- /*Free the buffer right away if write failed */
+ if (err)
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
- }
buf_hdlc = NULL;
#ifdef DIAG_DEBUG
pr_debug("diag: Number of bytes written "
@@ -1866,10 +1862,6 @@
if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
- /*Free the buffer right away if write failed */
- if (driver->logging_mode == USB_MODE)
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1894,10 +1886,6 @@
(unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) {
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
- /*Free the buffer right away if write failed */
- if (driver->logging_mode == USB_MODE)
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1919,10 +1907,6 @@
if (pkt_type == DATA_TYPE_RESPONSE) {
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
- /*Free the buffer right away if write failed */
- if (driver->logging_mode == USB_MODE)
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 379dc4d..7108dc4 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -623,8 +623,16 @@
driver->write_ptr_svc->buf = buf;
err = usb_diag_write(driver->legacy_ch,
driver->write_ptr_svc);
- } else
- err = -1;
+ /* Free the buffer if write failed */
+ if (err) {
+ diagmem_free(driver,
+ (unsigned char *)driver->
+ write_ptr_svc,
+ POOL_TYPE_WRITE_STRUCT);
+ }
+ } else {
+ err = -ENOMEM;
+ }
} else if ((data_type >= MODEM_DATA) &&
(data_type <= WCNSS_DATA)) {
write_ptr->buf = buf;
@@ -1591,6 +1599,9 @@
}
#endif
if (!found_it) {
+ if (driver->logging_mode != USB_MODE)
+ pr_debug("diag: freeing buffer when not in usb mode\n");
+
diagmem_free(driver, (unsigned char *)buf,
POOL_TYPE_HDLC);
diagmem_free(driver, (unsigned char *)diag_write_ptr,
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index a6ef3ca..ff1f6f2 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -31,7 +31,8 @@
if (pool_type == POOL_TYPE_COPY) {
if (driver->diagpool) {
mutex_lock(&driver->diagmem_mutex);
- if (driver->count < driver->poolsize) {
+ if ((driver->count < driver->poolsize) &&
+ (size <= driver->itemsize)) {
atomic_add(1, (atomic_t *)&driver->count);
buf = mempool_alloc(driver->diagpool,
GFP_ATOMIC);
@@ -40,7 +41,8 @@
}
} else if (pool_type == POOL_TYPE_HDLC) {
if (driver->diag_hdlc_pool) {
- if (driver->count_hdlc_pool < driver->poolsize_hdlc) {
+ if ((driver->count_hdlc_pool < driver->poolsize_hdlc) &&
+ (size <= driver->itemsize_hdlc)) {
atomic_add(1,
(atomic_t *)&driver->count_hdlc_pool);
buf = mempool_alloc(driver->diag_hdlc_pool,
@@ -49,7 +51,8 @@
}
} else if (pool_type == POOL_TYPE_USER) {
if (driver->diag_user_pool) {
- if (driver->count_user_pool < driver->poolsize_user) {
+ if ((driver->count_user_pool < driver->poolsize_user) &&
+ (size <= driver->itemsize_user)) {
atomic_add(1,
(atomic_t *)&driver->count_user_pool);
buf = mempool_alloc(driver->diag_user_pool,
@@ -58,8 +61,9 @@
}
} else if (pool_type == POOL_TYPE_WRITE_STRUCT) {
if (driver->diag_write_struct_pool) {
- if (driver->count_write_struct_pool <
- driver->poolsize_write_struct) {
+ if ((driver->count_write_struct_pool <
+ driver->poolsize_write_struct) &&
+ (size <= driver->itemsize_write_struct)) {
atomic_add(1,
(atomic_t *)&driver->count_write_struct_pool);
buf = mempool_alloc(
@@ -71,8 +75,9 @@
pool_type == POOL_TYPE_HSIC_2) {
index = pool_type - POOL_TYPE_HSIC;
if (diag_hsic[index].diag_hsic_pool) {
- if (diag_hsic[index].count_hsic_pool <
- diag_hsic[index].poolsize_hsic) {
+ if ((diag_hsic[index].count_hsic_pool <
+ diag_hsic[index].poolsize_hsic) &&
+ (size <= diag_hsic[index].itemsize_hsic)) {
atomic_add(1, (atomic_t *)
&diag_hsic[index].count_hsic_pool);
buf = mempool_alloc(
@@ -85,7 +90,8 @@
index = pool_type - POOL_TYPE_HSIC_WRITE;
if (diag_hsic[index].diag_hsic_write_pool) {
if (diag_hsic[index].count_hsic_write_pool <
- diag_hsic[index].poolsize_hsic_write) {
+ diag_hsic[index].poolsize_hsic_write &&
+ (size <= diag_hsic[index].itemsize_hsic_write)) {
atomic_add(1, (atomic_t *)
&diag_hsic[index].
count_hsic_write_pool);