From patchwork Mon Feb 11 09:09:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Sitnicki X-Patchwork-Id: 1039721 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.b="QVjUJOsR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43yg3S4jf2z9sML for ; Mon, 11 Feb 2019 20:09:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726969AbfBKJJy (ORCPT ); Mon, 11 Feb 2019 04:09:54 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:46807 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725962AbfBKJJy (ORCPT ); Mon, 11 Feb 2019 04:09:54 -0500 Received: by mail-lf1-f67.google.com with SMTP id f5so7084719lfc.13 for ; Mon, 11 Feb 2019 01:09:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id; bh=GJ6imEDw5UyUioFjaMHqimZGHnA0N8Anah3vNme+WoE=; b=QVjUJOsRBl33KYctTMZtuiio3Tn/DxG7oKEpnSeS8OFtogNnubvo3RYrOBBsrBcKIF KJr9Sye+I3+c039nwtpvbhLN8YSBda5bFc43YyuUYwE7GGGV5mrEYViUASfDMoUfTxac WXzrLOshh362G4CMHHqr9SoY9yTYf/OmyCZl4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=GJ6imEDw5UyUioFjaMHqimZGHnA0N8Anah3vNme+WoE=; b=kLInNOoK+qzBBJUaNzbLOwq7DuII9hva1zKePme4luUt6x/9k+dp3kKYxQUiwWz7QY S1WHoJ0wz5u9gruZ2XqsX1gJwkBwkCBWK8Auecn/Nlp9ezLRdG9LmRiF9odWPNOcqBIn XXFFvQvK/+VhuN5M1gpxKhsyM7CUlSnWSlDiTR5uKAk26unzlT1Xy4rL7BQSf5uF3lVS IOFixwfPrZZsop05safb6UnSmydTruSF5R0c3YoKN4qT2paDIu0T2p8nHkbJvoK8aUDf cO2msJP10jtsBregG0YF7xeOkXvsGLC6vDwRamfzWb2vjvAgy5hvc/Pyt37+saqEKbbc l7lQ== X-Gm-Message-State: AHQUAuYKGOh4ZnqdrCSlfZ42CWdPwRiPjXGPuqjX3BBHf+iQn8lIARKv pNTGFM/SyK518IfEbbJYzgPEj/Mtiuo= X-Google-Smtp-Source: AHgI3IaPJq7I7yDdldsAnxUTf8uFSo1PHGw9xeM8yOAw4c47MBmgXsqvqx7v14ye17re1zYQwHUy2w== X-Received: by 2002:a19:4f57:: with SMTP id a23mr10235445lfk.46.1549876191043; Mon, 11 Feb 2019 01:09:51 -0800 (PST) Received: from cloudflare.com ([176.221.114.230]) by smtp.gmail.com with ESMTPSA id p21sm2183291lfd.4.2019.02.11.01.09.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 11 Feb 2019 01:09:50 -0800 (PST) From: Jakub Sitnicki To: netdev@vger.kernel.org Cc: Daniel Borkmann , John Fastabend , Marek Majkowski Subject: [PATCH net] sk_msg: Keep reference on socket file while psock lives Date: Mon, 11 Feb 2019 10:09:49 +0100 Message-Id: <20190211090949.18560-1-jakub@cloudflare.com> X-Mailer: git-send-email 2.17.2 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Backlog work for psock (sk_psock_backlog) might sleep while waiting for memory to free up when sending packets. While sleeping, socket can disappear from under our feet together with its wait queue because the userspace has closed it. This breaks an assumption in sk_stream_wait_memory, which expects the wait queue to be still there when it wakes up resulting in a use-after-free: ================================================================== BUG: KASAN: use-after-free in remove_wait_queue+0x31/0x70 Write of size 8 at addr ffff888069a0c4e8 by task kworker/0:2/110 CPU: 0 PID: 110 Comm: kworker/0:2 Not tainted 5.0.0-rc2-00335-g28f9d1a3d4fe-dirty #14 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-2.fc27 04/01/2014 Workqueue: events sk_psock_backlog Call Trace: print_address_description+0x6e/0x2b0 ? remove_wait_queue+0x31/0x70 kasan_report+0xfd/0x177 ? remove_wait_queue+0x31/0x70 ? remove_wait_queue+0x31/0x70 remove_wait_queue+0x31/0x70 sk_stream_wait_memory+0x4dd/0x5f0 ? sk_stream_wait_close+0x1b0/0x1b0 ? wait_woken+0xc0/0xc0 ? tcp_current_mss+0xc5/0x110 tcp_sendmsg_locked+0x634/0x15d0 ? tcp_set_state+0x2e0/0x2e0 ? __kasan_slab_free+0x1d1/0x230 ? kmem_cache_free+0x70/0x140 ? sk_psock_backlog+0x40c/0x4b0 ? process_one_work+0x40b/0x660 ? worker_thread+0x82/0x680 ? kthread+0x1b9/0x1e0 ? ret_from_fork+0x1f/0x30 ? check_preempt_curr+0xaf/0x130 ? iov_iter_kvec+0x5f/0x70 ? kernel_sendmsg_locked+0xa0/0xe0 skb_send_sock_locked+0x273/0x3c0 ? skb_splice_bits+0x180/0x180 ? start_thread+0xe0/0xe0 ? update_min_vruntime.constprop.27+0x88/0xc0 sk_psock_backlog+0xb3/0x4b0 ? strscpy+0xbf/0x1e0 process_one_work+0x40b/0x660 worker_thread+0x82/0x680 ? process_one_work+0x660/0x660 kthread+0x1b9/0x1e0 ? __kthread_create_on_node+0x250/0x250 ret_from_fork+0x1f/0x30 Allocated by task 109: sock_alloc_inode+0x54/0x120 alloc_inode+0x28/0xb0 new_inode_pseudo+0x7/0x60 sock_alloc+0x21/0xe0 __sys_accept4+0xc2/0x330 __x64_sys_accept+0x3b/0x50 do_syscall_64+0xb2/0x3e0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Freed by task 7: kfree+0x7f/0x140 rcu_process_callbacks+0xe0/0x100 __do_softirq+0xe5/0x29a The buggy address belongs to the object at ffff888069a0c4e0 which belongs to the cache kmalloc-64 of size 64 The buggy address is located 8 bytes inside of 64-byte region [ffff888069a0c4e0, ffff888069a0c520) The buggy address belongs to the page: page:ffffea0001a68300 count:1 mapcount:0 mapping:ffff88806d4018c0 index:0x0 flags: 0x4000000000000200(slab) raw: 4000000000000200 dead000000000100 dead000000000200 ffff88806d4018c0 raw: 0000000000000000 00000000002a002a 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888069a0c380: fb fb fb fb fc fc fc fc fb fb fb fb fb fb fb fb ffff888069a0c400: fc fc fc fc fb fb fb fb fb fb fb fb fc fc fc fc >ffff888069a0c480: 00 00 00 00 00 00 00 00 fc fc fc fc fb fb fb fb ^ ffff888069a0c500: fb fb fb fb fc fc fc fc fb fb fb fb fb fb fb fb ffff888069a0c580: fc fc fc fc fb fb fb fb fb fb fb fb fc fc fc fc ================================================================== Avoid it by keeping a reference to the socket file until the psock gets destroyed. While at it, rearrange the order of reference grabbing and initialization to match the destructor in reverse. Reported-by: Marek Majkowski Link: https://lore.kernel.org/netdev/CAJPywTLwgXNEZ2dZVoa=udiZmtrWJ0q5SuBW64aYs0Y1khXX3A@mail.gmail.com Signed-off-by: Jakub Sitnicki --- net/core/skmsg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 8c826603bf36..a38442b8580b 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -493,8 +493,13 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node) sk_psock_set_state(psock, SK_PSOCK_TX_ENABLED); refcount_set(&psock->refcnt, 1); - rcu_assign_sk_user_data(sk, psock); + /* Hold on to socket wait queue. Backlog work waits on it for + * memory when sending. We must cancel work before socket wait + * queue can go away. + */ + get_file(sk->sk_socket->file); sock_hold(sk); + rcu_assign_sk_user_data(sk, psock); return psock; } @@ -558,6 +563,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc) if (psock->sk_redir) sock_put(psock->sk_redir); sock_put(psock->sk); + fput(psock->sk->sk_socket->file); kfree(psock); }