Skip to content

Commit 537b583

Browse files
Vudentzgregkh
authored andcommitted
Bluetooth: L2CAP: Fix regressions caused by reusing ident
commit 761fb8e upstream. This attempt to fix regressions caused by reusing ident which apparently is not handled well on certain stacks causing the stack to not respond to requests, so instead of simple returning the first unallocated id this stores the last used tx_ident and then attempt to use the next until all available ids are exausted and then cycle starting over to 1. Link: https://bugzilla.kernel.org/show_bug.cgi?id=221120 Link: https://bugzilla.kernel.org/show_bug.cgi?id=221177 Fixes: 6c3ea15 ("Bluetooth: L2CAP: Fix not tracking outstanding TX ident") Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Tested-by: Christian Eggers <ceggers@arri.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 26e7139 commit 537b583

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

include/net/bluetooth/l2cap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ struct l2cap_conn {
658658
struct sk_buff *rx_skb;
659659
__u32 rx_len;
660660
struct ida tx_ida;
661+
__u8 tx_ident;
661662

662663
struct sk_buff_head pending_rx;
663664
struct work_struct pending_rx_work;

net/bluetooth/l2cap_core.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,16 +926,39 @@ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
926926

927927
static int l2cap_get_ident(struct l2cap_conn *conn)
928928
{
929+
u8 max;
930+
int ident;
931+
929932
/* LE link does not support tools like l2ping so use the full range */
930933
if (conn->hcon->type == LE_LINK)
931-
return ida_alloc_range(&conn->tx_ida, 1, 255, GFP_ATOMIC);
932-
934+
max = 255;
933935
/* Get next available identificator.
934936
* 1 - 128 are used by kernel.
935937
* 129 - 199 are reserved.
936938
* 200 - 254 are used by utilities like l2ping, etc.
937939
*/
938-
return ida_alloc_range(&conn->tx_ida, 1, 128, GFP_ATOMIC);
940+
else
941+
max = 128;
942+
943+
/* Allocate ident using min as last used + 1 (cyclic) */
944+
ident = ida_alloc_range(&conn->tx_ida, READ_ONCE(conn->tx_ident) + 1,
945+
max, GFP_ATOMIC);
946+
/* Force min 1 to start over */
947+
if (ident <= 0) {
948+
ident = ida_alloc_range(&conn->tx_ida, 1, max, GFP_ATOMIC);
949+
if (ident <= 0) {
950+
/* If all idents are in use, log an error, this is
951+
* extremely unlikely to happen and would indicate a bug
952+
* in the code that idents are not being freed properly.
953+
*/
954+
BT_ERR("Unable to allocate ident: %d", ident);
955+
return 0;
956+
}
957+
}
958+
959+
WRITE_ONCE(conn->tx_ident, ident);
960+
961+
return ident;
939962
}
940963

941964
static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb,

0 commit comments

Comments
 (0)