Message ID | 20221120090213.922567-1-syoshida@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp1043519wrr; Sun, 20 Nov 2022 01:30:07 -0800 (PST) X-Google-Smtp-Source: AA0mqf4AmtIXj3gNM6lZCccH/rlO/IknQhlLrfcVzhnhmj4oRnswex0d6+k5BnbXiQ8PuO8awYbz X-Received: by 2002:a05:6a00:1a88:b0:562:bcf8:7b35 with SMTP id e8-20020a056a001a8800b00562bcf87b35mr15822990pfv.52.1668936606916; Sun, 20 Nov 2022 01:30:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668936606; cv=none; d=google.com; s=arc-20160816; b=A+zvWsGPVKSBVU1BldG4evQt5kSeufiPXMBygQxxB382xqbtKuVLkXYY7H18+S/lfg CtfnA0/FayFQ0hWSRziAJe9PMiTrx6N5ke2SV5fs8Wh5xPaFBIKD/Hteilr0xFjhDoHO GYMKgpeP2orAAmMxzt4aW3Z9FJ70dlu6Qa2w+kB6tR5RnU6v/rjC2uKcuzJVDFxwz6TD odY3VmsL5lDZrsGs299eCyd34ouYAfHtGoZ+EoCBnIYkdIG1fVROD1Ed9z15z9pJVsWW +WgXAQKOLHZt8El717PRz+OORh0VrXA+zcVysTPYj71xP2fbnxZyfFUuvWDKIygWmIFE M+BA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=oEYRj+tvOCAOAYfObhytG1SVOeN3XgfIQzsjLTeBgGY=; b=HyTJAo8SuYKBiqOHfqUTUQby/EFZLglD2GllmewBwNmf3jb/osWcvNMhhh1sXkaGcg 2+w9kJt9qeZUT0nVn78NtsIGwfnw5X5uqKSiZakTxC3aaG5npdTbYal7MGFqwvwIrHcP qkOFWJrOfdpsdSjsEDP5eMRSvmJJDxNCfIZCNJTvQQ2J3XyQiWnWGk6dhvlbHNEi4fvC yJws7KAfx+uQXcpMJOiZaWWcR+zleE5BxojpTLjHm57QJ+7/Ic1BIlzU8hDfedzYsqIz PG5mKAXQsn7MVD6sPBUL20osSeZ8PGAT9dRRgW69EF0BNNNuVljUHuql0aMPEp28EzJF kCTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="b/yM8opZ"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r33-20020a632061000000b0047011722bc6si8119009pgm.531.2022.11.20.01.29.38; Sun, 20 Nov 2022 01:30:06 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="b/yM8opZ"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229595AbiKTJDd (ORCPT <rfc822;aposhian.dev@gmail.com> + 99 others); Sun, 20 Nov 2022 04:03:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229454AbiKTJDb (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sun, 20 Nov 2022 04:03:31 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D7C610AB for <linux-kernel@vger.kernel.org>; Sun, 20 Nov 2022 01:02:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1668934952; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=oEYRj+tvOCAOAYfObhytG1SVOeN3XgfIQzsjLTeBgGY=; b=b/yM8opZEW1JjuO7UTNj7NlVg192MAqzjUVZ4MdgyoG9SiBaGgIzv9UhxzMU6YBEN7siQ8 bWIaGgMxpGZr03gS2KQFiDZAK2/I1FCFSt3PTGhklh5JricLar1UjdkjaTMQqli43sygY0 J4+HhIALZm398fuDi08beOYEmqG98AM= Received: from mail-pj1-f69.google.com (mail-pj1-f69.google.com [209.85.216.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-669-hFMFia6RMv26j7ORsP0WTA-1; Sun, 20 Nov 2022 04:02:30 -0500 X-MC-Unique: hFMFia6RMv26j7ORsP0WTA-1 Received: by mail-pj1-f69.google.com with SMTP id p1-20020a17090a2c4100b00212733d7aaaso4688684pjm.4 for <linux-kernel@vger.kernel.org>; Sun, 20 Nov 2022 01:02:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=oEYRj+tvOCAOAYfObhytG1SVOeN3XgfIQzsjLTeBgGY=; b=h8FycCaSAIzbzEIOGJvKcBDL/n9Od60A4ubWjE6zhWTnQS8bEfT0HHX+cIrKX3u1GY Kkbpt4MAChP0eBvSIRWnR2YX4RO6oiti4VfpbE72Vo4m38wjntOaHDKRu+pKTOVKgIU6 JQsXnkHTuyL+ihRQugypLg4WuMQKPfwSUciGnJe4G7mukilmZ9MPElusVvLzLIkdjsln gqxU8TzBH3+DE2IXPx0HtCDV6pPgE5xviycy4XVxq7FA2NxAbaVlv+h5yKIamBbuPc9+ 2NDZQAOMP+p20XJ6vJ1HEhXiKaySVLBJtvuy1uDqefYo02PeC0GoOqCc7qqfwjL2rYK1 RLig== X-Gm-Message-State: ANoB5pm0kCDi64WGQJLqUPgK9wHdwXMgkESskUPnhnx5wpR1WXD8LYwo tRQMZgTlgOcE9OaLjrCpqEFYMPDQl+smPSXqm9chOd16d4dhjXUMfr6Penx4IOVC9SKkbU/QT0+ 3/Bh3QBkUF2Z0jPZZmjQn7JRX X-Received: by 2002:a17:902:b40b:b0:188:ca57:ce0c with SMTP id x11-20020a170902b40b00b00188ca57ce0cmr7033110plr.57.1668934949248; Sun, 20 Nov 2022 01:02:29 -0800 (PST) X-Received: by 2002:a17:902:b40b:b0:188:ca57:ce0c with SMTP id x11-20020a170902b40b00b00188ca57ce0cmr7033078plr.57.1668934948810; Sun, 20 Nov 2022 01:02:28 -0800 (PST) Received: from ryzen.. ([240d:1a:c0d:9f00:fc9c:8ee9:e32c:2d9]) by smtp.gmail.com with ESMTPSA id h129-20020a625387000000b0056c063dd4cfsm6323422pfb.66.2022.11.20.01.02.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Nov 2022 01:02:28 -0800 (PST) From: Shigeru Yoshida <syoshida@redhat.com> To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com, Shigeru Yoshida <syoshida@redhat.com>, syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com Subject: [PATCH v2] net: tun: Fix use-after-free in tun_detach() Date: Sun, 20 Nov 2022 18:02:13 +0900 Message-Id: <20221120090213.922567-1-syoshida@redhat.com> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749911256687682614?= X-GMAIL-MSGID: =?utf-8?q?1750006871820699586?= |
Series |
[v2] net: tun: Fix use-after-free in tun_detach()
|
|
Commit Message
Shigeru Yoshida
Nov. 20, 2022, 9:02 a.m. UTC
syzbot reported use-after-free in tun_detach() [1]. This causes call
trace like below:
==================================================================
BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75
Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673
CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:284 [inline]
print_report+0x15e/0x461 mm/kasan/report.c:395
kasan_report+0xbf/0x1f0 mm/kasan/report.c:495
notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75
call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942
call_netdevice_notifiers_extack net/core/dev.c:1983 [inline]
call_netdevice_notifiers net/core/dev.c:1997 [inline]
netdev_wait_allrefs_any net/core/dev.c:10237 [inline]
netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351
tun_detach drivers/net/tun.c:704 [inline]
tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
exit_task_work include/linux/task_work.h:38 [inline]
do_exit+0xb3d/0x2a30 kernel/exit.c:820
do_group_exit+0xd4/0x2a0 kernel/exit.c:950
get_signal+0x21b1/0x2440 kernel/signal.c:2858
arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869
exit_to_user_mode_loop kernel/entry/common.c:168 [inline]
exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The cause of the issue is that sock_put() from __tun_detach() drops
last reference count for struct net, and then notifier_call_chain()
from netdev_state_change() accesses that struct net.
This patch fixes the issue by calling sock_put() from tun_detach()
after all necessary accesses for the struct net has done.
Fixes: 83c1f36f9880 ("tun: send netlink notification when the device is modified")
Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe [1]
Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>
---
v2:
- Include symbolic stack trace
- Add Fixes and Reported-by tags
v1: https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/
---
drivers/net/tun.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
Comments
On Sun, Nov 20, 2022 at 2:49 AM Hillf Danton <hdanton@sina.com> wrote: > > On 20 Nov 2022 18:02:13 +0900 Shigeru Yoshida <syoshida@redhat.com> > > syzbot reported use-after-free in tun_detach() [1]. This causes call > > trace like below: > > > > ================================================================== > > BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > > Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 > > > > CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 > > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 > > Call Trace: > > <TASK> > > __dump_stack lib/dump_stack.c:88 [inline] > > dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 > > print_address_description mm/kasan/report.c:284 [inline] > > print_report+0x15e/0x461 mm/kasan/report.c:395 > > kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 > > notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > > call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 > > call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] > > call_netdevice_notifiers net/core/dev.c:1997 [inline] > > netdev_wait_allrefs_any net/core/dev.c:10237 [inline] > > netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 > > tun_detach drivers/net/tun.c:704 [inline] > > tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 > > __fput+0x27c/0xa90 fs/file_table.c:320 > > task_work_run+0x16f/0x270 kernel/task_work.c:179 > > exit_task_work include/linux/task_work.h:38 [inline] > > do_exit+0xb3d/0x2a30 kernel/exit.c:820 > > do_group_exit+0xd4/0x2a0 kernel/exit.c:950 > > get_signal+0x21b1/0x2440 kernel/signal.c:2858 > > arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 > > exit_to_user_mode_loop kernel/entry/common.c:168 [inline] > > exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 > > __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] > > syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 > > do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 > > entry_SYSCALL_64_after_hwframe+0x63/0xcd > > > > The cause of the issue is that sock_put() from __tun_detach() drops > > last reference count for struct net, and then notifier_call_chain() > > from netdev_state_change() accesses that struct net. > > Correct. IOW the race between netdev_run_todo() and cleanup_net() is behind > the uaf report from syzbot. > > > > > This patch fixes the issue by calling sock_put() from tun_detach() > > after all necessary accesses for the struct net has done. > > Thanks for your fix. > > But tun is not special wrt netdev_run_todo() and call_netdevice_notifiers(), > so the correct fix should be making netdev grab another hold on net and > invoking put_net() in the path of netdev_run_todo(). Well, this is not going to work. Unless I am missing something. 1) A netns is destroyed when its refcount reaches zero. if (refcount_dec_and_test(&net->ns.count)) __put_net(net); This transition is final. (It is illegal to attempt a refcount_inc() from this state) 2) All its netdevices are unregistered. Trying to get a reference on netns in netdevice dismantle path would immediately trigger a refcount_t warning.
On Sun, Nov 20, 2022 at 4:34 PM Hillf Danton <hdanton@sina.com> wrote: > > On 20 Nov 2022 08:04:13 -0800 Eric Dumazet <edumazet@google.com> > > On Sun, Nov 20, 2022 at 2:49 AM Hillf Danton <hdanton@sina.com> wrote: > > > On 20 Nov 2022 18:02:13 +0900 Shigeru Yoshida <syoshida@redhat.com> > > > > > > > > This patch fixes the issue by calling sock_put() from tun_detach() > > > > after all necessary accesses for the struct net has done. > > > > > > Thanks for your fix. > > > > > > But tun is not special wrt netdev_run_todo() and call_netdevice_notifiers(), > > > so the correct fix should be making netdev grab another hold on net and > > > invoking put_net() in the path of netdev_run_todo(). > > > > Well, this is not going to work. Unless I am missing something. > > Thanks for taking a look. > > I mean bump up refcount for net when updating netdev->nd_net in a bid to > make dev_net() safe throught netdev's life span. This would prevent netns deletion, as the following sequence would then no longer work as intended. ip netns add foo ip netns add ip link set lo up ip netns del foo When a netns is deleted ("ip netns del" and no more refcounted sockets), we have callbacks to unregister all devices tied to it.
On Sun, Nov 20, 2022 at 1:02 AM Shigeru Yoshida <syoshida@redhat.com> wrote: > > syzbot reported use-after-free in tun_detach() [1]. This causes call > trace like below: > > ================================================================== > BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 > > CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 > Call Trace: > <TASK> > __dump_stack lib/dump_stack.c:88 [inline] > dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 > print_address_description mm/kasan/report.c:284 [inline] > print_report+0x15e/0x461 mm/kasan/report.c:395 > kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 > notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 > call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] > call_netdevice_notifiers net/core/dev.c:1997 [inline] > netdev_wait_allrefs_any net/core/dev.c:10237 [inline] > netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 > tun_detach drivers/net/tun.c:704 [inline] > tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 > __fput+0x27c/0xa90 fs/file_table.c:320 > task_work_run+0x16f/0x270 kernel/task_work.c:179 > exit_task_work include/linux/task_work.h:38 [inline] > do_exit+0xb3d/0x2a30 kernel/exit.c:820 > do_group_exit+0xd4/0x2a0 kernel/exit.c:950 > get_signal+0x21b1/0x2440 kernel/signal.c:2858 > arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 > exit_to_user_mode_loop kernel/entry/common.c:168 [inline] > exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 > __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] > syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 > do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 > entry_SYSCALL_64_after_hwframe+0x63/0xcd > > The cause of the issue is that sock_put() from __tun_detach() drops > last reference count for struct net, and then notifier_call_chain() > from netdev_state_change() accesses that struct net. > > This patch fixes the issue by calling sock_put() from tun_detach() > after all necessary accesses for the struct net has done. > > Fixes: 83c1f36f9880 ("tun: send netlink notification when the device is modified") > Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com > Link: https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe [1] > Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> > --- > v2: > - Include symbolic stack trace > - Add Fixes and Reported-by tags > v1: https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/ > --- > drivers/net/tun.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/tun.c b/drivers/net/tun.c > index 7a3ab3427369..ce9fcf4c8ef4 100644 > --- a/drivers/net/tun.c > +++ b/drivers/net/tun.c > @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean) > if (tun) > xdp_rxq_info_unreg(&tfile->xdp_rxq); > ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); > - sock_put(&tfile->sk); > } > } > > @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, bool clean) > if (dev) > netdev_state_change(dev); > rtnl_unlock(); > + > + if (clean) { Would you mind explaining (a comment would be nice) why this barrier is needed ? Thanks. > + synchronize_rcu(); > + sock_put(&tfile->sk); > + } > } > > static void tun_detach_all(struct net_device *dev) > -- > 2.38.1 >
Hi Eric, On Mon, 21 Nov 2022 08:47:17 -0800, Eric Dumazet wrote: > On Sun, Nov 20, 2022 at 1:02 AM Shigeru Yoshida <syoshida@redhat.com> wrote: >> >> syzbot reported use-after-free in tun_detach() [1]. This causes call >> trace like below: >> >> ================================================================== >> BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 >> Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 >> >> CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 >> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 >> Call Trace: >> <TASK> >> __dump_stack lib/dump_stack.c:88 [inline] >> dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 >> print_address_description mm/kasan/report.c:284 [inline] >> print_report+0x15e/0x461 mm/kasan/report.c:395 >> kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 >> notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 >> call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 >> call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] >> call_netdevice_notifiers net/core/dev.c:1997 [inline] >> netdev_wait_allrefs_any net/core/dev.c:10237 [inline] >> netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 >> tun_detach drivers/net/tun.c:704 [inline] >> tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 >> __fput+0x27c/0xa90 fs/file_table.c:320 >> task_work_run+0x16f/0x270 kernel/task_work.c:179 >> exit_task_work include/linux/task_work.h:38 [inline] >> do_exit+0xb3d/0x2a30 kernel/exit.c:820 >> do_group_exit+0xd4/0x2a0 kernel/exit.c:950 >> get_signal+0x21b1/0x2440 kernel/signal.c:2858 >> arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 >> exit_to_user_mode_loop kernel/entry/common.c:168 [inline] >> exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 >> __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] >> syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 >> do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 >> entry_SYSCALL_64_after_hwframe+0x63/0xcd >> >> The cause of the issue is that sock_put() from __tun_detach() drops >> last reference count for struct net, and then notifier_call_chain() >> from netdev_state_change() accesses that struct net. >> >> This patch fixes the issue by calling sock_put() from tun_detach() >> after all necessary accesses for the struct net has done. >> >> Fixes: 83c1f36f9880 ("tun: send netlink notification when the device is modified") >> Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com >> Link: https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe [1] >> Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> >> --- >> v2: >> - Include symbolic stack trace >> - Add Fixes and Reported-by tags >> v1: https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/ >> --- >> drivers/net/tun.c | 6 +++++- >> 1 file changed, 5 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/net/tun.c b/drivers/net/tun.c >> index 7a3ab3427369..ce9fcf4c8ef4 100644 >> --- a/drivers/net/tun.c >> +++ b/drivers/net/tun.c >> @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean) >> if (tun) >> xdp_rxq_info_unreg(&tfile->xdp_rxq); >> ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); >> - sock_put(&tfile->sk); >> } >> } >> >> @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, bool clean) >> if (dev) >> netdev_state_change(dev); >> rtnl_unlock(); >> + >> + if (clean) { > > Would you mind explaining (a comment would be nice) why this barrier is needed ? I thought that tfile is accessed with rcu_lock(), so I put synchronize_rcu() here. Please let me know if I misunderstand the concept of rcu (I'm losing my confidence...). Thanks, Shigeru > > Thanks. > >> + synchronize_rcu(); >> + sock_put(&tfile->sk); >> + } >> } >> >> static void tun_detach_all(struct net_device *dev) >> -- >> 2.38.1 >> >
On Tue, Nov 22, 2022 at 10:10 AM Shigeru Yoshida <syoshida@redhat.com> wrote: > > Hi Eric, > > On Mon, 21 Nov 2022 08:47:17 -0800, Eric Dumazet wrote: > > On Sun, Nov 20, 2022 at 1:02 AM Shigeru Yoshida <syoshida@redhat.com> wrote: > >> > >> syzbot reported use-after-free in tun_detach() [1]. This causes call > >> trace like below: > >> > >> ================================================================== > >> BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > >> Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 > >> > >> CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 > >> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 > >> Call Trace: > >> <TASK> > >> __dump_stack lib/dump_stack.c:88 [inline] > >> dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 > >> print_address_description mm/kasan/report.c:284 [inline] > >> print_report+0x15e/0x461 mm/kasan/report.c:395 > >> kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 > >> notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 > >> call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 > >> call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] > >> call_netdevice_notifiers net/core/dev.c:1997 [inline] > >> netdev_wait_allrefs_any net/core/dev.c:10237 [inline] > >> netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 > >> tun_detach drivers/net/tun.c:704 [inline] > >> tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 > >> __fput+0x27c/0xa90 fs/file_table.c:320 > >> task_work_run+0x16f/0x270 kernel/task_work.c:179 > >> exit_task_work include/linux/task_work.h:38 [inline] > >> do_exit+0xb3d/0x2a30 kernel/exit.c:820 > >> do_group_exit+0xd4/0x2a0 kernel/exit.c:950 > >> get_signal+0x21b1/0x2440 kernel/signal.c:2858 > >> arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 > >> exit_to_user_mode_loop kernel/entry/common.c:168 [inline] > >> exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 > >> __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] > >> syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 > >> do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 > >> entry_SYSCALL_64_after_hwframe+0x63/0xcd > >> > >> The cause of the issue is that sock_put() from __tun_detach() drops > >> last reference count for struct net, and then notifier_call_chain() > >> from netdev_state_change() accesses that struct net. > >> > >> This patch fixes the issue by calling sock_put() from tun_detach() > >> after all necessary accesses for the struct net has done. > >> > >> Fixes: 83c1f36f9880 ("tun: send netlink notification when the device is modified") > >> Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com > >> Link: https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe [1] > >> Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> > >> --- > >> v2: > >> - Include symbolic stack trace > >> - Add Fixes and Reported-by tags > >> v1: https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/ > >> --- > >> drivers/net/tun.c | 6 +++++- > >> 1 file changed, 5 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/net/tun.c b/drivers/net/tun.c > >> index 7a3ab3427369..ce9fcf4c8ef4 100644 > >> --- a/drivers/net/tun.c > >> +++ b/drivers/net/tun.c > >> @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean) > >> if (tun) > >> xdp_rxq_info_unreg(&tfile->xdp_rxq); > >> ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); > >> - sock_put(&tfile->sk); > >> } > >> } > >> > >> @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, bool clean) > >> if (dev) > >> netdev_state_change(dev); > >> rtnl_unlock(); > >> + > >> + if (clean) { > > > > Would you mind explaining (a comment would be nice) why this barrier is needed ? > > I thought that tfile is accessed with rcu_lock(), so I put > synchronize_rcu() here. Please let me know if I misunderstand the > concept of rcu (I'm losing my confidence...). > Addin Jason for comments. If an RCU grace period was needed before commit 83c1f36f9880 ("tun: send netlink notification when the device is modified"), would we need another patch ? Also sock_flag(sk, SOCK_RCU_FREE) would probably be better than adding a synchronize_rcu() (if again a grace period is needed) > Thanks, > Shigeru > > > > > Thanks. > > > >> + synchronize_rcu(); > >> + sock_put(&tfile->sk); > >> + } > >> } > >> > >> static void tun_detach_all(struct net_device *dev) > >> -- > >> 2.38.1 > >> > > >
在 2022/11/23 02:47, Eric Dumazet 写道: > On Tue, Nov 22, 2022 at 10:10 AM Shigeru Yoshida <syoshida@redhat.com> wrote: >> Hi Eric, >> >> On Mon, 21 Nov 2022 08:47:17 -0800, Eric Dumazet wrote: >>> On Sun, Nov 20, 2022 at 1:02 AM Shigeru Yoshida <syoshida@redhat.com> wrote: >>>> syzbot reported use-after-free in tun_detach() [1]. This causes call >>>> trace like below: >>>> >>>> ================================================================== >>>> BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 >>>> Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 >>>> >>>> CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 >>>> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 >>>> Call Trace: >>>> <TASK> >>>> __dump_stack lib/dump_stack.c:88 [inline] >>>> dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 >>>> print_address_description mm/kasan/report.c:284 [inline] >>>> print_report+0x15e/0x461 mm/kasan/report.c:395 >>>> kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 >>>> notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 >>>> call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 >>>> call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] >>>> call_netdevice_notifiers net/core/dev.c:1997 [inline] >>>> netdev_wait_allrefs_any net/core/dev.c:10237 [inline] >>>> netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 >>>> tun_detach drivers/net/tun.c:704 [inline] >>>> tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 >>>> __fput+0x27c/0xa90 fs/file_table.c:320 >>>> task_work_run+0x16f/0x270 kernel/task_work.c:179 >>>> exit_task_work include/linux/task_work.h:38 [inline] >>>> do_exit+0xb3d/0x2a30 kernel/exit.c:820 >>>> do_group_exit+0xd4/0x2a0 kernel/exit.c:950 >>>> get_signal+0x21b1/0x2440 kernel/signal.c:2858 >>>> arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 >>>> exit_to_user_mode_loop kernel/entry/common.c:168 [inline] >>>> exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 >>>> __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] >>>> syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 >>>> do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 >>>> entry_SYSCALL_64_after_hwframe+0x63/0xcd >>>> >>>> The cause of the issue is that sock_put() from __tun_detach() drops >>>> last reference count for struct net, and then notifier_call_chain() >>>> from netdev_state_change() accesses that struct net. >>>> >>>> This patch fixes the issue by calling sock_put() from tun_detach() >>>> after all necessary accesses for the struct net has done. >>>> >>>> Fixes: 83c1f36f9880 ("tun: send netlink notification when the device is modified") >>>> Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com >>>> Link: https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe [1] >>>> Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> >>>> --- >>>> v2: >>>> - Include symbolic stack trace >>>> - Add Fixes and Reported-by tags >>>> v1: https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/ >>>> --- >>>> drivers/net/tun.c | 6 +++++- >>>> 1 file changed, 5 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c >>>> index 7a3ab3427369..ce9fcf4c8ef4 100644 >>>> --- a/drivers/net/tun.c >>>> +++ b/drivers/net/tun.c >>>> @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean) >>>> if (tun) >>>> xdp_rxq_info_unreg(&tfile->xdp_rxq); >>>> ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); >>>> - sock_put(&tfile->sk); >>>> } >>>> } >>>> >>>> @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, bool clean) >>>> if (dev) >>>> netdev_state_change(dev); >>>> rtnl_unlock(); >>>> + >>>> + if (clean) { >>> Would you mind explaining (a comment would be nice) why this barrier is needed ? >> I thought that tfile is accessed with rcu_lock(), so I put >> synchronize_rcu() here. Please let me know if I misunderstand the >> concept of rcu (I'm losing my confidence...). >> > Addin Jason for comments. > > If an RCU grace period was needed before commit 83c1f36f9880 ("tun: > send netlink notification when the device is modified"), > would we need another patch ? I think we don't need another synchronization here. __tun_detach() has already done the necessary synchronization when it tries to modify tun->tfiles array and tfile->tun. Thanks > > Also sock_flag(sk, SOCK_RCU_FREE) would probably be better than adding > a synchronize_rcu() (if again a grace period is needed) > > > >> Thanks, >> Shigeru >> >>> Thanks. >>> >>>> + synchronize_rcu(); >>>> + sock_put(&tfile->sk); >>>> + } >>>> } >>>> >>>> static void tun_detach_all(struct net_device *dev) >>>> -- >>>> 2.38.1 >>>>
Hi Jason, On Wed, 23 Nov 2022 12:20:47 +0800, Jason Wang wrote: > > 在 2022/11/23 02:47, Eric Dumazet 写道: >> On Tue, Nov 22, 2022 at 10:10 AM Shigeru Yoshida <syoshida@redhat.com> >> wrote: >>> Hi Eric, >>> >>> On Mon, 21 Nov 2022 08:47:17 -0800, Eric Dumazet wrote: >>>> On Sun, Nov 20, 2022 at 1:02 AM Shigeru Yoshida <syoshida@redhat.com> >>>> wrote: >>>>> syzbot reported use-after-free in tun_detach() [1]. This causes call >>>>> trace like below: >>>>> >>>>> ================================================================== >>>>> BUG: KASAN: use-after-free in notifier_call_chain+0x1ee/0x200 >>>>> kernel/notifier.c:75 >>>>> Read of size 8 at addr ffff88807324e2a8 by task syz-executor.0/3673 >>>>> >>>>> CPU: 0 PID: 3673 Comm: syz-executor.0 Not tainted >>>>> 6.1.0-rc5-syzkaller-00044-gcc675d22e422 #0 >>>>> Hardware name: Google Google Compute Engine/Google Compute Engine, >>>>> BIOS Google 10/26/2022 >>>>> Call Trace: >>>>> <TASK> >>>>> __dump_stack lib/dump_stack.c:88 [inline] >>>>> dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106 >>>>> print_address_description mm/kasan/report.c:284 [inline] >>>>> print_report+0x15e/0x461 mm/kasan/report.c:395 >>>>> kasan_report+0xbf/0x1f0 mm/kasan/report.c:495 >>>>> notifier_call_chain+0x1ee/0x200 kernel/notifier.c:75 >>>>> call_netdevice_notifiers_info+0x86/0x130 net/core/dev.c:1942 >>>>> call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] >>>>> call_netdevice_notifiers net/core/dev.c:1997 [inline] >>>>> netdev_wait_allrefs_any net/core/dev.c:10237 [inline] >>>>> netdev_run_todo+0xbc6/0x1100 net/core/dev.c:10351 >>>>> tun_detach drivers/net/tun.c:704 [inline] >>>>> tun_chr_close+0xe4/0x190 drivers/net/tun.c:3467 >>>>> __fput+0x27c/0xa90 fs/file_table.c:320 >>>>> task_work_run+0x16f/0x270 kernel/task_work.c:179 >>>>> exit_task_work include/linux/task_work.h:38 [inline] >>>>> do_exit+0xb3d/0x2a30 kernel/exit.c:820 >>>>> do_group_exit+0xd4/0x2a0 kernel/exit.c:950 >>>>> get_signal+0x21b1/0x2440 kernel/signal.c:2858 >>>>> arch_do_signal_or_restart+0x86/0x2300 arch/x86/kernel/signal.c:869 >>>>> exit_to_user_mode_loop kernel/entry/common.c:168 [inline] >>>>> exit_to_user_mode_prepare+0x15f/0x250 kernel/entry/common.c:203 >>>>> __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] >>>>> syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296 >>>>> do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86 >>>>> entry_SYSCALL_64_after_hwframe+0x63/0xcd >>>>> >>>>> The cause of the issue is that sock_put() from __tun_detach() drops >>>>> last reference count for struct net, and then notifier_call_chain() >>>>> from netdev_state_change() accesses that struct net. >>>>> >>>>> This patch fixes the issue by calling sock_put() from tun_detach() >>>>> after all necessary accesses for the struct net has done. >>>>> >>>>> Fixes: 83c1f36f9880 ("tun: send netlink notification when the device >>>>> is modified") >>>>> Reported-by: syzbot+106f9b687cd64ee70cd1@syzkaller.appspotmail.com >>>>> Link: >>>>> https://syzkaller.appspot.com/bug?id=96eb7f1ce75ef933697f24eeab928c4a716edefe >>>>> [1] >>>>> Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> >>>>> --- >>>>> v2: >>>>> - Include symbolic stack trace >>>>> - Add Fixes and Reported-by tags >>>>> v1: >>>>> https://lore.kernel.org/all/20221119075615.723290-1-syoshida@redhat.com/ >>>>> --- >>>>> drivers/net/tun.c | 6 +++++- >>>>> 1 file changed, 5 insertions(+), 1 deletion(-) >>>>> >>>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c >>>>> index 7a3ab3427369..ce9fcf4c8ef4 100644 >>>>> --- a/drivers/net/tun.c >>>>> +++ b/drivers/net/tun.c >>>>> @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, >>>>> bool clean) >>>>> if (tun) >>>>> xdp_rxq_info_unreg(&tfile->xdp_rxq); >>>>> ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); >>>>> - sock_put(&tfile->sk); >>>>> } >>>>> } >>>>> >>>>> @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, >>>>> bool clean) >>>>> if (dev) >>>>> netdev_state_change(dev); >>>>> rtnl_unlock(); >>>>> + >>>>> + if (clean) { >>>> Would you mind explaining (a comment would be nice) why this barrier >>>> is needed ? >>> I thought that tfile is accessed with rcu_lock(), so I put >>> synchronize_rcu() here. Please let me know if I misunderstand the >>> concept of rcu (I'm losing my confidence...). >>> >> Addin Jason for comments. >> >> If an RCU grace period was needed before commit 83c1f36f9880 ("tun: >> send netlink notification when the device is modified"), >> would we need another patch ? > > > I think we don't need another synchronization here. __tun_detach() has > already done the necessary synchronization when it tries to modify > tun->tfiles array and tfile->tun. Thank you so much for your comment. I'll prepare v3 patch to remove calling synchronize_rcu(). Thanks, Shigeru > Thanks > > >> >> Also sock_flag(sk, SOCK_RCU_FREE) would probably be better than adding >> a synchronize_rcu() (if again a grace period is needed) >> >> >> >>> Thanks, >>> Shigeru >>> >>>> Thanks. >>>> >>>>> + synchronize_rcu(); >>>>> + sock_put(&tfile->sk); >>>>> + } >>>>> } >>>>> >>>>> static void tun_detach_all(struct net_device *dev) >>>>> -- >>>>> 2.38.1 >>>>> >
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7a3ab3427369..ce9fcf4c8ef4 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -686,7 +686,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean) if (tun) xdp_rxq_info_unreg(&tfile->xdp_rxq); ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); - sock_put(&tfile->sk); } } @@ -702,6 +701,11 @@ static void tun_detach(struct tun_file *tfile, bool clean) if (dev) netdev_state_change(dev); rtnl_unlock(); + + if (clean) { + synchronize_rcu(); + sock_put(&tfile->sk); + } } static void tun_detach_all(struct net_device *dev)