OSDN Git Service

diag: Protect md_info structure while reallocation
authorManoj Prabhu B <bmanoj@codeaurora.org>
Wed, 25 Jul 2018 09:30:19 +0000 (15:00 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Wed, 1 Aug 2018 06:12:42 +0000 (23:12 -0700)
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 <bmanoj@codeaurora.org>
drivers/char/diag/diag_memorydevice.c
drivers/char/diag/diagfwd_peripheral.c

index aa45c2e..fe86aeb 100644 (file)
@@ -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",
index bfdce05..d4c49ad 100644 (file)
@@ -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;