]> git.hungrycats.org Git - linux/commitdiff
net/bluetooth: avoid NULL pointer dereference when there is an error during setup zygo-3.2.20-zb64
authorZygo Blaxell <zblaxell@satsuki.furryterror.org>
Tue, 8 May 2012 01:00:10 +0000 (21:00 -0400)
committerZygo Blaxell <zblaxell@serenity.furryterror.org>
Mon, 18 Jun 2012 00:20:52 +0000 (20:20 -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
(cherry picked from commit 587acb9d3a3a89bf3d3b0ba31926cd6fff8a1d5f)

net/bluetooth/sco.c

index a324b009e34b7bc1b66a91ce9e3a5188169ec04c..66b676aeee48f8077491f936105b6d6425e36883 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