• Daniel Borkmann's avatar
    tls: fix use-after-free in tls_push_record · 5e8a5c30
    Daniel Borkmann authored
    [ Upstream commit a447da7d ]
    
    syzkaller managed to trigger a use-after-free in tls like the
    following:
    
      BUG: KASAN: use-after-free in tls_push_record.constprop.15+0x6a2/0x810 [tls]
      Write of size 1 at addr ffff88037aa08000 by task a.out/2317
    
      CPU: 3 PID: 2317 Comm: a.out Not tainted 4.17.0+ #144
      Hardware name: LENOVO 20FBCTO1WW/20FBCTO1WW, BIOS N1FET47W (1.21 ) 11/28/2016
      Call Trace:
       dump_stack+0x71/0xab
       print_address_description+0x6a/0x280
       kasan_report+0x258/0x380
       ? tls_push_record.constprop.15+0x6a2/0x810 [tls]
       tls_push_record.constprop.15+0x6a2/0x810 [tls]
       tls_sw_push_pending_record+0x2e/0x40 [tls]
       tls_sk_proto_close+0x3fe/0x710 [tls]
       ? tcp_check_oom+0x4c0/0x4c0
       ? tls_write_space+0x260/0x260 [tls]
       ? kmem_cache_free+0x88/0x1f0
       inet_release+0xd6/0x1b0
       __sock_release+0xc0/0x240
       sock_close+0x11/0x20
       __fput+0x22d/0x660
       task_work_run+0x114/0x1a0
       do_exit+0x71a/0x2780
       ? mm_update_next_owner+0x650/0x650
       ? handle_mm_fault+0x2f5/0x5f0
       ? __do_page_fault+0x44f/0xa50
       ? mm_fault_error+0x2d0/0x2d0
       do_group_exit+0xde/0x300
       __x64_sys_exit_group+0x3a/0x50
       do_syscall_64+0x9a/0x300
       ? page_fault+0x8/0x30
       entry_SYSCALL_64_after_hwframe+0x44/0xa9
    
    This happened through fault injection where aead_req allocation in
    tls_do_encryption() eventually failed and we returned -ENOMEM from
    the function. Turns out that the use-after-free is triggered from
    tls_sw_sendmsg() in the second tls_push_record(). The error then
    triggers a jump to waiting for memory in sk_stream_wait_memory()
    resp. returning immediately in case of MSG_DONTWAIT. What follows is
    the trim_both_sgl(sk, orig_size), which drops elements from the sg
    list added via tls_sw_sendmsg(). Now the use-after-free gets triggered
    when the socket is being closed, where tls_sk_proto_close() callback
    is invoked. The tls_complete_pending_work() will figure that there's
    a pending closed tls record to be flushed and thus calls into the
    tls_push_pending_closed_record() from there. ctx->push_pending_record()
    is called from the latter, which is the tls_sw_push_pending_record()
    from sw path. This again calls into tls_push_record(). And here the
    tls_fill_prepend() will panic since the buffer address has been freed
    earlier via trim_both_sgl(). One way to fix it is to move the aead
    request allocation out of tls_do_encryption() early into tls_push_record().
    This means we don't prep the tls header and advance state to the
    TLS_PENDING_CLOSED_RECORD before allocation which could potentially
    fail happened. That fixes the issue on my side.
    
    Fixes: 3c4d7559 ("tls: kernel TLS support")
    Reported-by: syzbot+5c74af81c547738e1684@syzkaller.appspotmail.com
    Reported-by: syzbot+709f2810a6a05f11d4d3@syzkaller.appspotmail.com
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Acked-by: default avatarDave Watson <davejwatson@fb.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    5e8a5c30
Name
Last commit
Last update
..
6lowpan Loading commit data...
802 Loading commit data...
8021q Loading commit data...
9p Loading commit data...
appletalk Loading commit data...
atm Loading commit data...
ax25 Loading commit data...
batman-adv Loading commit data...
bluetooth Loading commit data...
bpf Loading commit data...
bridge Loading commit data...
caif Loading commit data...
can Loading commit data...
ceph Loading commit data...
core Loading commit data...
dcb Loading commit data...
dccp Loading commit data...
decnet Loading commit data...
dns_resolver Loading commit data...
dsa Loading commit data...
ethernet Loading commit data...
hsr Loading commit data...
ieee802154 Loading commit data...
ife Loading commit data...
ipv4 Loading commit data...
ipv6 Loading commit data...
ipx Loading commit data...
iucv Loading commit data...
kcm Loading commit data...
key Loading commit data...
l2tp Loading commit data...
l3mdev Loading commit data...
lapb Loading commit data...
llc Loading commit data...
mac80211 Loading commit data...
mac802154 Loading commit data...
mpls Loading commit data...
ncsi Loading commit data...
netfilter Loading commit data...
netlabel Loading commit data...
netlink Loading commit data...
netrom Loading commit data...
nfc Loading commit data...
nsh Loading commit data...
openvswitch Loading commit data...
packet Loading commit data...
phonet Loading commit data...
psample Loading commit data...
qrtr Loading commit data...
rds Loading commit data...
rfkill Loading commit data...
rose Loading commit data...
rxrpc Loading commit data...
sched Loading commit data...
sctp Loading commit data...
smc Loading commit data...
strparser Loading commit data...
sunrpc Loading commit data...
switchdev Loading commit data...
tipc Loading commit data...
tls Loading commit data...
unix Loading commit data...
vmw_vsock Loading commit data...
wimax Loading commit data...
wireless Loading commit data...
x25 Loading commit data...
xfrm Loading commit data...
Kconfig Loading commit data...
Makefile Loading commit data...
compat.c Loading commit data...
socket.c Loading commit data...
sysctl_net.c Loading commit data...