]>
Commit | Line | Data |
---|---|---|
7a674766 GKH |
1 | From 4d0a2dfeefdac1692425ba99023b7f0107b80b10 Mon Sep 17 00:00:00 2001 |
2 | From: Daniel Borkmann <dborkman@redhat.com> | |
3 | Date: Thu, 6 Jun 2013 15:53:47 +0200 | |
4 | Subject: net: sctp: fix NULL pointer dereference in socket destruction | |
5 | ||
6 | From: Daniel Borkmann <dborkman@redhat.com> | |
7 | ||
8 | [ Upstream commit 1abd165ed757db1afdefaac0a4bc8a70f97d258c ] | |
9 | ||
10 | While stress testing sctp sockets, I hit the following panic: | |
11 | ||
12 | BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 | |
13 | IP: [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp] | |
14 | PGD 7cead067 PUD 7ce76067 PMD 0 | |
15 | Oops: 0000 [#1] SMP | |
16 | Modules linked in: sctp(F) libcrc32c(F) [...] | |
17 | CPU: 7 PID: 2950 Comm: acc Tainted: GF 3.10.0-rc2+ #1 | |
18 | Hardware name: Dell Inc. PowerEdge T410/0H19HD, BIOS 1.6.3 02/01/2011 | |
19 | task: ffff88007ce0e0c0 ti: ffff88007b568000 task.ti: ffff88007b568000 | |
20 | RIP: 0010:[<ffffffffa0490c4e>] [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp] | |
21 | RSP: 0018:ffff88007b569e08 EFLAGS: 00010292 | |
22 | RAX: 0000000000000000 RBX: ffff88007db78a00 RCX: dead000000200200 | |
23 | RDX: ffffffffa049fdb0 RSI: ffff8800379baf38 RDI: 0000000000000000 | |
24 | RBP: ffff88007b569e18 R08: ffff88007c230da0 R09: 0000000000000001 | |
25 | R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 | |
26 | R13: ffff880077990d00 R14: 0000000000000084 R15: ffff88007db78a00 | |
27 | FS: 00007fc18ab61700(0000) GS:ffff88007fc60000(0000) knlGS:0000000000000000 | |
28 | CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b | |
29 | CR2: 0000000000000020 CR3: 000000007cf9d000 CR4: 00000000000007e0 | |
30 | DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 | |
31 | DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 | |
32 | Stack: | |
33 | ffff88007b569e38 ffff88007db78a00 ffff88007b569e38 ffffffffa049fded | |
34 | ffffffff81abf0c0 ffff88007db78a00 ffff88007b569e58 ffffffff8145b60e | |
35 | 0000000000000000 0000000000000000 ffff88007b569eb8 ffffffff814df36e | |
36 | Call Trace: | |
37 | [<ffffffffa049fded>] sctp_destroy_sock+0x3d/0x80 [sctp] | |
38 | [<ffffffff8145b60e>] sk_common_release+0x1e/0xf0 | |
39 | [<ffffffff814df36e>] inet_create+0x2ae/0x350 | |
40 | [<ffffffff81455a6f>] __sock_create+0x11f/0x240 | |
41 | [<ffffffff81455bf0>] sock_create+0x30/0x40 | |
42 | [<ffffffff8145696c>] SyS_socket+0x4c/0xc0 | |
43 | [<ffffffff815403be>] ? do_page_fault+0xe/0x10 | |
44 | [<ffffffff8153cb32>] ? page_fault+0x22/0x30 | |
45 | [<ffffffff81544e02>] system_call_fastpath+0x16/0x1b | |
46 | Code: 0c c9 c3 66 2e 0f 1f 84 00 00 00 00 00 e8 fb fe ff ff c9 c3 66 0f | |
47 | 1f 84 00 00 00 00 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 <48> | |
48 | 8b 47 20 48 89 fb c6 47 1c 01 c6 40 12 07 e8 9e 68 01 00 48 | |
49 | RIP [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp] | |
50 | RSP <ffff88007b569e08> | |
51 | CR2: 0000000000000020 | |
52 | ---[ end trace e0d71ec1108c1dd9 ]--- | |
53 | ||
54 | I did not hit this with the lksctp-tools functional tests, but with a | |
55 | small, multi-threaded test program, that heavily allocates, binds, | |
56 | listens and waits in accept on sctp sockets, and then randomly kills | |
57 | some of them (no need for an actual client in this case to hit this). | |
58 | Then, again, allocating, binding, etc, and then killing child processes. | |
59 | ||
60 | This panic then only occurs when ``echo 1 > /proc/sys/net/sctp/auth_enable'' | |
61 | is set. The cause for that is actually very simple: in sctp_endpoint_init() | |
62 | we enter the path of sctp_auth_init_hmacs(). There, we try to allocate | |
63 | our crypto transforms through crypto_alloc_hash(). In our scenario, | |
64 | it then can happen that crypto_alloc_hash() fails with -EINTR from | |
65 | crypto_larval_wait(), thus we bail out and release the socket via | |
66 | sk_common_release(), sctp_destroy_sock() and hit the NULL pointer | |
67 | dereference as soon as we try to access members in the endpoint during | |
68 | sctp_endpoint_free(), since endpoint at that time is still NULL. Now, | |
69 | if we have that case, we do not need to do any cleanup work and just | |
70 | leave the destruction handler. | |
71 | ||
72 | Signed-off-by: Daniel Borkmann <dborkman@redhat.com> | |
73 | Acked-by: Neil Horman <nhorman@tuxdriver.com> | |
74 | Acked-by: Vlad Yasevich <vyasevich@gmail.com> | |
75 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
76 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
77 | --- | |
78 | net/sctp/socket.c | 6 ++++++ | |
79 | 1 file changed, 6 insertions(+) | |
80 | ||
81 | --- a/net/sctp/socket.c | |
82 | +++ b/net/sctp/socket.c | |
83 | @@ -3929,6 +3929,12 @@ SCTP_STATIC void sctp_destroy_sock(struc | |
84 | ||
85 | /* Release our hold on the endpoint. */ | |
86 | sp = sctp_sk(sk); | |
87 | + /* This could happen during socket init, thus we bail out | |
88 | + * early, since the rest of the below is not setup either. | |
89 | + */ | |
90 | + if (sp->ep == NULL) | |
91 | + return; | |
92 | + | |
93 | if (sp->do_auto_asconf) { | |
94 | sp->do_auto_asconf = 0; | |
95 | list_del(&sp->auto_asconf_list); |