OSDN Git Service

Avoid double memory free and crash during LE discovery or disconnect
authorNitin Arora <niarora@codeaurora.org>
Thu, 28 Jan 2016 01:02:02 +0000 (17:02 -0800)
committerAndre Eisenbach <eisenbach@google.com>
Thu, 28 Jan 2016 22:23:52 +0000 (22:23 +0000)
1. Prevent GATT operations to proceed if queue is not empty

This change returns a FALSE from GATT enqueue operation, in case
there is already a GATT command enqueued. This simple change will
a. Prevent incorrect memory freeing of the currently queued command.
b. Prevent incorrect dequeing of the ongoing command and enqueing
another command which will never be executed.
c. Double free of memory causing segmentation fault

2. Prevent performing pending operations when link is down

This change prevents performing the execution of pending operations
when the link is disconnected. The pending operation in that case
is bound to fail thus freeing the memory pointed to by the p_q_cmd
which is cleaned up again by the discovery completion routine and
thus causing double free.

Bug:24178843
Change-Id: Ief2756f289a7db73d251ef7e247774dd3f7fc413

bta/gatt/bta_gattc_act.c
bta/gatt/bta_gattc_utils.c

index a9b9cd1..d62f8b6 100644 (file)
@@ -1064,8 +1064,10 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
     else if (p_q_cmd != NULL)
     {
         p_clcb->p_q_cmd = NULL;
-
-        bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
+        /* execute pending operation of link block still present */
+        if (l2cu_find_lcb_by_bd_addr(p_clcb->p_srcb->server_bda, BT_TRANSPORT_LE) != NULL) {
+            bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
+        }
         /* if the command executed requeued the cmd, we don't
          * want to free the underlying buffer that's being
          * referenced by p_clcb->p_q_cmd
index 539d2a7..a8c4ac3 100644 (file)
@@ -440,17 +440,15 @@ tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
 BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
 
- if (p_clcb->p_q_cmd == NULL)
- {
-     p_clcb->p_q_cmd = p_data;
- }
- else
- {
-     APPL_TRACE_ERROR("already has a pending command!!");
-     /* skip the callback now. ----- need to send callback ? */
- }
- return (p_clcb->p_q_cmd != NULL) ? TRUE : FALSE;
+    if (p_clcb->p_q_cmd == NULL)
+    {
+        p_clcb->p_q_cmd = p_data;
+        return TRUE;
+    }
 
+    APPL_TRACE_ERROR ("%s: already has a pending command!!", __func__);
+    /* skip the callback now. ----- need to send callback ? */
+    return FALSE;
 }
 
 /*******************************************************************************