Skip to content

Commit 2688899

Browse files
committed
Bluetooth: L2CAP: Fix data leaks when segment cannot be sent
Now that bt_l2cap_send_cb can fail the buffer state needs to be save and restored otherwise the data stored on it would be lost. Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 088526c commit 2688899

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

subsys/bluetooth/host/l2cap.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ static inline struct net_buf *l2cap_alloc_seg(struct net_buf *buf)
11721172
}
11731173

11741174
/* Fallback to using global connection tx pool */
1175-
return bt_l2cap_create_pdu(NULL, 0);
1175+
return bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT);
11761176
}
11771177

11781178
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
@@ -1255,10 +1255,11 @@ static void l2cap_chan_seg_sent(struct bt_conn *conn, void *user_data)
12551255
l2cap_chan_tx_resume(BT_L2CAP_LE_CHAN(chan));
12561256
}
12571257

1258-
static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
1259-
u16_t sdu_hdr_len)
1258+
static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch,
1259+
struct net_buf *buf, u16_t sdu_hdr_len)
12601260
{
12611261
struct net_buf *seg;
1262+
struct net_buf_simple_state state;
12621263
int len, err;
12631264

12641265
/* Wait for credits */
@@ -1267,18 +1268,15 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
12671268
return -EAGAIN;
12681269
}
12691270

1271+
/* Save state so it can be restored if we failed to send */
1272+
net_buf_simple_save(&buf->b, &state);
1273+
12701274
seg = l2cap_chan_create_seg(ch, buf, sdu_hdr_len);
12711275
if (!seg) {
12721276
k_sem_give(&ch->tx.credits);
12731277
return -EAGAIN;
12741278
}
12751279

1276-
/* Channel may have been disconnected while waiting for a buffer */
1277-
if (!ch->chan.conn) {
1278-
net_buf_unref(seg);
1279-
return -ECONNRESET;
1280-
}
1281-
12821280
BT_DBG("ch %p cid 0x%04x len %u credits %u", ch, ch->tx.cid,
12831281
seg->len, k_sem_count_get(&ch->tx.credits));
12841282

@@ -1300,6 +1298,8 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
13001298
k_sem_give(&ch->tx.credits);
13011299

13021300
if (err == -ENOBUFS) {
1301+
/* Restore state since segment could not be sent */
1302+
net_buf_simple_restore(&buf->b, &state);
13031303
return -EAGAIN;
13041304
}
13051305

0 commit comments

Comments
 (0)