Message ID | tencent_E7941CEA8AEEA2CC0879BA6C2C2C956E2C0A@qq.com |
---|---|
State | New |
Headers | show |
Series | Bluetooth: hci_core: sync hci rx and cmd sync work | expand |
On Thu, 16 Jan 2025 10:31:03 -0500 Luiz Augusto von Dentz > On Thu, Jan 16, 2025 at 5:42 AM Hillf Danton <hdanton@sina.com> wrote: > > > > This does not work because conn can be freed before bumping refcnt up, > > and bumpup alone does not help l2cap_send_cmd() in case conn->hchan has been > > cleared in l2cap_conn_del(). > > Well then perhaps we can use hdev lock just to protect l2cap_data: > > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c > index 27b4c4a2ba1f..00ef61609d49 100644 > --- a/net/bluetooth/l2cap_core.c > +++ b/net/bluetooth/l2cap_core.c > @@ -7466,14 +7466,33 @@ static void l2cap_recv_reset(struct l2cap_conn *conn) > conn->rx_len = 0; > } > > +static struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c) > +{ > + BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref)); > + > + if (!kref_get_unless_zero(&c->ref)) > + return NULL; > + > + return c; > +} > + > void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) > { > - struct l2cap_conn *conn = hcon->l2cap_data; > + struct l2cap_conn *conn; > int len; > > + /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */ > + hci_dev_lock(hcon->hdev); > + > + conn = hcon->l2cap_data; > + > if (!conn) > conn = l2cap_conn_add(hcon); > > + conn = l2cap_conn_hold_unless_zero(conn); > + > + hci_dev_unlock(hcon->hdev); > + This does not work either because after releasing lock bumpup alone can not prevent conn->hchan from being cleared.
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f9e19f9cb5a3..88c8aa37eb64 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3798,7 +3798,9 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); /* Send to upper protocol */ + hci_dev_lock(hdev); l2cap_recv_acldata(conn, skb, flags); + hci_dev_unlock(hdev); return; } else { bt_dev_err(hdev, "ACL packet for unknown connection handle %d",