On 7/7/25 9:21 AM, Shuai Zhang wrote: > Dear all (Please don't top-post) It would probably help if you included the maintainers in the To/Cc fields, so that your email can actually reach them When using the b4 tool, you can simply run `b4 prep -c`. Please resend this patch and add these emails: Marcel Holtmann <marcel@xxxxxxxxxxxx> Johan Hedberg <johan.hedberg@xxxxxxxxx> Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx> "David S. Miller" <davem@xxxxxxxxxxxxx> Eric Dumazet <edumazet@xxxxxxxxxx> Jakub Kicinski <kuba@xxxxxxxxxx> Paolo Abeni <pabeni@xxxxxxxxxx> Simon Horman <horms@xxxxxxxxxx> linux-bluetooth@xxxxxxxxxxxxxxx netdev@xxxxxxxxxxxxxxx linux-kernel@xxxxxxxxxxxxxxx Konrad > > On 2025/6/27 11:02, Shuai Zhang wrote: >> When the DUT receives a remote L2CAP Connection Request during the Read >> Encryption Key Size procedure, if it fails to complete reading the >> Encryption Key Size while processing the request, it will respond with >> a Connection Response – Refused (security block), resulting in the >> disconnection of the remote device. >> >> Use HCI_CONN_ENC_KEY_READY to determine whether >> l2cap_connect_request is pending. >> >> When l2cap_connect occurs before the read_enc_key_size event, it will >> be pending because HCI_CONN_ENC_KEY_READY has not yet been set. >> The connection request will be processed once the read_enc_key_size >> event completes. >> >> Signed-off-by: Shuai Zhang <quic_shuaz@xxxxxxxxxxx> >> --- >> include/net/bluetooth/hci_core.h | 3 +++ >> include/net/bluetooth/l2cap.h | 10 +++++++++- >> net/bluetooth/hci_event.c | 16 ++++++++++++++++ >> net/bluetooth/l2cap_core.c | 30 ++++++++++++++++++++++++++++++ >> 4 files changed, 58 insertions(+), 1 deletion(-) >> >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h >> index b47c74080..db329abbf 100644 >> --- a/include/net/bluetooth/hci_core.h >> +++ b/include/net/bluetooth/hci_core.h >> @@ -767,6 +767,8 @@ struct hci_conn { >> >> struct bt_codec codec; >> >> + struct l2cap_pending_connect *pending_connect; >> + >> void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); >> void (*security_cfm_cb) (struct hci_conn *conn, u8 status); >> void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason); >> @@ -970,6 +972,7 @@ enum { >> HCI_CONN_CREATE_PA_SYNC, >> HCI_CONN_PA_SYNC, >> HCI_CONN_PA_SYNC_FAILED, >> + HCI_CONN_ENC_KEY_READY, >> }; >> >> static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) >> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h >> index 4bb0eaedd..b1ccd56bd 100644 >> --- a/include/net/bluetooth/l2cap.h >> +++ b/include/net/bluetooth/l2cap.h >> @@ -679,6 +679,13 @@ struct l2cap_user { >> void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user); >> }; >> >> +struct l2cap_pending_connect { >> + struct l2cap_conn *conn; >> + struct l2cap_cmd_hdr cmd; >> + u8 data[sizeof(struct l2cap_conn_req)]; >> + u8 rsp_code; >> +}; >> + >> #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 >> #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 >> #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 >> @@ -976,5 +983,6 @@ void l2cap_conn_put(struct l2cap_conn *conn); >> >> int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); >> void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); >> - >> +void l2cap_process_pending_connect(struct l2cap_conn *conn, >> + struct l2cap_cmd_hdr *cmd, u8 *data, u8 rsp_code); >> #endif /* __L2CAP_H */ >> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c >> index c4b87bfb4..6c992f83e 100644 >> --- a/net/bluetooth/hci_event.c >> +++ b/net/bluetooth/hci_event.c >> @@ -32,6 +32,7 @@ >> #include <net/bluetooth/bluetooth.h> >> #include <net/bluetooth/hci_core.h> >> #include <net/bluetooth/mgmt.h> >> +#include <net/bluetooth/l2cap.h> >> >> #include "hci_debugfs.h" >> #include "hci_codec.h" >> @@ -766,10 +767,23 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, >> /* Update the key encryption size with the connection one */ >> if (key_enc_size && *key_enc_size != conn->enc_key_size) >> *key_enc_size = conn->enc_key_size; >> + set_bit(HCI_CONN_ENC_KEY_READY, &conn->flags); >> } >> >> hci_encrypt_cfm(conn, status); >> >> + /*Defer l2cap_connect here if it's triggered before key size is read.*/ >> + if (conn->pending_connect) { >> + struct l2cap_pending_connect *pc = conn->pending_connect; >> + >> + conn->pending_connect = NULL; >> + >> + bt_dev_dbg(hdev, "Defer l2cap_connect"); >> + l2cap_process_pending_connect(pc->conn, &pc->cmd, pc->data, pc->rsp_code); >> + >> + kfree(pc); >> + } >> + >> done: >> hci_dev_unlock(hdev); >> >> @@ -3396,6 +3410,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data, >> if (!conn) >> goto unlock; >> >> + clear_bit(HCI_CONN_ENC_KEY_READY, &conn->flags); >> + >> if (ev->status) { >> mgmt_disconnect_failed(hdev, &conn->dst, conn->type, >> conn->dst_type, ev->status); >> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c >> index 40daa3827..c4cb60e65 100644 >> --- a/net/bluetooth/l2cap_core.c >> +++ b/net/bluetooth/l2cap_core.c >> @@ -3982,6 +3982,30 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, >> struct l2cap_chan *chan = NULL, *pchan = NULL; >> int result, status = L2CAP_CS_NO_INFO; >> >> + /* If encryption is requested, but the key size is not ready yet, >> + * we need to wait for the key size to be ready before we can >> + * proceed with the connection. We do this by deferring the >> + * connection request until the key size is ready. This is done >> + * by storing the connection request in the hcon->pending_connect >> + * field. The connection request will be retried when the key size >> + * is ready. >> + */ >> + if (test_bit(HCI_CONN_ENCRYPT, &conn->hcon->flags) && >> + !test_bit(HCI_CONN_ENC_KEY_READY, &conn->hcon->flags)) { >> + struct l2cap_pending_connect *pc; >> + >> + pc = kzalloc(sizeof(*pc), GFP_KERNEL); >> + if (!pc) >> + return; >> + pc->conn = conn; >> + memcpy(&pc->cmd, cmd, sizeof(*cmd)); >> + memcpy(pc->data, data, sizeof(struct l2cap_conn_req)); >> + pc->rsp_code = rsp_code; >> + BT_DBG("store request and retried when keysize is ready"); >> + conn->hcon->pending_connect = pc; >> + return; >> + } >> + >> u16 dcid = 0, scid = __le16_to_cpu(req->scid); >> __le16 psm = req->psm; >> >> @@ -4105,6 +4129,12 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, >> l2cap_chan_put(pchan); >> } >> >> +void l2cap_process_pending_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, >> + u8 *data, u8 rsp_code) >> +{ >> + l2cap_connect(conn, cmd, data, rsp_code); >> +} >> + >> static int l2cap_connect_req(struct l2cap_conn *conn, >> struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) >> { > > Is there any update? > > thanks, > Shuai >