• Daniel Borkmann's avatar
    tls: fix NULL pointer dereference on poll · f6fadff3
    Daniel Borkmann authored
    While hacking on kTLS, I ran into the following panic from an
    unprivileged netserver / netperf TCP session:
    
      BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
      PGD 800000037f378067 P4D 800000037f378067 PUD 3c0e61067 PMD 0
      Oops: 0010 [#1] SMP KASAN PTI
      CPU: 1 PID: 2289 Comm: netserver Not tainted 4.17.0+ #139
      Hardware name: LENOVO 20FBCTO1WW/20FBCTO1WW, BIOS N1FET47W (1.21 ) 11/28/2016
      RIP: 0010:          (null)
      Code: Bad RIP value.
      RSP: 0018:ffff88036abcf740 EFLAGS: 00010246
      RAX: dffffc0000000000 RBX: ffff88036f5f6800 RCX: 1ffff1006debed26
      RDX: ffff88036abcf920 RSI: ffff8803cb1a4f00 RDI: ffff8803c258c280
      RBP: ffff8803c258c280 R08: ffff8803c258c280 R09: ffffed006f559d48
      R10: ffff88037aacea43 R11: ffffed006f559d49 R12: ffff8803c258c280
      R13: ffff8803cb1a4f20 R14: 00000000000000db R15: ffffffffc168a350
      FS:  00007f7e631f4700(0000) GS:ffff8803d1c80000(0000) knlGS:0000000000000000
      CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: ffffffffffffffd6 CR3: 00000003ccf64005 CR4: 00000000003606e0
      DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
      DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
      Call Trace:
       ? tls_sw_poll+0xa4/0x160 [tls]
       ? sock_poll+0x20a/0x680
       ? do_select+0x77b/0x11a0
       ? poll_schedule_timeout.constprop.12+0x130/0x130
       ? pick_link+0xb00/0xb00
       ? read_word_at_a_time+0x13/0x20
       ? vfs_poll+0x270/0x270
       ? deref_stack_reg+0xad/0xe0
       ? __read_once_size_nocheck.constprop.6+0x10/0x10
      [...]
    
    Debugging further, it turns out that calling into ctx->sk_poll() is
    invalid since sk_poll itself is NULL which was saved from the original
    TCP socket in order for tls_sw_poll() to invoke it.
    
    Looks like the recent conversion from poll to poll_mask callback started
    in 15252423 ("net: add support for ->poll_mask in proto_ops") missed
    to eventually convert kTLS, too: TCP's ->poll was converted over to the
    ->poll_mask in commit 2c7d3dac ("net/tcp: convert to ->poll_mask")
    and therefore kTLS wrongly saved the ->poll old one which is now NULL.
    
    Convert kTLS over to use ->poll_mask instead. Also instead of POLLIN |
    POLLRDNORM use the proper EPOLLIN | EPOLLRDNORM bits as the case in
    tcp_poll_mask() as well that is mangled here.
    
    Fixes: 2c7d3dac ("net/tcp: convert to ->poll_mask")
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: Dave Watson <davejwatson@fb.com>
    Tested-by: default avatarDave Watson <davejwatson@fb.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    f6fadff3
tls_main.c 16.3 KB