OSDN Git Service

GATT: Initiate L2CAP disconnect only when the channel is open
authorvenkata Jagadeesh <vjagad@codeaurora.org>
Thu, 26 Nov 2015 08:44:00 +0000 (14:14 +0530)
committerAndre Eisenbach <eisenbach@google.com>
Fri, 4 Mar 2016 21:52:03 +0000 (21:52 +0000)
Use case:
Crash found during L2CAP disconnect from faulty BLE APP.

Steps:
Run SNS testing.

Failure:
Crash during L2CAP disc.

Root cause:
Faulty BLE application triggering GATT disconnection
which internally triggering L2CAP disconnection without checking
proper state of channel.

Fix:
- Initiate L2CAP disconnect only when the channel is open
- Validate LCB during disconnection from upper layers

Change-Id: Ic9d065f095feba659c861828732647e968c20db8

stack/gatt/gatt_main.c
stack/l2cap/l2c_utils.c

index bcc552f..bda5b41 100644 (file)
@@ -230,7 +230,8 @@ BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb)
 {
     BOOLEAN             ret = FALSE;
     tGATT_CH_STATE      ch_state;
-    GATT_TRACE_DEBUG ("gatt_disconnect ");
+
+    GATT_TRACE_EVENT ("%s", __func__);
 
     if (p_tcb != NULL)
     {
@@ -252,12 +253,15 @@ BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb)
             }
             else
             {
-                ret = L2CA_DisconnectReq(p_tcb->att_lcid);
+                if ((ch_state == GATT_CH_OPEN) || (ch_state == GATT_CH_CFG))
+                    ret = L2CA_DisconnectReq(p_tcb->att_lcid);
+                else
+                    GATT_TRACE_DEBUG ("%s gatt_disconnect channel not opened", __func__);
             }
         }
         else
         {
-            GATT_TRACE_DEBUG ("gatt_disconnect already in closing state");
+            GATT_TRACE_DEBUG ("%s already in closing state", __func__);
         }
     }
 
index 2f801b2..73aeb00 100644 (file)
@@ -904,6 +904,12 @@ void l2cu_send_peer_disc_req (tL2C_CCB *p_ccb)
     BT_HDR  *p_buf, *p_buf2;
     UINT8   *p;
 
+    if ((!p_ccb) || (p_ccb->p_lcb == NULL))
+    {
+        L2CAP_TRACE_ERROR ("%s L2CAP - ccb or lcb invalid", __func__);
+        return;
+    }
+
     /* Create an identifier for this packet */
     p_ccb->p_lcb->id++;
     l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);