mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Bluetooth: SCO: Fix data-race on sco_pi fields in sco_connect
sco_sock_connect() copies the destination address into sco_pi(sk)->dst
under lock_sock(), then releases the lock and calls sco_connect(),
which reads dst, src, setting, and codec without holding lock_sock() in
hci_get_route() and hci_connect_sco().
These fields may be modified concurrently by connect(), bind(), or
setsockopt() on the same socket, resulting in data-races reported by
KCSAN.
Fix this by snapshotting dst, src, setting, and codec under lock_sock()
at the start of sco_connect() before passing them to hci_get_route()
and hci_connect_sco().
BUG: KCSAN: data-race in memcmp+0x45/0xb0
race at unknown origin, with read to 0xffff88800e6b0dd0 of 1 bytes
by task 315 on cpu 0:
memcmp+0x45/0xb0
hci_connect_acl+0x1b7/0x6b0
hci_connect_sco+0x4d/0xb30
sco_sock_connect+0x27b/0xd60
__sys_connect_file+0xbd/0xe0
__sys_connect+0xe0/0x110
__x64_sys_connect+0x40/0x50
x64_sys_call+0xcad/0x1c60
do_syscall_64+0x133/0x590
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Fixes: 9a8ec9e8eb ("Bluetooth: SCO: Fix possible circular locking dependency on sco_connect_cfm")
Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
9ca7053d62
commit
4847c5bca2
|
|
@ -312,11 +312,21 @@ static int sco_connect(struct sock *sk)
|
|||
struct sco_conn *conn;
|
||||
struct hci_conn *hcon;
|
||||
struct hci_dev *hdev;
|
||||
bdaddr_t src, dst;
|
||||
struct bt_codec codec;
|
||||
__u16 setting;
|
||||
int err, type;
|
||||
|
||||
BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
|
||||
lock_sock(sk);
|
||||
bacpy(&src, &sco_pi(sk)->src);
|
||||
bacpy(&dst, &sco_pi(sk)->dst);
|
||||
setting = sco_pi(sk)->setting;
|
||||
codec = sco_pi(sk)->codec;
|
||||
release_sock(sk);
|
||||
|
||||
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
|
||||
BT_DBG("%pMR -> %pMR", &src, &dst);
|
||||
|
||||
hdev = hci_get_route(&dst, &src, BDADDR_BREDR);
|
||||
if (!hdev)
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
|
|
@ -327,7 +337,7 @@ static int sco_connect(struct sock *sk)
|
|||
else
|
||||
type = SCO_LINK;
|
||||
|
||||
switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
|
||||
switch (setting & SCO_AIRMODE_MASK) {
|
||||
case SCO_AIRMODE_TRANSP:
|
||||
if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
|
||||
err = -EOPNOTSUPP;
|
||||
|
|
@ -336,8 +346,8 @@ static int sco_connect(struct sock *sk)
|
|||
break;
|
||||
}
|
||||
|
||||
hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
|
||||
sco_pi(sk)->setting, &sco_pi(sk)->codec,
|
||||
hcon = hci_connect_sco(hdev, type, &dst,
|
||||
setting, &codec,
|
||||
READ_ONCE(sk->sk_sndtimeo));
|
||||
if (IS_ERR(hcon)) {
|
||||
err = PTR_ERR(hcon);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user