linux/net/sctp
Daniel Borkmann 1abd165ed7 net: sctp: fix NULL pointer dereference in socket destruction
While stress testing sctp sockets, I hit the following panic:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000020
IP: [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
PGD 7cead067 PUD 7ce76067 PMD 0
Oops: 0000 [#1] SMP
Modules linked in: sctp(F) libcrc32c(F) [...]
CPU: 7 PID: 2950 Comm: acc Tainted: GF            3.10.0-rc2+ #1
Hardware name: Dell Inc. PowerEdge T410/0H19HD, BIOS 1.6.3 02/01/2011
task: ffff88007ce0e0c0 ti: ffff88007b568000 task.ti: ffff88007b568000
RIP: 0010:[<ffffffffa0490c4e>]  [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
RSP: 0018:ffff88007b569e08  EFLAGS: 00010292
RAX: 0000000000000000 RBX: ffff88007db78a00 RCX: dead000000200200
RDX: ffffffffa049fdb0 RSI: ffff8800379baf38 RDI: 0000000000000000
RBP: ffff88007b569e18 R08: ffff88007c230da0 R09: 0000000000000001
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
R13: ffff880077990d00 R14: 0000000000000084 R15: ffff88007db78a00
FS:  00007fc18ab61700(0000) GS:ffff88007fc60000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000020 CR3: 000000007cf9d000 CR4: 00000000000007e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Stack:
 ffff88007b569e38 ffff88007db78a00 ffff88007b569e38 ffffffffa049fded
 ffffffff81abf0c0 ffff88007db78a00 ffff88007b569e58 ffffffff8145b60e
 0000000000000000 0000000000000000 ffff88007b569eb8 ffffffff814df36e
Call Trace:
 [<ffffffffa049fded>] sctp_destroy_sock+0x3d/0x80 [sctp]
 [<ffffffff8145b60e>] sk_common_release+0x1e/0xf0
 [<ffffffff814df36e>] inet_create+0x2ae/0x350
 [<ffffffff81455a6f>] __sock_create+0x11f/0x240
 [<ffffffff81455bf0>] sock_create+0x30/0x40
 [<ffffffff8145696c>] SyS_socket+0x4c/0xc0
 [<ffffffff815403be>] ? do_page_fault+0xe/0x10
 [<ffffffff8153cb32>] ? page_fault+0x22/0x30
 [<ffffffff81544e02>] system_call_fastpath+0x16/0x1b
Code: 0c c9 c3 66 2e 0f 1f 84 00 00 00 00 00 e8 fb fe ff ff c9 c3 66 0f
      1f 84 00 00 00 00 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 <48>
      8b 47 20 48 89 fb c6 47 1c 01 c6 40 12 07 e8 9e 68 01 00 48
RIP  [<ffffffffa0490c4e>] sctp_endpoint_free+0xe/0x40 [sctp]
 RSP <ffff88007b569e08>
CR2: 0000000000000020
---[ end trace e0d71ec1108c1dd9 ]---

I did not hit this with the lksctp-tools functional tests, but with a
small, multi-threaded test program, that heavily allocates, binds,
listens and waits in accept on sctp sockets, and then randomly kills
some of them (no need for an actual client in this case to hit this).
Then, again, allocating, binding, etc, and then killing child processes.

This panic then only occurs when ``echo 1 > /proc/sys/net/sctp/auth_enable''
is set. The cause for that is actually very simple: in sctp_endpoint_init()
we enter the path of sctp_auth_init_hmacs(). There, we try to allocate
our crypto transforms through crypto_alloc_hash(). In our scenario,
it then can happen that crypto_alloc_hash() fails with -EINTR from
crypto_larval_wait(), thus we bail out and release the socket via
sk_common_release(), sctp_destroy_sock() and hit the NULL pointer
dereference as soon as we try to access members in the endpoint during
sctp_endpoint_free(), since endpoint at that time is still NULL. Now,
if we have that case, we do not need to do any cleanup work and just
leave the destruction handler.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-06-11 02:49:05 -07:00
..
Kconfig net, sctp: remove CONFIG_EXPERIMENTAL 2013-02-13 13:57:27 -05:00
Makefile sctp: implement sctp association probing module 2010-04-30 22:41:09 -04:00
associola.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2013-05-01 14:08:52 -07:00
auth.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-02-08 18:02:14 -05:00
bind_addr.c net: sctp: sctp_bind_addr: remove dead code 2013-04-17 14:13:02 -04:00
chunk.c sctp: fix -ENOMEM result with invalid user space pointer in sendto() syscall 2012-11-28 11:11:17 -05:00
command.c [SCTP]: Remove sctp_add_cmd_sf wrapper bloat 2008-03-27 17:54:29 -07:00
debug.c sctp: remove completely unsed EMPTY state 2011-04-20 01:51:03 -07:00
endpointola.c net: sctp: minor: make sctp_ep_common's member 'dead' a bool 2013-04-15 14:11:37 -04:00
input.c hlist: drop the node parameter from iterators 2013-02-27 19:10:24 -08:00
inqueue.c net: sctp: sctp_inq: remove dead code 2013-04-17 14:13:02 -04:00
ipv6.c net: sctp: sctp_v6_get_dst: fix boolean test in dst cache 2013-02-13 13:42:34 -05:00
objcnt.c sctp: Make the proc files per network namespace. 2012-08-14 23:29:53 -07:00
output.c net: sctp: minor: remove dead code from sctp_packet 2013-04-22 16:25:21 -04:00
outqueue.c net: sctp: outqueue: simplify sctp_outq_uncork function 2013-04-17 14:13:02 -04:00
primitive.c sctp: Push struct net down to sctp_chunk_event_lookup 2012-08-14 23:30:37 -07:00
probe.c net: sctp: attribute printl with __printf for gcc fmt checks 2013-05-01 15:04:10 -04:00
proc.c sctp: Add buffer utilization fields to /proc/net/sctp/assocs 2013-04-16 16:43:34 -04:00
protocol.c net: sctp: remove cast for kmalloc/kzalloc return value 2013-03-18 14:16:00 +01:00
sm_make_chunk.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2013-02-21 17:40:58 -08:00
sm_sideeffect.c net: remove redundant check for timer pending state before del_timer 2013-02-04 13:26:49 -05:00
sm_statefuns.c sctp: Use correct sideffect command in duplicate cookie handling 2013-03-13 09:59:21 -04:00
sm_statetable.c sctp: Make sysctl tunables per net 2012-08-14 23:32:16 -07:00
socket.c net: sctp: fix NULL pointer dereference in socket destruction 2013-06-11 02:49:05 -07:00
ssnmap.c net: sctp: sctp_ssnmap: remove 'malloced' element from struct 2013-04-17 14:13:02 -04:00
sysctl.c SCTP: Free the per-net sysctl table on net exit. v2 2013-01-28 00:09:32 -05:00
transport.c net: sctp: sctp_transport: remove unused variable 2013-04-17 14:13:02 -04:00
tsnmap.c sctp: fix association hangs due to off-by-one errors in sctp_tsnmap_grow() 2013-02-28 15:34:26 -05:00
ulpevent.c netvm: prevent a stream-specific deadlock 2012-07-31 18:42:47 -07:00
ulpqueue.c net: sctp: sctp_ulpq: remove 'malloced' struct member 2013-04-17 14:13:02 -04:00