diff mbox series

Bluetooth: add missing checks in state transitions

Message ID 20240209070443.3617790-1-iam@sung-woo.kim
State New
Headers show
Series Bluetooth: add missing checks in state transitions | expand

Commit Message

Sungwoo Kim Feb. 9, 2024, 7:04 a.m. UTC
When an l2cap channel receives L2CAP_CONN_RSP, it revives from BT_DISCONN
to BT_CONFIG or BT_CONNECTED.
It is very weird, violates the specification, and I cannot see any real
usecase for this.
Similar to this, the L2cap channel has six illegal state transitions:

1. BT_CONNECT2 -> BT_CONFIG by L2CAP_CONN_RSP
2. BT_CONNECT2 -> BT_CONNECTED by L2CAP_CONF_RSP
3. BT_CONNECT2 -> BT_DISCONN by L2CAP_CONF_RSP
4. BT_CONNECTED -> BT_CONFIG by L2CAP_CONN_RSP
5. BT_DISCONN -> BT_CONFIG by L2CAP_CONN_RSP
6. BT_DISCONN -> BT_CONNECTED by L2CAP_CONN_RSP

This patch fixes 2, 3, 5, and 6 by adding checks.
For 1 and 4, I will make an RFC for as it requires some refactoring.

The detaild logs are described in here:
https://lore.kernel.org/lkml/CAJNyHpKpDdps4=QHZ77zu4jfY-NNBcGUrw6UwjuBKfpuSuE__g@mail.gmail.com/

Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
---
 net/bluetooth/l2cap_core.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

Sungwoo Kim Feb. 19, 2024, 1:16 a.m. UTC | #1
Hello, could I ask for comments on this?

On Fri, Feb 9, 2024 at 2:06 AM Sungwoo Kim <iam@sung-woo.kim> wrote:
>
> When an l2cap channel receives L2CAP_CONN_RSP, it revives from BT_DISCONN
> to BT_CONFIG or BT_CONNECTED.
> It is very weird, violates the specification, and I cannot see any real
> usecase for this.
> Similar to this, the L2cap channel has six illegal state transitions:
>
> 1. BT_CONNECT2 -> BT_CONFIG by L2CAP_CONN_RSP
> 2. BT_CONNECT2 -> BT_CONNECTED by L2CAP_CONF_RSP
> 3. BT_CONNECT2 -> BT_DISCONN by L2CAP_CONF_RSP
> 4. BT_CONNECTED -> BT_CONFIG by L2CAP_CONN_RSP
> 5. BT_DISCONN -> BT_CONFIG by L2CAP_CONN_RSP
> 6. BT_DISCONN -> BT_CONNECTED by L2CAP_CONN_RSP
>
> This patch fixes 2, 3, 5, and 6 by adding checks.
> For 1 and 4, I will make an RFC for as it requires some refactoring.
>
> The detaild logs are described in here:
> https://lore.kernel.org/lkml/CAJNyHpKpDdps4=QHZ77zu4jfY-NNBcGUrw6UwjuBKfpuSuE__g@mail.gmail.com/
>
> Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
> ---
>  net/bluetooth/l2cap_core.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 60298975d..c5fa2b683 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -4339,6 +4339,14 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
>
>         l2cap_chan_lock(chan);
>
> +       switch (chan->state) {
> +       case BT_CLOSED:
> +       case BT_DISCONN:
> +               l2cap_chan_unlock(chan);
> +               l2cap_chan_put(chan);
> +               goto unlock;
> +       }
> +
>         switch (result) {
>         case L2CAP_CR_SUCCESS:
>                 if (__l2cap_get_chan_by_dcid(conn, dcid)) {
> @@ -4552,6 +4560,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
>         if (!chan)
>                 return 0;
>
> +       switch (chan->state) {
> +       case BT_CLOSED:
> +       case BT_CONNECT:
> +       case BT_CONNECT2:
> +       case BT_DISCONN:
> +               goto done;
> +       }
> +
>         switch (result) {
>         case L2CAP_CONF_SUCCESS:
>                 l2cap_conf_rfc_get(chan, rsp->data, len);
> --
> 2.25.1
>
diff mbox series

Patch

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 60298975d..c5fa2b683 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4339,6 +4339,14 @@  static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
 
 	l2cap_chan_lock(chan);
 
+	switch (chan->state) {
+	case BT_CLOSED:
+	case BT_DISCONN:
+		l2cap_chan_unlock(chan);
+		l2cap_chan_put(chan);
+		goto unlock;
+	}
+
 	switch (result) {
 	case L2CAP_CR_SUCCESS:
 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
@@ -4552,6 +4560,14 @@  static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 	if (!chan)
 		return 0;
 
+	switch (chan->state) {
+	case BT_CLOSED:
+	case BT_CONNECT:
+	case BT_CONNECT2:
+	case BT_DISCONN:
+		goto done;
+	}
+
 	switch (result) {
 	case L2CAP_CONF_SUCCESS:
 		l2cap_conf_rfc_get(chan, rsp->data, len);