Skip to content
  • Vlad Yasevich's avatar
    net: sctp: cache auth_enable per endpoint · b14878cc
    Vlad Yasevich authored
    
    
    Currently, it is possible to create an SCTP socket, then switch
    auth_enable via sysctl setting to 1 and crash the system on connect:
    
    Oops[#1]:
    CPU: 0 PID: 0 Comm: swapper Not tainted 3.14.1-mipsgit-20140415 #1
    task: ffffffff8056ce80 ti: ffffffff8055c000 task.ti: ffffffff8055c000
    [...]
    Call Trace:
    [<ffffffff8043c4e8>] sctp_auth_asoc_set_default_hmac+0x68/0x80
    [<ffffffff8042b300>] sctp_process_init+0x5e0/0x8a4
    [<ffffffff8042188c>] sctp_sf_do_5_1B_init+0x234/0x34c
    [<ffffffff804228c8>] sctp_do_sm+0xb4/0x1e8
    [<ffffffff80425a08>] sctp_endpoint_bh_rcv+0x1c4/0x214
    [<ffffffff8043af68>] sctp_rcv+0x588/0x630
    [<ffffffff8043e8e8>] sctp6_rcv+0x10/0x24
    [<ffffffff803acb50>] ip6_input+0x2c0/0x440
    [<ffffffff8030fc00>] __netif_receive_skb_core+0x4a8/0x564
    [<ffffffff80310650>] process_backlog+0xb4/0x18c
    [<ffffffff80313cbc>] net_rx_action+0x12c/0x210
    [<ffffffff80034254>] __do_softirq+0x17c/0x2ac
    [<ffffffff800345e0>] irq_exit+0x54/0xb0
    [<ffffffff800075a4>] ret_from_irq+0x0/0x4
    [<ffffffff800090ec>] rm7k_wait_irqoff+0x24/0x48
    [<ffffffff8005e388>] cpu_startup_entry+0xc0/0x148
    [<ffffffff805a88b0>] start_kernel+0x37c/0x398
    Code: dd0900b8  000330f8  0126302d <dcc60000> 50c0fff1  0047182a  a48306a0
    03e00008  00000000
    ---[ end trace b530b0551467f2fd ]---
    Kernel panic - not syncing: Fatal exception in interrupt
    
    What happens while auth_enable=0 in that case is, that
    ep->auth_hmacs is initialized to NULL in sctp_auth_init_hmacs()
    when endpoint is being created.
    
    After that point, if an admin switches over to auth_enable=1,
    the machine can crash due to NULL pointer dereference during
    reception of an INIT chunk. When we enter sctp_process_init()
    via sctp_sf_do_5_1B_init() in order to respond to an INIT chunk,
    the INIT verification succeeds and while we walk and process
    all INIT params via sctp_process_param() we find that
    net->sctp.auth_enable is set, therefore do not fall through,
    but invoke sctp_auth_asoc_set_default_hmac() instead, and thus,
    dereference what we have set to NULL during endpoint
    initialization phase.
    
    The fix is to make auth_enable immutable by caching its value
    during endpoint initialization, so that its original value is
    being carried along until destruction. The bug seems to originate
    from the very first days.
    
    Fix in joint work with Daniel Borkmann.
    
    Reported-by: default avatarJoshua Kinard <kumba@gentoo.org>
    Signed-off-by: default avatarVlad Yasevich <vyasevic@redhat.com>
    Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
    Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
    Tested-by: default avatarJoshua Kinard <kumba@gentoo.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    b14878cc