Message ID | 20230412005013.30456-1-dinghui@sangfor.com.cn |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2966950vqo; Tue, 11 Apr 2023 18:13:06 -0700 (PDT) X-Google-Smtp-Source: AKy350a7/ZYcmgnTNeVJfJ/my14Hrz1yvL//RJwxNQ8G+GaV1Qm6P6JI9n1xBiYl56NgT8JLmJQA X-Received: by 2002:aa7:cc02:0:b0:504:71a7:1c69 with SMTP id q2-20020aa7cc02000000b0050471a71c69mr14291942edt.26.1681261986155; Tue, 11 Apr 2023 18:13:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681261986; cv=none; d=google.com; s=arc-20160816; b=qRWarLwx2UiE347q3HJVMerVDGYgpIPQXF8dOnObc3sZJ2Df+84ePZcMW0JRqcr1fU 6jCKSlvui9X2D8CFTOgCRxY6dncU92OBniF6MhZoAIwBy2niXn8qgdu+58t/F1y3AcAI B3VOnNg78EjpFih+CD1XIKtkdL9pwoiWYo54rKll4kXyESQSwBUUcqA2sJ3hDVPcEo5r Fj5e5aOyWcR1q4fzLK7f83D8dmp2Yn3379lzU3BlRCXQ4di7Hzk8P1fyQu1nytyUDva1 RRb7zH7dZDpdRkd87RL+f16yHb0AyM574R68fqe4B3fyxNT3oJZuPqbN4txlUkEgTRvR yNHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=ZfspHJCXFFeLQa1roBXYhnDqGg5EFAhxrtqJRgNy5jo=; b=i5HoxgSvDKAGqlHT7cq/yaZ98WX0T/A/zBOWjcf+AvrDynjLEocMCluNAwTYctOI7C lpqO3oskich5kz9ftQ+fzTLU9Sb9QW6vHbUCTqy5HcFfz9Fpw3wP1RE2AJFI/FINCqqI RfccA2tAa7NJFq2GT4vveleLNah0CFzjnG+zPKegglOn3HHscxCE0gBxXAm0AhSg+MmB fZCvJdBzmlM104s0LgQ3NIyGkng8ELuc5XKu18s4zIELtulV+z7kMKWwvJ5loesrxB3/ ULbJ0K6SBDpafSAzBJ3GxoNCu8DmQ/bGthAqTnplOE/TYUoRtsMnmP53+K1C3+xoq7GH Mc7Q== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=sangfor.com.cn Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g10-20020a056402114a00b00504805f54adsi2869890edw.387.2023.04.11.18.12.42; Tue, 11 Apr 2023 18:13:06 -0700 (PDT) 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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=sangfor.com.cn Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229639AbjDLBAX (ORCPT <rfc822;leviz.kernel.dev@gmail.com> + 99 others); Tue, 11 Apr 2023 21:00:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229459AbjDLBAW (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 11 Apr 2023 21:00:22 -0400 X-Greylist: delayed 570 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Tue, 11 Apr 2023 18:00:20 PDT Received: from mail-m11875.qiye.163.com (mail-m11875.qiye.163.com [115.236.118.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A1BFE73; Tue, 11 Apr 2023 18:00:20 -0700 (PDT) Received: from localhost.localdomain (unknown [IPV6:240e:3b7:3273:10b0:7023:7419:46f0:9cf3]) by mail-m11875.qiye.163.com (Hmail) with ESMTPA id 4D92E280392; Wed, 12 Apr 2023 08:50:45 +0800 (CST) From: Ding Hui <dinghui@sangfor.com.cn> To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ecree.xilinx@gmail.com, habetsm.xilinx@gmail.com Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, pengdonglin@sangfor.com.cn, huangcun@sangfor.com.cn, Ding Hui <dinghui@sangfor.com.cn> Subject: [RFC PATCH net] sfc: Fix use-after-free due to selftest_work Date: Wed, 12 Apr 2023 08:50:13 +0800 Message-Id: <20230412005013.30456-1-dinghui@sangfor.com.cn> X-Mailer: git-send-email 2.17.1 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWS1ZQUlXWQ8JGhUIEh9ZQVkZSB9OVkJIQkxDT05IGU1KSVUTARMWGhIXJBQOD1 lXWRgSC1lBWUlPSx5BSBlMQUhJTEhBSksZS0FMS0lIQUxPSkJBT00dS0FCGB1IWVdZFhoPEhUdFF lBWU9LSFVKSktISkNVSktLVUtZBg++ X-HM-Tid: 0a8772f18d0d2eb1kusn4d92e280392 X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6NCo6FDo5KT0VOCgNNhkNSSoT Lw4aFAhVSlVKTUNKSU1LTU9NSklIVTMWGhIXVR8SFRwTDhI7CBoVHB0UCVUYFBZVGBVFWVdZEgtZ QVlJT0seQUgZTEFISUxIQUpLGUtBTEtJSEFMT0pCQU9NHUtBQhgdSFlXWQgBWUFIQkNINwY+ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS 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?1762930968307343266?= X-GMAIL-MSGID: =?utf-8?q?1762930968307343266?= |
Series |
[RFC,net] sfc: Fix use-after-free due to selftest_work
|
|
Commit Message
Ding Hui
April 12, 2023, 12:50 a.m. UTC
There is a use-after-free scenario that is:
When netif_running() is false, user set mac address or vlan tag to VF,
the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop()
and efx_net_open(), since netif_running() is false, the port will not
start and keep port_enabled false, but selftest_worker is scheduled
in efx_net_open().
If we remove the device before selftest_worker run, the efx is freed,
then we will get a UAF in run_timer_softirq() like this:
[ 1178.907941] ==================================================================
[ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90
[ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0
[ 1178.907950]
[ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1
[ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022
[ 1178.907955] Call Trace:
[ 1178.907956] <IRQ>
[ 1178.907960] dump_stack+0x71/0xab
[ 1178.907963] print_address_description+0x6b/0x290
[ 1178.907965] ? run_timer_softirq+0xdea/0xe90
[ 1178.907967] kasan_report+0x14a/0x2b0
[ 1178.907968] run_timer_softirq+0xdea/0xe90
[ 1178.907971] ? init_timer_key+0x170/0x170
[ 1178.907973] ? hrtimer_cancel+0x20/0x20
[ 1178.907976] ? sched_clock+0x5/0x10
[ 1178.907978] ? sched_clock_cpu+0x18/0x170
[ 1178.907981] __do_softirq+0x1c8/0x5fa
[ 1178.907985] irq_exit+0x213/0x240
[ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330
[ 1178.907989] apic_timer_interrupt+0xf/0x20
[ 1178.907990] </IRQ>
[ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370
I am thinking about several ways to fix the issue:
[1] In this RFC, I cancel the selftest_worker unconditionally in
efx_pci_remove().
[2] Add a test condition, only invoke efx_selftest_async_start() when
efx->port_enabled is true in efx_net_open().
[3] Move invoking efx_selftest_async_start() from efx_net_open() to
efx_start_all() or efx_start_port(), that matching cancel action in
efx_stop_port().
[4] However, I also notice that in efx_ef10_set_mac_address(), the
efx_net_open() depends on original port_enabled, but others are not,
if we change all efx_net_open() depends on old state like
efx_ef10_set_mac_address() does, the UAF can also be fixed in theory.
But I'm not sure which is better, is there any suggestions? Thanks.
Signed-off-by: Ding Hui <dinghui@sangfor.com.cn>
---
drivers/net/ethernet/sfc/efx.c | 2 ++
1 file changed, 2 insertions(+)
Comments
On 4/11/2023 5:50 PM, Ding Hui wrote: > There is a use-after-free scenario that is: > > When netif_running() is false, user set mac address or vlan tag to VF, > the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() > and efx_net_open(), since netif_running() is false, the port will not > start and keep port_enabled false, but selftest_worker is scheduled > in efx_net_open(). > > If we remove the device before selftest_worker run, the efx is freed, > then we will get a UAF in run_timer_softirq() like this: > > [ 1178.907941] ================================================================== > [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 > [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 > [ 1178.907950] > [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 > [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 > [ 1178.907955] Call Trace: > [ 1178.907956] <IRQ> > [ 1178.907960] dump_stack+0x71/0xab > [ 1178.907963] print_address_description+0x6b/0x290 > [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 > [ 1178.907967] kasan_report+0x14a/0x2b0 > [ 1178.907968] run_timer_softirq+0xdea/0xe90 > [ 1178.907971] ? init_timer_key+0x170/0x170 > [ 1178.907973] ? hrtimer_cancel+0x20/0x20 > [ 1178.907976] ? sched_clock+0x5/0x10 > [ 1178.907978] ? sched_clock_cpu+0x18/0x170 > [ 1178.907981] __do_softirq+0x1c8/0x5fa > [ 1178.907985] irq_exit+0x213/0x240 > [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 > [ 1178.907989] apic_timer_interrupt+0xf/0x20 > [ 1178.907990] </IRQ> > [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 > > I am thinking about several ways to fix the issue: > > [1] In this RFC, I cancel the selftest_worker unconditionally in > efx_pci_remove(). > > [2] Add a test condition, only invoke efx_selftest_async_start() when > efx->port_enabled is true in efx_net_open(). > > [3] Move invoking efx_selftest_async_start() from efx_net_open() to > efx_start_all() or efx_start_port(), that matching cancel action in > efx_stop_port(). > > [4] However, I also notice that in efx_ef10_set_mac_address(), the > efx_net_open() depends on original port_enabled, but others are not, > if we change all efx_net_open() depends on old state like > efx_ef10_set_mac_address() does, the UAF can also be fixed in theory. > > But I'm not sure which is better, is there any suggestions? Thanks. > I think this fix makes the most sense to me. > Signed-off-by: Ding Hui <dinghui@sangfor.com.cn> > --- net patches need a Fixes tag indicating what commit this fixes. This being RFC is likely why that was left off? > drivers/net/ethernet/sfc/efx.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c > index 884d8d168862..dd0b2363eed1 100644 > --- a/drivers/net/ethernet/sfc/efx.c > +++ b/drivers/net/ethernet/sfc/efx.c > @@ -876,6 +876,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) > efx->state = STATE_UNINIT; > rtnl_unlock(); > > + efx_selftest_async_cancel(efx); > + > if (efx->type->sriov_fini) > efx->type->sriov_fini(efx); >
On 2023/4/13 6:34, Jacob Keller wrote: > > > On 4/11/2023 5:50 PM, Ding Hui wrote: >> There is a use-after-free scenario that is: >> >> When netif_running() is false, user set mac address or vlan tag to VF, >> the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() >> and efx_net_open(), since netif_running() is false, the port will not >> start and keep port_enabled false, but selftest_worker is scheduled >> in efx_net_open(). >> >> If we remove the device before selftest_worker run, the efx is freed, >> then we will get a UAF in run_timer_softirq() like this: >> >> [ 1178.907941] ================================================================== >> [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 >> [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 >> [ 1178.907950] >> [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 >> [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 >> [ 1178.907955] Call Trace: >> [ 1178.907956] <IRQ> >> [ 1178.907960] dump_stack+0x71/0xab >> [ 1178.907963] print_address_description+0x6b/0x290 >> [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 >> [ 1178.907967] kasan_report+0x14a/0x2b0 >> [ 1178.907968] run_timer_softirq+0xdea/0xe90 >> [ 1178.907971] ? init_timer_key+0x170/0x170 >> [ 1178.907973] ? hrtimer_cancel+0x20/0x20 >> [ 1178.907976] ? sched_clock+0x5/0x10 >> [ 1178.907978] ? sched_clock_cpu+0x18/0x170 >> [ 1178.907981] __do_softirq+0x1c8/0x5fa >> [ 1178.907985] irq_exit+0x213/0x240 >> [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 >> [ 1178.907989] apic_timer_interrupt+0xf/0x20 >> [ 1178.907990] </IRQ> >> [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 >> >> I am thinking about several ways to fix the issue: >> >> [1] In this RFC, I cancel the selftest_worker unconditionally in >> efx_pci_remove(). >> >> [2] Add a test condition, only invoke efx_selftest_async_start() when >> efx->port_enabled is true in efx_net_open(). >> >> [3] Move invoking efx_selftest_async_start() from efx_net_open() to >> efx_start_all() or efx_start_port(), that matching cancel action in >> efx_stop_port(). >> >> [4] However, I also notice that in efx_ef10_set_mac_address(), the >> efx_net_open() depends on original port_enabled, but others are not, >> if we change all efx_net_open() depends on old state like >> efx_ef10_set_mac_address() does, the UAF can also be fixed in theory. >> >> But I'm not sure which is better, is there any suggestions? Thanks. >> > > I think this fix makes the most sense to me. > >> Signed-off-by: Ding Hui <dinghui@sangfor.com.cn> >> --- > > net patches need a Fixes tag indicating what commit this fixes. This > being RFC is likely why that was left off? > Thanks. The commit dd40781e3a4e ("sfc: Run event/IRQ self-test asynchronously when interface is brought up") add efx_selftest_async_start() into efx_net_open(), it was okay then since efx_net_open() was only invoked by the callback. Base on the original purpose of this commit, the way [2][3] makes sense. The commit e340be923012 ("sfc: add ndo_set_vf_mac() function for EF10") first add efx_ef10_sriov_set_vf_mac(), it invoke efx_net_open(), then this UAF scenario started. I'll remove RFC and add Fixes in v2. Fixes: e340be923012 ("sfc: add ndo_set_vf_mac() function for EF10") >> drivers/net/ethernet/sfc/efx.c | 2 ++ >> 1 file changed, 2 insertions(+) >> >> diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c >> index 884d8d168862..dd0b2363eed1 100644 >> --- a/drivers/net/ethernet/sfc/efx.c >> +++ b/drivers/net/ethernet/sfc/efx.c >> @@ -876,6 +876,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) >> efx->state = STATE_UNINIT; >> rtnl_unlock(); >> >> + efx_selftest_async_cancel(efx); >> + >> if (efx->type->sriov_fini) >> efx->type->sriov_fini(efx); >> >
On Wed, Apr 12, 2023 at 08:50:13AM +0800, Ding Hui wrote: > There is a use-after-free scenario that is: > > When netif_running() is false, user set mac address or vlan tag to VF, > the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() > and efx_net_open(), since netif_running() is false, the port will not > start and keep port_enabled false, but selftest_worker is scheduled > in efx_net_open(). > > If we remove the device before selftest_worker run, the efx is freed, > then we will get a UAF in run_timer_softirq() like this: > > [ 1178.907941] ================================================================== > [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 > [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 > [ 1178.907950] > [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 > [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 > [ 1178.907955] Call Trace: > [ 1178.907956] <IRQ> > [ 1178.907960] dump_stack+0x71/0xab > [ 1178.907963] print_address_description+0x6b/0x290 > [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 > [ 1178.907967] kasan_report+0x14a/0x2b0 > [ 1178.907968] run_timer_softirq+0xdea/0xe90 > [ 1178.907971] ? init_timer_key+0x170/0x170 > [ 1178.907973] ? hrtimer_cancel+0x20/0x20 > [ 1178.907976] ? sched_clock+0x5/0x10 > [ 1178.907978] ? sched_clock_cpu+0x18/0x170 > [ 1178.907981] __do_softirq+0x1c8/0x5fa > [ 1178.907985] irq_exit+0x213/0x240 > [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 > [ 1178.907989] apic_timer_interrupt+0xf/0x20 > [ 1178.907990] </IRQ> > [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 > > I am thinking about several ways to fix the issue: > > [1] In this RFC, I cancel the selftest_worker unconditionally in > efx_pci_remove(). > > [2] Add a test condition, only invoke efx_selftest_async_start() when > efx->port_enabled is true in efx_net_open(). > > [3] Move invoking efx_selftest_async_start() from efx_net_open() to > efx_start_all() or efx_start_port(), that matching cancel action in > efx_stop_port(). I think moving this to efx_start_port() is best, as you say to match the cancel in efx_stop_port(). Thanks, Martin > > [4] However, I also notice that in efx_ef10_set_mac_address(), the > efx_net_open() depends on original port_enabled, but others are not, > if we change all efx_net_open() depends on old state like > efx_ef10_set_mac_address() does, the UAF can also be fixed in theory. > > But I'm not sure which is better, is there any suggestions? Thanks. > > Signed-off-by: Ding Hui <dinghui@sangfor.com.cn> > --- > drivers/net/ethernet/sfc/efx.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c > index 884d8d168862..dd0b2363eed1 100644 > --- a/drivers/net/ethernet/sfc/efx.c > +++ b/drivers/net/ethernet/sfc/efx.c > @@ -876,6 +876,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) > efx->state = STATE_UNINIT; > rtnl_unlock(); > > + efx_selftest_async_cancel(efx); > + > if (efx->type->sriov_fini) > efx->type->sriov_fini(efx); > > -- > 2.17.1
On Wed, Apr 12, 2023 at 03:34:51PM -0700, Jacob Keller wrote: > > > On 4/11/2023 5:50 PM, Ding Hui wrote: > > There is a use-after-free scenario that is: > > > > When netif_running() is false, user set mac address or vlan tag to VF, > > the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() > > and efx_net_open(), since netif_running() is false, the port will not > > start and keep port_enabled false, but selftest_worker is scheduled > > in efx_net_open(). > > > > If we remove the device before selftest_worker run, the efx is freed, > > then we will get a UAF in run_timer_softirq() like this: > > > > [ 1178.907941] ================================================================== > > [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 > > [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 > > [ 1178.907950] > > [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 > > [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 > > [ 1178.907955] Call Trace: > > [ 1178.907956] <IRQ> > > [ 1178.907960] dump_stack+0x71/0xab > > [ 1178.907963] print_address_description+0x6b/0x290 > > [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 > > [ 1178.907967] kasan_report+0x14a/0x2b0 > > [ 1178.907968] run_timer_softirq+0xdea/0xe90 > > [ 1178.907971] ? init_timer_key+0x170/0x170 > > [ 1178.907973] ? hrtimer_cancel+0x20/0x20 > > [ 1178.907976] ? sched_clock+0x5/0x10 > > [ 1178.907978] ? sched_clock_cpu+0x18/0x170 > > [ 1178.907981] __do_softirq+0x1c8/0x5fa > > [ 1178.907985] irq_exit+0x213/0x240 > > [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 > > [ 1178.907989] apic_timer_interrupt+0xf/0x20 > > [ 1178.907990] </IRQ> > > [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 > > > > I am thinking about several ways to fix the issue: > > > > [1] In this RFC, I cancel the selftest_worker unconditionally in > > efx_pci_remove(). > > > > [2] Add a test condition, only invoke efx_selftest_async_start() when > > efx->port_enabled is true in efx_net_open(). > > > > [3] Move invoking efx_selftest_async_start() from efx_net_open() to > > efx_start_all() or efx_start_port(), that matching cancel action in > > efx_stop_port(). > > > > [4] However, I also notice that in efx_ef10_set_mac_address(), the > > efx_net_open() depends on original port_enabled, but others are not, > > if we change all efx_net_open() depends on old state like > > efx_ef10_set_mac_address() does, the UAF can also be fixed in theory. > > > > But I'm not sure which is better, is there any suggestions? Thanks. > > > > I think this fix makes the most sense to me. For me this is too late. It leaves a gap where the selftest timer is still running but the NIC has already stopped sending events. So we could still get a failure "channel %d timed out waiting for event queue" from the selftest. Martin > > > Signed-off-by: Ding Hui <dinghui@sangfor.com.cn> > > --- > > net patches need a Fixes tag indicating what commit this fixes. This > being RFC is likely why that was left off? > > > drivers/net/ethernet/sfc/efx.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c > > index 884d8d168862..dd0b2363eed1 100644 > > --- a/drivers/net/ethernet/sfc/efx.c > > +++ b/drivers/net/ethernet/sfc/efx.c > > @@ -876,6 +876,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) > > efx->state = STATE_UNINIT; > > rtnl_unlock(); > > > > + efx_selftest_async_cancel(efx); > > + > > if (efx->type->sriov_fini) > > efx->type->sriov_fini(efx); > >
On 2023/4/13 15:52, Martin Habets wrote: > On Wed, Apr 12, 2023 at 03:34:51PM -0700, Jacob Keller wrote: >> >> >> On 4/11/2023 5:50 PM, Ding Hui wrote: >>> There is a use-after-free scenario that is: >>> >>> When netif_running() is false, user set mac address or vlan tag to VF, >>> the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() >>> and efx_net_open(), since netif_running() is false, the port will not >>> start and keep port_enabled false, but selftest_worker is scheduled >>> in efx_net_open(). >>> >>> If we remove the device before selftest_worker run, the efx is freed, >>> then we will get a UAF in run_timer_softirq() like this: >>> >>> [ 1178.907941] ================================================================== >>> [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 >>> [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 >>> [ 1178.907950] >>> [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 >>> [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 >>> [ 1178.907955] Call Trace: >>> [ 1178.907956] <IRQ> >>> [ 1178.907960] dump_stack+0x71/0xab >>> [ 1178.907963] print_address_description+0x6b/0x290 >>> [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 >>> [ 1178.907967] kasan_report+0x14a/0x2b0 >>> [ 1178.907968] run_timer_softirq+0xdea/0xe90 >>> [ 1178.907971] ? init_timer_key+0x170/0x170 >>> [ 1178.907973] ? hrtimer_cancel+0x20/0x20 >>> [ 1178.907976] ? sched_clock+0x5/0x10 >>> [ 1178.907978] ? sched_clock_cpu+0x18/0x170 >>> [ 1178.907981] __do_softirq+0x1c8/0x5fa >>> [ 1178.907985] irq_exit+0x213/0x240 >>> [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 >>> [ 1178.907989] apic_timer_interrupt+0xf/0x20 >>> [ 1178.907990] </IRQ> >>> [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 >>> >>> I am thinking about several ways to fix the issue: >>> >>> [1] In this RFC, I cancel the selftest_worker unconditionally in >>> efx_pci_remove(). >>> >>> [2] Add a test condition, only invoke efx_selftest_async_start() when >>> efx->port_enabled is true in efx_net_open(). >>> >>> [3] Move invoking efx_selftest_async_start() from efx_net_open() to >>> efx_start_all() or efx_start_port(), that matching cancel action in >>> efx_stop_port(). >>> >>> [4] However, I also notice that in efx_ef10_set_mac_address(), the >>> efx_net_open() depends on original port_enabled, but others are not, >>> if we change all efx_net_open() depends on old state like >>> efx_ef10_set_mac_address() does, the UAF can also be fixed in theory. >>> >>> But I'm not sure which is better, is there any suggestions? Thanks. >>> >> >> I think this fix makes the most sense to me. > > For me this is too late. It leaves a gap where the selftest timer is still running > but the NIC has already stopped sending events. So we could still get a > failure "channel %d timed out waiting for event queue" from the selftest. > Yes, assuming not consider removing, scheduled selftest_work if NIC not brought up actually, we will also get this failure log.
On 2023/4/13 15:37, Martin Habets wrote: > On Wed, Apr 12, 2023 at 08:50:13AM +0800, Ding Hui wrote: >> There is a use-after-free scenario that is: >> >> When netif_running() is false, user set mac address or vlan tag to VF, >> the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() >> and efx_net_open(), since netif_running() is false, the port will not >> start and keep port_enabled false, but selftest_worker is scheduled >> in efx_net_open(). >> >> If we remove the device before selftest_worker run, the efx is freed, >> then we will get a UAF in run_timer_softirq() like this: >> >> [ 1178.907941] ================================================================== >> [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 >> [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 >> [ 1178.907950] >> [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 >> [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 >> [ 1178.907955] Call Trace: >> [ 1178.907956] <IRQ> >> [ 1178.907960] dump_stack+0x71/0xab >> [ 1178.907963] print_address_description+0x6b/0x290 >> [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 >> [ 1178.907967] kasan_report+0x14a/0x2b0 >> [ 1178.907968] run_timer_softirq+0xdea/0xe90 >> [ 1178.907971] ? init_timer_key+0x170/0x170 >> [ 1178.907973] ? hrtimer_cancel+0x20/0x20 >> [ 1178.907976] ? sched_clock+0x5/0x10 >> [ 1178.907978] ? sched_clock_cpu+0x18/0x170 >> [ 1178.907981] __do_softirq+0x1c8/0x5fa >> [ 1178.907985] irq_exit+0x213/0x240 >> [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 >> [ 1178.907989] apic_timer_interrupt+0xf/0x20 >> [ 1178.907990] </IRQ> >> [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 >> >> I am thinking about several ways to fix the issue: >> >> [1] In this RFC, I cancel the selftest_worker unconditionally in >> efx_pci_remove(). >> >> [2] Add a test condition, only invoke efx_selftest_async_start() when >> efx->port_enabled is true in efx_net_open(). >> >> [3] Move invoking efx_selftest_async_start() from efx_net_open() to >> efx_start_all() or efx_start_port(), that matching cancel action in >> efx_stop_port(). > > I think moving this to efx_start_port() is best, as you say to match > the cancel in efx_stop_port(). > If moving to efx_start_port(), should we worry about that IRQ_TIMEOUT is still enough? I'm not sure if there is a long time waiting from starting of schedule selftest_work to the ending of efx_net_open().
On Thu, Apr 13, 2023 at 04:35:08PM +0800, Ding Hui wrote: > On 2023/4/13 15:37, Martin Habets wrote: > > On Wed, Apr 12, 2023 at 08:50:13AM +0800, Ding Hui wrote: > > > There is a use-after-free scenario that is: > > > > > > When netif_running() is false, user set mac address or vlan tag to VF, > > > the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() > > > and efx_net_open(), since netif_running() is false, the port will not > > > start and keep port_enabled false, but selftest_worker is scheduled > > > in efx_net_open(). > > > > > > If we remove the device before selftest_worker run, the efx is freed, > > > then we will get a UAF in run_timer_softirq() like this: > > > > > > [ 1178.907941] ================================================================== > > > [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 > > > [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 > > > [ 1178.907950] > > > [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 > > > [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 > > > [ 1178.907955] Call Trace: > > > [ 1178.907956] <IRQ> > > > [ 1178.907960] dump_stack+0x71/0xab > > > [ 1178.907963] print_address_description+0x6b/0x290 > > > [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 > > > [ 1178.907967] kasan_report+0x14a/0x2b0 > > > [ 1178.907968] run_timer_softirq+0xdea/0xe90 > > > [ 1178.907971] ? init_timer_key+0x170/0x170 > > > [ 1178.907973] ? hrtimer_cancel+0x20/0x20 > > > [ 1178.907976] ? sched_clock+0x5/0x10 > > > [ 1178.907978] ? sched_clock_cpu+0x18/0x170 > > > [ 1178.907981] __do_softirq+0x1c8/0x5fa > > > [ 1178.907985] irq_exit+0x213/0x240 > > > [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 > > > [ 1178.907989] apic_timer_interrupt+0xf/0x20 > > > [ 1178.907990] </IRQ> > > > [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 > > > > > > I am thinking about several ways to fix the issue: > > > > > > [1] In this RFC, I cancel the selftest_worker unconditionally in > > > efx_pci_remove(). > > > > > > [2] Add a test condition, only invoke efx_selftest_async_start() when > > > efx->port_enabled is true in efx_net_open(). > > > > > > [3] Move invoking efx_selftest_async_start() from efx_net_open() to > > > efx_start_all() or efx_start_port(), that matching cancel action in > > > efx_stop_port(). > > > > I think moving this to efx_start_port() is best, as you say to match > > the cancel in efx_stop_port(). > > > > If moving to efx_start_port(), should we worry about that IRQ_TIMEOUT > is still enough? 1 second is a long time for a machine running code, so it does not worry me. > I'm not sure if there is a long time waiting from starting of schedule > selftest_work to the ending of efx_net_open(). I see your point. Looking at efx_start_all() there is the call to efx_start_datapath() after the call to efx_net_open(), which takes a relatively long time (well under 200ms though). Logically it would be better to move efx_selftest_async_start() after this call. What do you think? The point here is that efx_start_all() calls efx_start_port() early, and efx_stop_all() also calls efx_stop_port() early. The calling sequence is correct but they are not the strict inverse of each other. Martin > > -- > Thanks, > - Ding Hui
On 2023/4/14 17:44, Martin Habets wrote: > On Thu, Apr 13, 2023 at 04:35:08PM +0800, Ding Hui wrote: >> On 2023/4/13 15:37, Martin Habets wrote: >>> On Wed, Apr 12, 2023 at 08:50:13AM +0800, Ding Hui wrote: >>>> There is a use-after-free scenario that is: >>>> >>>> When netif_running() is false, user set mac address or vlan tag to VF, >>>> the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() >>>> and efx_net_open(), since netif_running() is false, the port will not >>>> start and keep port_enabled false, but selftest_worker is scheduled >>>> in efx_net_open(). >>>> >>>> If we remove the device before selftest_worker run, the efx is freed, >>>> then we will get a UAF in run_timer_softirq() like this: >>>> >>>> [ 1178.907941] ================================================================== >>>> [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 >>>> [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 >>>> [ 1178.907950] >>>> [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 >>>> [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 >>>> [ 1178.907955] Call Trace: >>>> [ 1178.907956] <IRQ> >>>> [ 1178.907960] dump_stack+0x71/0xab >>>> [ 1178.907963] print_address_description+0x6b/0x290 >>>> [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 >>>> [ 1178.907967] kasan_report+0x14a/0x2b0 >>>> [ 1178.907968] run_timer_softirq+0xdea/0xe90 >>>> [ 1178.907971] ? init_timer_key+0x170/0x170 >>>> [ 1178.907973] ? hrtimer_cancel+0x20/0x20 >>>> [ 1178.907976] ? sched_clock+0x5/0x10 >>>> [ 1178.907978] ? sched_clock_cpu+0x18/0x170 >>>> [ 1178.907981] __do_softirq+0x1c8/0x5fa >>>> [ 1178.907985] irq_exit+0x213/0x240 >>>> [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 >>>> [ 1178.907989] apic_timer_interrupt+0xf/0x20 >>>> [ 1178.907990] </IRQ> >>>> [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 >>>> >>>> I am thinking about several ways to fix the issue: >>>> >>>> [1] In this RFC, I cancel the selftest_worker unconditionally in >>>> efx_pci_remove(). >>>> >>>> [2] Add a test condition, only invoke efx_selftest_async_start() when >>>> efx->port_enabled is true in efx_net_open(). >>>> >>>> [3] Move invoking efx_selftest_async_start() from efx_net_open() to >>>> efx_start_all() or efx_start_port(), that matching cancel action in >>>> efx_stop_port(). >>> >>> I think moving this to efx_start_port() is best, as you say to match >>> the cancel in efx_stop_port(). >>> >> >> If moving to efx_start_port(), should we worry about that IRQ_TIMEOUT >> is still enough? > > 1 second is a long time for a machine running code, so it does not worry me. > >> I'm not sure if there is a long time waiting from starting of schedule >> selftest_work to the ending of efx_net_open(). > > I see your point. Looking at efx_start_all() there is the call to > efx_start_datapath() after the call to efx_net_open(), which takes a ^^^^^^^^^^^^ Do you mean efx_start_port()? > relatively long time (well under 200ms though). > Logically it would be better to move efx_selftest_async_start() after this > call. What do you think? Agree with you. > The point here is that efx_start_all() calls efx_start_port() early, and > efx_stop_all() also calls efx_stop_port() early. The calling sequence is > correct but they are not the strict inverse of each other. > Yeah, that is what I noticed monitor_work does. Then I'll move efx_selftest_async_start() into efx_start_all(), follows the monitor_work.
On Fri, Apr 14, 2023 at 07:03:41PM +0800, Ding Hui wrote: > On 2023/4/14 17:44, Martin Habets wrote: > > On Thu, Apr 13, 2023 at 04:35:08PM +0800, Ding Hui wrote: > > > On 2023/4/13 15:37, Martin Habets wrote: > > > > On Wed, Apr 12, 2023 at 08:50:13AM +0800, Ding Hui wrote: > > > > > There is a use-after-free scenario that is: > > > > > > > > > > When netif_running() is false, user set mac address or vlan tag to VF, > > > > > the xxx_set_vf_mac() or xxx_set_vf_vlan() will invoke efx_net_stop() > > > > > and efx_net_open(), since netif_running() is false, the port will not > > > > > start and keep port_enabled false, but selftest_worker is scheduled > > > > > in efx_net_open(). > > > > > > > > > > If we remove the device before selftest_worker run, the efx is freed, > > > > > then we will get a UAF in run_timer_softirq() like this: > > > > > > > > > > [ 1178.907941] ================================================================== > > > > > [ 1178.907948] BUG: KASAN: use-after-free in run_timer_softirq+0xdea/0xe90 > > > > > [ 1178.907950] Write of size 8 at addr ff11001f449cdc80 by task swapper/47/0 > > > > > [ 1178.907950] > > > > > [ 1178.907953] CPU: 47 PID: 0 Comm: swapper/47 Kdump: loaded Tainted: G O --------- -t - 4.18.0 #1 > > > > > [ 1178.907954] Hardware name: SANGFOR X620G40/WI2HG-208T1061A, BIOS SPYH051032-U01 04/01/2022 > > > > > [ 1178.907955] Call Trace: > > > > > [ 1178.907956] <IRQ> > > > > > [ 1178.907960] dump_stack+0x71/0xab > > > > > [ 1178.907963] print_address_description+0x6b/0x290 > > > > > [ 1178.907965] ? run_timer_softirq+0xdea/0xe90 > > > > > [ 1178.907967] kasan_report+0x14a/0x2b0 > > > > > [ 1178.907968] run_timer_softirq+0xdea/0xe90 > > > > > [ 1178.907971] ? init_timer_key+0x170/0x170 > > > > > [ 1178.907973] ? hrtimer_cancel+0x20/0x20 > > > > > [ 1178.907976] ? sched_clock+0x5/0x10 > > > > > [ 1178.907978] ? sched_clock_cpu+0x18/0x170 > > > > > [ 1178.907981] __do_softirq+0x1c8/0x5fa > > > > > [ 1178.907985] irq_exit+0x213/0x240 > > > > > [ 1178.907987] smp_apic_timer_interrupt+0xd0/0x330 > > > > > [ 1178.907989] apic_timer_interrupt+0xf/0x20 > > > > > [ 1178.907990] </IRQ> > > > > > [ 1178.907991] RIP: 0010:mwait_idle+0xae/0x370 > > > > > > > > > > I am thinking about several ways to fix the issue: > > > > > > > > > > [1] In this RFC, I cancel the selftest_worker unconditionally in > > > > > efx_pci_remove(). > > > > > > > > > > [2] Add a test condition, only invoke efx_selftest_async_start() when > > > > > efx->port_enabled is true in efx_net_open(). > > > > > > > > > > [3] Move invoking efx_selftest_async_start() from efx_net_open() to > > > > > efx_start_all() or efx_start_port(), that matching cancel action in > > > > > efx_stop_port(). > > > > > > > > I think moving this to efx_start_port() is best, as you say to match > > > > the cancel in efx_stop_port(). > > > > > > > > > > If moving to efx_start_port(), should we worry about that IRQ_TIMEOUT > > > is still enough? > > > > 1 second is a long time for a machine running code, so it does not worry me. > > > > > I'm not sure if there is a long time waiting from starting of schedule > > > selftest_work to the ending of efx_net_open(). > > > > I see your point. Looking at efx_start_all() there is the call to > > efx_start_datapath() after the call to efx_net_open(), which takes a > ^^^^^^^^^^^^ > Do you mean efx_start_port()? Woops, yes that what I meant. > > relatively long time (well under 200ms though). > > Logically it would be better to move efx_selftest_async_start() after this > > call. What do you think? > > Agree with you. > > > The point here is that efx_start_all() calls efx_start_port() early, and > > efx_stop_all() also calls efx_stop_port() early. The calling sequence is > > correct but they are not the strict inverse of each other. > > > > Yeah, that is what I noticed monitor_work does. > Then I'll move efx_selftest_async_start() into efx_start_all(), follows > the monitor_work. Sounds good. Thanks, Martin > -- > Thanks, > - Ding Hui
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 884d8d168862..dd0b2363eed1 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -876,6 +876,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx->state = STATE_UNINIT; rtnl_unlock(); + efx_selftest_async_cancel(efx); + if (efx->type->sriov_fini) efx->type->sriov_fini(efx);