From 013254162adc53b12866a9300fdf0a1f0bdb9a0e Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Wed, 25 Jul 2018 15:00:19 +0530 Subject: [PATCH] diag: Protect md_info structure while reallocation The possibility of md_info structure being accessed simultaneously by two threads is prevented by synchronizing while buffer reallocation for hdlc encoding. Extend the scope of protection to md_info till queueing the write to sdcard. CRs-Fixed: 2279473 Change-Id: I75ddb102adfc6c79f35ed69914c9140cb82894c9 Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_memorydevice.c | 10 +++++++--- drivers/char/diag/diagfwd_peripheral.c | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index aa45c2e7ec7b..fe86aebbe55c 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -164,11 +164,12 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) return -EIO; } pid = session_info->pid; - mutex_unlock(&driver->md_session_lock); ch = &diag_md[id]; - if (!ch || !ch->md_info_inited) + if (!ch || !ch->md_info_inited) { + mutex_unlock(&driver->md_session_lock); return -EINVAL; + } spin_lock_irqsave(&ch->lock, flags); for (i = 0; i < ch->num_tbl_entries && !found; i++) { @@ -184,8 +185,10 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) } spin_unlock_irqrestore(&ch->lock, flags); - if (found) + if (found) { + mutex_unlock(&driver->md_session_lock); return -ENOMEM; + } spin_lock_irqsave(&ch->lock, flags); for (i = 0; i < ch->num_tbl_entries && !found; i++) { @@ -198,6 +201,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) } } spin_unlock_irqrestore(&ch->lock, flags); + mutex_unlock(&driver->md_session_lock); if (!found) { pr_err_ratelimited("diag: Unable to find an empty space in table, please reduce logging rate, proc: %d\n", diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index bfdce051d405..d4c49ad40210 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -191,6 +191,7 @@ static int check_bufsize_for_encoding(struct diagfwd_buf_t *buf, uint32_t len) { int i, ctx = 0; uint32_t max_size = 0; + unsigned long flags; unsigned char *temp_buf = NULL; struct diag_md_info *ch = NULL; @@ -205,11 +206,16 @@ static int check_bufsize_for_encoding(struct diagfwd_buf_t *buf, uint32_t len) max_size = MAX_PERIPHERAL_HDLC_BUF_SZ; } + mutex_lock(&driver->md_session_lock); if (buf->len < max_size) { if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE) { ch = &diag_md[DIAG_LOCAL_PROC]; - for (i = 0; ch != NULL && - i < ch->num_tbl_entries; i++) { + if (!ch || !ch->md_info_inited) { + mutex_unlock(&driver->md_session_lock); + return -EINVAL; + } + spin_lock_irqsave(&ch->lock, flags); + for (i = 0; i < ch->num_tbl_entries; i++) { if (ch->tbl[i].buf == buf->data) { ctx = ch->tbl[i].ctx; ch->tbl[i].buf = NULL; @@ -222,18 +228,22 @@ static int check_bufsize_for_encoding(struct diagfwd_buf_t *buf, uint32_t len) break; } } + spin_unlock_irqrestore(&ch->lock, flags); } temp_buf = krealloc(buf->data, max_size + APF_DIAG_PADDING, GFP_KERNEL); - if (!temp_buf) + if (!temp_buf) { + mutex_unlock(&driver->md_session_lock); return -ENOMEM; + } DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Reallocated data buffer: %pK with size: %d\n", temp_buf, max_size); buf->data = temp_buf; buf->len = max_size; } + mutex_unlock(&driver->md_session_lock); } return buf->len;