Commit ca1fd42e authored by Ruihan Li's avatar Ruihan Li Committed by Luiz Augusto von Dentz

Bluetooth: Fix potential double free caused by hci_conn_unlink

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: 06149746 ("Bluetooth: hci_conn: Add support for linking multiple hcon")
Signed-off-by: default avatarRuihan Li <lrh2000@pku.edu.cn>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Reported-by: syzbot+690b90b14f14f43f4688@syzkaller.appspotmail.com
Reported-by: default avatarLuiz Augusto von Dentz <luiz.dentz@gmail.com>
Reported-by: syzbot+8bb72f86fc823817bc5d@syzkaller.appspotmail.com
parent 9025944f
...@@ -1083,8 +1083,18 @@ static void hci_conn_unlink(struct hci_conn *conn) ...@@ -1083,8 +1083,18 @@ static void hci_conn_unlink(struct hci_conn *conn)
if (!conn->parent) { if (!conn->parent) {
struct hci_link *link, *t; struct hci_link *link, *t;
list_for_each_entry_safe(link, t, &conn->link_list, list) list_for_each_entry_safe(link, t, &conn->link_list, list) {
hci_conn_unlink(link->conn); 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; return;
} }
...@@ -1100,13 +1110,6 @@ static void hci_conn_unlink(struct hci_conn *conn) ...@@ -1100,13 +1110,6 @@ static void hci_conn_unlink(struct hci_conn *conn)
kfree(conn->link); kfree(conn->link);
conn->link = NULL; 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) int hci_conn_del(struct hci_conn *conn)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment