Message ID | 20230502212527.1662896-1-luiz.dentz@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | [v3,1/4] Bluetooth: Fix potential double free caused by hci_conn_unlink | expand |
Hi Luiz, On Tue, 2 May 2023 14:25:24 -0700, Luiz Augusto von Dentz wrote: > From: Ruihan Li <lrh2000@pku.edu.cn> > > The hci_conn_unlink function is being called by hci_conn_del, which > means it should not call hci_conn_del with the input parameter conn > again. If it does, conn may have already been released when > hci_conn_unlink returns, leading to potential UAF and double-free > issues. > > This patch resolves the problem by modifying hci_conn_unlink to release > only conn's child links when necessary, but never release conn itself. > > Reported-by: syzbot+690b90b14f14f43f4688@syzkaller.appspotmail.com > Closes: https://lore.kernel.org/linux-bluetooth/000000000000484a8205faafe216@google.com/ > Fixes: 06149746e720 ("Bluetooth: hci_conn: Add support for linking multiple hcon") > Signed-off-by: Ruihan Li <lrh2000@pku.edu.cn> > Reported-by: syzbot+690b90b14f14f43f4688@syzkaller.appspotmail.com > Reported-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com> > Reported-by: syzbot+8bb72f86fc823817bc5d@syzkaller.appspotmail.com I don't think these tags are properly inserted in commit messages, are they? > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> > --- > net/bluetooth/hci_conn.c | 21 ++++++++++++--------- > 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c > index 640b951bf40a..70e1655a9df6 100644 > --- a/net/bluetooth/hci_conn.c > +++ b/net/bluetooth/hci_conn.c > @@ -1083,8 +1083,18 @@ static void hci_conn_unlink(struct hci_conn *conn) > if (!conn->parent) { > struct hci_link *link, *t; > > - list_for_each_entry_safe(link, t, &conn->link_list, list) > - hci_conn_unlink(link->conn); > + list_for_each_entry_safe(link, t, &conn->link_list, list) { > + struct hci_conn *child = link->conn; > + > + hci_conn_unlink(child); > + > + /* Due to race, SCO connection might be not established > + * yet at this point. Delete it now, otherwise it is > + * possible for it to be stuck and can't be deleted. > + */ > + if (child->handle == HCI_CONN_HANDLE_UNSET) > + hci_conn_del(child); > + } > > return; > } > @@ -1100,13 +1110,6 @@ static void hci_conn_unlink(struct hci_conn *conn) > > kfree(conn->link); > conn->link = NULL; > - > - /* Due to race, SCO connection might be not established > - * yet at this point. Delete it now, otherwise it is > - * possible for it to be stuck and can't be deleted. > - */ > - if (conn->handle == HCI_CONN_HANDLE_UNSET) > - hci_conn_del(conn); > } > > int hci_conn_del(struct hci_conn *conn) > -- > 2.40.0 Thanks, Ruihan Li
Hello: This series was applied to bluetooth/bluetooth-next.git (master) by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>: On Tue, 2 May 2023 14:25:24 -0700 you wrote: > From: Ruihan Li <lrh2000@pku.edu.cn> > > The hci_conn_unlink function is being called by hci_conn_del, which > means it should not call hci_conn_del with the input parameter conn > again. If it does, conn may have already been released when > hci_conn_unlink returns, leading to potential UAF and double-free > issues. > > [...] Here is the summary with links: - [v3,1/4] Bluetooth: Fix potential double free caused by hci_conn_unlink https://git.kernel.org/bluetooth/bluetooth-next/c/3214238e9dc7 - [v3,2/4] Bluetooth: Refcnt drop must be placed last in hci_conn_unlink https://git.kernel.org/bluetooth/bluetooth-next/c/38e9b45310de - [v3,3/4] Bluetooth: Fix UAF in hci_conn_hash_flush again https://git.kernel.org/bluetooth/bluetooth-next/c/29f883dcbfd0 - [v3,4/4] Bluetooth: Unlink CISes when LE disconnects in hci_conn_del https://git.kernel.org/bluetooth/bluetooth-next/c/e6e576ec4e72 You are awesome, thank you!
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 640b951bf40a..70e1655a9df6 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1083,8 +1083,18 @@ static void hci_conn_unlink(struct hci_conn *conn) if (!conn->parent) { struct hci_link *link, *t; - list_for_each_entry_safe(link, t, &conn->link_list, list) - hci_conn_unlink(link->conn); + list_for_each_entry_safe(link, t, &conn->link_list, list) { + struct hci_conn *child = link->conn; + + hci_conn_unlink(child); + + /* Due to race, SCO connection might be not established + * yet at this point. Delete it now, otherwise it is + * possible for it to be stuck and can't be deleted. + */ + if (child->handle == HCI_CONN_HANDLE_UNSET) + hci_conn_del(child); + } return; } @@ -1100,13 +1110,6 @@ static void hci_conn_unlink(struct hci_conn *conn) kfree(conn->link); conn->link = NULL; - - /* Due to race, SCO connection might be not established - * yet at this point. Delete it now, otherwise it is - * possible for it to be stuck and can't be deleted. - */ - if (conn->handle == HCI_CONN_HANDLE_UNSET) - hci_conn_del(conn); } int hci_conn_del(struct hci_conn *conn)