• P
    vsock: Fix memory leak in vsock_connect() · d6a99a5b
    Peilin Ye 提交于
    stable inclusion
    from stable-v5.10.138
    commit 38ddccbda5e8b762c8ee06670bb1f64f1be5ee50
    category: bugfix
    bugzilla: 187891, https://gitee.com/src-openeuler/kernel/issues/I5WYLL
    CVE: CVE-2022-3629
    
    Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=38ddccbda5e8b762c8ee06670bb1f64f1be5ee50
    
    --------------------------------
    
    commit 7e97cfed upstream.
    
    An O_NONBLOCK vsock_connect() request may try to reschedule
    @connect_work.  Imagine the following sequence of vsock_connect()
    requests:
    
      1. The 1st, non-blocking request schedules @connect_work, which will
         expire after 200 jiffies.  Socket state is now SS_CONNECTING;
    
      2. Later, the 2nd, blocking request gets interrupted by a signal after
         a few jiffies while waiting for the connection to be established.
         Socket state is back to SS_UNCONNECTED, but @connect_work is still
         pending, and will expire after 100 jiffies.
    
      3. Now, the 3rd, non-blocking request tries to schedule @connect_work
         again.  Since @connect_work is already scheduled,
         schedule_delayed_work() silently returns.  sock_hold() is called
         twice, but sock_put() will only be called once in
         vsock_connect_timeout(), causing a memory leak reported by syzbot:
    
      BUG: memory leak
      unreferenced object 0xffff88810ea56a40 (size 1232):
        comm "syz-executor756", pid 3604, jiffies 4294947681 (age 12.350s)
        hex dump (first 32 bytes):
          00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
          28 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00  (..@............
        backtrace:
          [<ffffffff837c830e>] sk_prot_alloc+0x3e/0x1b0 net/core/sock.c:1930
          [<ffffffff837cbe22>] sk_alloc+0x32/0x2e0 net/core/sock.c:1989
          [<ffffffff842ccf68>] __vsock_create.constprop.0+0x38/0x320 net/vmw_vsock/af_vsock.c:734
          [<ffffffff842ce8f1>] vsock_create+0xc1/0x2d0 net/vmw_vsock/af_vsock.c:2203
          [<ffffffff837c0cbb>] __sock_create+0x1ab/0x2b0 net/socket.c:1468
          [<ffffffff837c3acf>] sock_create net/socket.c:1519 [inline]
          [<ffffffff837c3acf>] __sys_socket+0x6f/0x140 net/socket.c:1561
          [<ffffffff837c3bba>] __do_sys_socket net/socket.c:1570 [inline]
          [<ffffffff837c3bba>] __se_sys_socket net/socket.c:1568 [inline]
          [<ffffffff837c3bba>] __x64_sys_socket+0x1a/0x20 net/socket.c:1568
          [<ffffffff84512815>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
          [<ffffffff84512815>] do_syscall_64+0x35/0x80 arch/x86/entry/common.c:80
          [<ffffffff84600068>] entry_SYSCALL_64_after_hwframe+0x44/0xae
      <...>
    
    Use mod_delayed_work() instead: if @connect_work is already scheduled,
    reschedule it, and undo sock_hold() to keep the reference count
    balanced.
    
    Reported-and-tested-by: syzbot+b03f55bf128f9a38f064@syzkaller.appspotmail.com
    Fixes: d021c344 ("VSOCK: Introduce VM Sockets")
    Co-developed-by: NStefano Garzarella <sgarzare@redhat.com>
    Signed-off-by: NStefano Garzarella <sgarzare@redhat.com>
    Reviewed-by: NStefano Garzarella <sgarzare@redhat.com>
    Signed-off-by: NPeilin Ye <peilin.ye@bytedance.com>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: NDong Chenchen <dongchenchen2@huawei.com>
    Reviewed-by: NYue Haibing <yuehaibing@huawei.com>
    Reviewed-by: NXiu Jianfeng <xiujianfeng@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    d6a99a5b
af_vsock.c 54.1 KB