Bluetooth: L2CAP: Fix not checking l2cap_chan security level

[ Upstream commit 7af8479d9eb4319b4ba7b47a8c4d2c55af1c31e1 ]

l2cap_check_enc_key_size shall check the security level of the
l2cap_chan rather than the hci_conn since for incoming connection
request that may be different as hci_conn may already been
encrypted using a different security level.

Fixes: 522e9ed157e3 ("Bluetooth: l2cap: Check encryption key size on incoming connection")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Luiz Augusto von Dentz 2025-05-07 15:00:30 -04:00 committed by Greg Kroah-Hartman
parent ca51db2316
commit 1e8b7e96f7

View File

@ -1411,7 +1411,8 @@ static void l2cap_request_info(struct l2cap_conn *conn)
sizeof(req), &req); sizeof(req), &req);
} }
static bool l2cap_check_enc_key_size(struct hci_conn *hcon) static bool l2cap_check_enc_key_size(struct hci_conn *hcon,
struct l2cap_chan *chan)
{ {
/* The minimum encryption key size needs to be enforced by the /* The minimum encryption key size needs to be enforced by the
* host stack before establishing any L2CAP connections. The * host stack before establishing any L2CAP connections. The
@ -1425,7 +1426,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
int min_key_size = hcon->hdev->min_enc_key_size; int min_key_size = hcon->hdev->min_enc_key_size;
/* On FIPS security level, key size must be 16 bytes */ /* On FIPS security level, key size must be 16 bytes */
if (hcon->sec_level == BT_SECURITY_FIPS) if (chan->sec_level == BT_SECURITY_FIPS)
min_key_size = 16; min_key_size = 16;
return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
@ -1453,7 +1454,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
!__l2cap_no_conn_pending(chan)) !__l2cap_no_conn_pending(chan))
return; return;
if (l2cap_check_enc_key_size(conn->hcon)) if (l2cap_check_enc_key_size(conn->hcon, chan))
l2cap_start_connection(chan); l2cap_start_connection(chan);
else else
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT); __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
@ -1528,7 +1529,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
continue; continue;
} }
if (l2cap_check_enc_key_size(conn->hcon)) if (l2cap_check_enc_key_size(conn->hcon, chan))
l2cap_start_connection(chan); l2cap_start_connection(chan);
else else
l2cap_chan_close(chan, ECONNREFUSED); l2cap_chan_close(chan, ECONNREFUSED);
@ -3957,7 +3958,7 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
/* Check if the ACL is secure enough (if not SDP) */ /* Check if the ACL is secure enough (if not SDP) */
if (psm != cpu_to_le16(L2CAP_PSM_SDP) && if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
(!hci_conn_check_link_mode(conn->hcon) || (!hci_conn_check_link_mode(conn->hcon) ||
!l2cap_check_enc_key_size(conn->hcon))) { !l2cap_check_enc_key_size(conn->hcon, pchan))) {
conn->disc_reason = HCI_ERROR_AUTH_FAILURE; conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
result = L2CAP_CR_SEC_BLOCK; result = L2CAP_CR_SEC_BLOCK;
goto response; goto response;
@ -7317,7 +7318,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
} }
if (chan->state == BT_CONNECT) { if (chan->state == BT_CONNECT) {
if (!status && l2cap_check_enc_key_size(hcon)) if (!status && l2cap_check_enc_key_size(hcon, chan))
l2cap_start_connection(chan); l2cap_start_connection(chan);
else else
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT); __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
@ -7327,7 +7328,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
struct l2cap_conn_rsp rsp; struct l2cap_conn_rsp rsp;
__u16 res, stat; __u16 res, stat;
if (!status && l2cap_check_enc_key_size(hcon)) { if (!status && l2cap_check_enc_key_size(hcon, chan)) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
res = L2CAP_CR_PEND; res = L2CAP_CR_PEND;
stat = L2CAP_CS_AUTHOR_PEND; stat = L2CAP_CS_AUTHOR_PEND;