• Florian Westphal's avatar
    mptcp: fix panic on user pointer access · 50e741bb
    Florian Westphal authored
    Its not possible to call the kernel_(s|g)etsockopt functions here,
    the address points to user memory:
    
    General protection fault in user access. Non-canonical address?
    WARNING: CPU: 1 PID: 5352 at arch/x86/mm/extable.c:77 ex_handler_uaccess+0xba/0xe0 arch/x86/mm/extable.c:77
    Kernel panic - not syncing: panic_on_warn set ...
    [..]
    Call Trace:
     fixup_exception+0x9d/0xcd arch/x86/mm/extable.c:178
     general_protection+0x2d/0x40 arch/x86/entry/entry_64.S:1202
     do_ip_getsockopt+0x1f6/0x1860 net/ipv4/ip_sockglue.c:1323
     ip_getsockopt+0x87/0x1c0 net/ipv4/ip_sockglue.c:1561
     tcp_getsockopt net/ipv4/tcp.c:3691 [inline]
     tcp_getsockopt+0x8c/0xd0 net/ipv4/tcp.c:3685
     kernel_getsockopt+0x121/0x1f0 net/socket.c:3736
     mptcp_getsockopt+0x69/0x90 net/mptcp/protocol.c:830
     __sys_getsockopt+0x13a/0x220 net/socket.c:2175
    
    We can call tcp_get/setsockopt functions instead.  Doing so fixes
    crashing, but still leaves rtnl related lockdep splat:
    
         WARNING: possible circular locking dependency detected
         5.5.0-rc6 #2 Not tainted
         ------------------------------------------------------
         syz-executor.0/16334 is trying to acquire lock:
         ffffffff84f7a080 (rtnl_mutex){+.+.}, at: do_ip_setsockopt.isra.0+0x277/0x3820 net/ipv4/ip_sockglue.c:644
         but task is already holding lock:
         ffff888116503b90 (sk_lock-AF_INET){+.+.}, at: lock_sock include/net/sock.h:1516 [inline]
         ffff888116503b90 (sk_lock-AF_INET){+.+.}, at: mptcp_setsockopt+0x28/0x90 net/mptcp/protocol.c:1284
    
         which lock already depends on the new lock.
         the existing dependency chain (in reverse order) is:
    
         -> #1 (sk_lock-AF_INET){+.+.}:
                lock_sock_nested+0xca/0x120 net/core/sock.c:2944
                lock_sock include/net/sock.h:1516 [inline]
                do_ip_setsockopt.isra.0+0x281/0x3820 net/ipv4/ip_sockglue.c:645
                ip_setsockopt+0x44/0xf0 net/ipv4/ip_sockglue.c:1248
                udp_setsockopt+0x5d/0xa0 net/ipv4/udp.c:2639
                __sys_setsockopt+0x152/0x240 net/socket.c:2130
                __do_sys_setsockopt net/socket.c:2146 [inline]
                __se_sys_setsockopt net/socket.c:2143 [inline]
                __x64_sys_setsockopt+0xba/0x150 net/socket.c:2143
                do_syscall_64+0xbd/0x5b0 arch/x86/entry/common.c:294
                entry_SYSCALL_64_after_hwframe+0x49/0xbe
    
         -> #0 (rtnl_mutex){+.+.}:
                check_prev_add kernel/locking/lockdep.c:2475 [inline]
                check_prevs_add kernel/locking/lockdep.c:2580 [inline]
                validate_chain kernel/locking/lockdep.c:2970 [inline]
                __lock_acquire+0x1fb2/0x4680 kernel/locking/lockdep.c:3954
                lock_acquire+0x127/0x330 kernel/locking/lockdep.c:4484
                __mutex_lock_common kernel/locking/mutex.c:956 [inline]
                __mutex_lock+0x158/0x1340 kernel/locking/mutex.c:1103
                do_ip_setsockopt.isra.0+0x277/0x3820 net/ipv4/ip_sockglue.c:644
                ip_setsockopt+0x44/0xf0 net/ipv4/ip_sockglue.c:1248
                tcp_setsockopt net/ipv4/tcp.c:3159 [inline]
                tcp_setsockopt+0x8c/0xd0 net/ipv4/tcp.c:3153
                kernel_setsockopt+0x121/0x1f0 net/socket.c:3767
                mptcp_setsockopt+0x69/0x90 net/mptcp/protocol.c:1288
                __sys_setsockopt+0x152/0x240 net/socket.c:2130
                __do_sys_setsockopt net/socket.c:2146 [inline]
                __se_sys_setsockopt net/socket.c:2143 [inline]
                __x64_sys_setsockopt+0xba/0x150 net/socket.c:2143
                do_syscall_64+0xbd/0x5b0 arch/x86/entry/common.c:294
                entry_SYSCALL_64_after_hwframe+0x49/0xbe
    
         other info that might help us debug this:
    
          Possible unsafe locking scenario:
    
                CPU0                    CPU1
                ----                    ----
           lock(sk_lock-AF_INET);
                                        lock(rtnl_mutex);
                                        lock(sk_lock-AF_INET);
           lock(rtnl_mutex);
    
    The lockdep complaint is because we hold mptcp socket lock when calling
    the sk_prot get/setsockopt handler, and those might need to acquire the
    rtnl mutex.  Normally, order is:
    
    rtnl_lock(sk) -> lock_sock
    
    Whereas for mptcp the order is
    
    lock_sock(mptcp_sk) rtnl_lock -> lock_sock(subflow_sk)
    
    We can avoid this by releasing the mptcp socket lock early, but, as Paolo
    points out, we need to get/put the subflow socket refcount before doing so
    to avoid race with concurrent close().
    
    Fixes: 717e79c8 ("mptcp: Add setsockopt()/getsockopt() socket operations")
    Reported-by: default avatarChristoph Paasch <cpaasch@apple.com>
    Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    50e741bb
protocol.c 29.9 KB