If there is an error while connecting a SCO socket, the state machine
transitions directly to BT_DISCONN state in __sco_sock_close before some
pointers are set non-NULL. The socket shutdown code assumes that these
pointers are non-NULL in BT_DISCONN state, and dereferences NULL.
My Jabra CLIPPER headset triggers this bug on nearly every connection.
This patch checks that the pointers are non-NULL before attempting to
dereference them. It has kept my kernels NULL-dereference-free for
almost a month.
Example backtrace:
May 14 09:30:32 faye bluetoothd[14989]: audio/transport.c:media_request_reply() Request Acquire Reply Input/output error
May 14 09:30:32 faye bluetoothd[14989]: audio/transport.c:media_owner_free() Owner :1.19
May 14 09:30:32 faye bluetoothd[14989]: audio/transport.c:media_owner_remove() Owner :1.19 Request Acquire
May 14 09:30:32 faye kernel: [127767.124812] sco_sock_shutdown:769: sock
d75e3680, sk
f399da00
May 14 09:30:32 faye kernel: [127767.124829] sco_sock_clear_timer:94: sock
f399da00 state 1
May 14 09:30:32 faye kernel: [127767.124841] __sco_sock_close:364: sk
f399da00 state 1 socket
d75e3680
May 14 09:30:32 faye kernel: [127767.124853] sco_sock_set_timer:88: sock
f399da00 state 8 timeout 2000
May 14 09:30:32 faye kernel: [127767.124920] BUG: unable to handle kernel NULL pointer dereference at
00000008
if (sco_pi(sk)->conn) {
sk->sk_state = BT_DISCONN;
sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+ if (!sco_pi(sk)) break;
+ if (!sco_pi(sk)->conn) break;
+ if (!sco_pi(sk)->conn->hcon) break;
hci_conn_put(sco_pi(sk)->conn->hcon);
sco_pi(sk)->conn->hcon = NULL;
} else