]> git.hungrycats.org Git - linux/commitdiff
net/bluetooth: avoid NULL pointer dereference when there is an error during setup zygo-3.3.8-zb5s
authorZygo Blaxell <zblaxell@satsuki.furryterror.org>
Tue, 8 May 2012 01:00:10 +0000 (21:00 -0400)
committerZygo Blaxell <zblaxell@satsuki.furryterror.org>
Fri, 8 Jun 2012 01:02:36 +0000 (21:02 -0400)
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

net/bluetooth/sco.c

index 8bf26d1bc5c181e25641622d980c0f812a6780e0..8a4cf6d1dbec2bf547d410c3001bea23f9bdcbd4 100644 (file)
@@ -373,6 +373,9 @@ static void __sco_sock_close(struct sock *sk)
                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