public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted
@ 2025-06-27  3:02 Shuai Zhang
  2025-06-27  3:25 ` [v1] " bluez.test.bot
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Shuai Zhang @ 2025-06-27  3:02 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: quic_bt, Shuai Zhang

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@quicinc.com>
---
 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)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* RE: [v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted
  2025-06-27  3:02 [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted Shuai Zhang
@ 2025-06-27  3:25 ` bluez.test.bot
  2025-07-07  7:21 ` [PATCH v1] " Shuai Zhang
  2025-07-07 18:29 ` Luiz Augusto von Dentz
  2 siblings, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2025-06-27  3:25 UTC (permalink / raw)
  To: linux-bluetooth, quic_shuaz

[-- Attachment #1: Type: text/plain, Size: 2397 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=976441

---Test result---

Test Summary:
CheckPatch                    PENDING   0.35 seconds
GitLint                       PENDING   0.25 seconds
SubjectPrefix                 FAIL      0.32 seconds
BuildKernel                   PASS      26.35 seconds
CheckAllWarning               PASS      27.48 seconds
CheckSparse                   WARNING   32.98 seconds
BuildKernel32                 PASS      26.31 seconds
TestRunnerSetup               PASS      480.84 seconds
TestRunner_l2cap-tester       PASS      26.40 seconds
TestRunner_iso-tester         PASS      38.17 seconds
TestRunner_bnep-tester        PASS      6.42 seconds
TestRunner_mgmt-tester        PASS      139.41 seconds
TestRunner_rfcomm-tester      PASS      10.14 seconds
TestRunner_sco-tester         PASS      15.76 seconds
TestRunner_ioctl-tester       PASS      11.29 seconds
TestRunner_mesh-tester        FAIL      12.82 seconds
TestRunner_smp-tester         PASS      9.39 seconds
TestRunner_userchan-tester    PASS      6.94 seconds
IncrementalBuild              PENDING   0.61 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix
Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:
net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.772 seconds
Mesh - Send cancel - 2                               Timed out    2.004 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted
  2025-06-27  3:02 [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted Shuai Zhang
  2025-06-27  3:25 ` [v1] " bluez.test.bot
@ 2025-07-07  7:21 ` Shuai Zhang
  2025-07-29 13:49   ` Konrad Dybcio
  2025-07-07 18:29 ` Luiz Augusto von Dentz
  2 siblings, 1 reply; 5+ messages in thread
From: Shuai Zhang @ 2025-07-07  7:21 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: quic_bt, linux-arm-msm

Dear all

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@quicinc.com>
> ---
>  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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted
  2025-06-27  3:02 [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted Shuai Zhang
  2025-06-27  3:25 ` [v1] " bluez.test.bot
  2025-07-07  7:21 ` [PATCH v1] " Shuai Zhang
@ 2025-07-07 18:29 ` Luiz Augusto von Dentz
  2 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2025-07-07 18:29 UTC (permalink / raw)
  To: Shuai Zhang; +Cc: linux-bluetooth, quic_bt

Hi Shuai,

On Thu, Jun 26, 2025 at 11:04 PM Shuai Zhang <quic_shuaz@quicinc.com> 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@quicinc.com>
> ---
>  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;

We have rx_queue for deferring packets, we may need to extend that to
store requests to channels that require encryption.

>         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.
> +        */

This should have been resolved by
https://github.com/bluez/bluetooth-next/commit/c82b6357a5465a3222780ac5d3edcdfb02208cc3:

    /* If the key enc_size is already known, use it as conn->enc_key_size,
     * otherwise use hdev->min_enc_key_size so the likes of
     * l2cap_check_enc_key_size don't fail while waiting for
     * HCI_OP_READ_ENC_KEY_SIZE response.
     */
    if (key_enc_size && *key_enc_size)
        conn->enc_key_size = *key_enc_size;
    else
        conn->enc_key_size = hdev->min_enc_key_size;

This will use the hci_conn_key_enc_size, then on the command reply we do:

        /* Attempt to check if the key size is too small or if it has
         * been downgraded from the last time it was stored as part of
         * the link_key.
         */
        if (conn->enc_key_size < hdev->min_enc_key_size ||
            (key_enc_size && conn->enc_key_size < *key_enc_size)) {
            /* As slave role, the conn->state has been set to
             * BT_CONNECTED and l2cap conn req might not be received
             * yet, at this moment the l2cap layer almost does
             * nothing with the non-zero status.
             * So we also clear encrypt related bits, and then the
             * handler of l2cap conn req will get the right secure
             * state at a later time.
             */
            status = HCI_ERROR_AUTH_FAILURE;
            clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
            clear_bit(HCI_CONN_AES_CCM, &conn->flags);
        }

> +       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)
>  {
> --
> 2.34.1
>
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted
  2025-07-07  7:21 ` [PATCH v1] " Shuai Zhang
@ 2025-07-29 13:49   ` Konrad Dybcio
  0 siblings, 0 replies; 5+ messages in thread
From: Konrad Dybcio @ 2025-07-29 13:49 UTC (permalink / raw)
  To: Shuai Zhang, linux-bluetooth; +Cc: quic_bt, linux-arm-msm

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@holtmann.org>
Johan Hedberg <johan.hedberg@gmail.com>
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
"David S. Miller" <davem@davemloft.net>
Eric Dumazet <edumazet@google.com>
Jakub Kicinski <kuba@kernel.org>
Paolo Abeni <pabeni@redhat.com>
Simon Horman <horms@kernel.org>
linux-bluetooth@vger.kernel.org
netdev@vger.kernel.org
linux-kernel@vger.kernel.org

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@quicinc.com>
>> ---
>>  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
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-07-29 13:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-27  3:02 [PATCH v1] net: bluetooth: add callback to exe l2cap when read_security uncompleted Shuai Zhang
2025-06-27  3:25 ` [v1] " bluez.test.bot
2025-07-07  7:21 ` [PATCH v1] " Shuai Zhang
2025-07-29 13:49   ` Konrad Dybcio
2025-07-07 18:29 ` Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox