Message ID | 20240209070443.3617790-1-iam@sung-woo.kim |
---|---|
State | New |
Headers | show |
Series | Bluetooth: add missing checks in state transitions | expand |
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 --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);
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(+)