From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f66.google.com (mail-pj1-f66.google.com [209.85.216.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E4A86357CE4 for ; Fri, 15 May 2026 05:05:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.66 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778821531; cv=none; b=fBqCqjAFUoOIzE6jA7vkBMM1UW/A+2Ikcawop+xsKltBL+ayYebq6NUmInnaIUN+BLgOPskN7ek/Ob1gGf6YFglpj4HzhOJAroLxh6TrhUPQPtrLYhRW0DePWX4VI7mvJ9iS7MYP7wj9PKTgDCZB3XQ1Lp2xHd0EY763HCDRRA8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778821531; c=relaxed/simple; bh=jekx5lE2mdrCcppdU6M6DAKIW6FzIJoRBoEUNcts1dQ=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=WFqEImizu1ZGsEBQcQ1fIlm5Gxufj3zTgZpByKQDNBYEACab5Lqmp+f0hRKz/1ToHqcSKFjT3/Vjk4U6W4U2+StQ1MKe5bSv9k+wSPO4kZ8D/sz7XTEne0CvgV+VLszw2+tT/ObNcwzfATIpu3mIJ4oJQTfwnCb6vzlS6v3URs0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YA1cU1jG; arc=none smtp.client-ip=209.85.216.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YA1cU1jG" Received: by mail-pj1-f66.google.com with SMTP id 98e67ed59e1d1-367cbac9c37so4619887a91.2 for ; Thu, 14 May 2026 22:05:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778821528; x=1779426328; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=mRMHbhwrF0T6A/xFTOvfROoIDN2E/QbJJf71F9Y5tjg=; b=YA1cU1jGz5uodXGhq1VgdUEUu0GagNQUr+JmioewTjPeH8I+1IQUMsQofXsDJ4vXrs ndnJlgZiJFSHuawl2rmQq+9O+7Ad4ceyeBIByd2P63FYHEOWD1F9vOcWmkHtnYzvnzdZ qnznp7ushqYbRhdsbtQBhpnnkKpV5QdHOOwQ1HVqnXmVfUCfg2Wb+tIDLSfgmiGVZaqf 2nflF2rUti3VzxQYruJqF6CuovdA/DHuxBO5Qo9VjC3DpwgpeiTB/qVIpJxV0sgSWOcc w3P2q41eaM+3O6w5Q+frmnwi/fyQ72gmw1IfaF75CpopgYUerXFcvoVZq5dS4AFkrioI 8Q7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778821528; x=1779426328; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=mRMHbhwrF0T6A/xFTOvfROoIDN2E/QbJJf71F9Y5tjg=; b=DJUnfMPAxZMbyLsEtd46FvL7EjP7LrKAT4dKNM7Z5714CeONmN/9z8sQmLGZcrnH49 MOVQrnhxW8c0JyvUsKUiGIM2D+36hpdZWpncn4sxp0vJt0p87q5XDz+U8Cv9gn6nz5v8 im9hoElZvmVYWg4RPXKgUv0EM8cz5+zOpkmoZesApkVaWPwq1+Hf7F6BeVIWYANa86OO VVb5xqag7s4cMYShTN6KXrm8xgioZ196a7oMRpTO+NHild5eaJocoj9E1mahKPYrwGFA a+W4WyyIyZ4kzUA52vzPJdY8O+Dr9KVvLtzwDUANjIpby8MnkdNU7Cts+HgHYC8qkP/K 2Fdg== X-Forwarded-Encrypted: i=1; AFNElJ/74R9LVcp4CzbwUoMB/eV4TOGcO4KLttfA2QQqVctAbngmDXD4+PMSTy/81Ew8IEL/Y4WNFSidCOA/z4g=@vger.kernel.org X-Gm-Message-State: AOJu0YyZW4R/LG90EAk2UAi0pvNaWUBVoWLtVBbTwiuh8YsnE1/tOGs3 FK9hl8FgoZgJzBLG+FCHHkT5DDsMT7Cq4i2zryRWNKrnlPsFCj8NgVfE X-Gm-Gg: Acq92OG6RNC+UuFQRDq9BWGVXgr6REuf/tJOA0ZtWLAJFj+qIs7h1VEty7kC5GgfCvI uJroo2wXW7D186vbbsINGl+64tAu5/3RTF2Mb8K20nXsJ39TxHR+mlOC2zMQJA5YnOya2L0cGe5 W0LK8QqO5p0TOCkvaKRpf/T9HtTFWmLttLzNMKXIcP8JxWDIch2NV/d2EDqS/Rle0jXJbqb1ikP lV+DShC9nu0YewD1u/8GF6lUdB6j0lrVoXAKd1gSQdAc2tLqKpR17H1rc24qWM7JKu+Fi1Qs5rC 3zHM3oNcqqlmhzGex7ucyVtD1kxl4ZA2ywg9ibL2UdPGy2rgEescOklNh2CPTBpCHk4e86wBvSw oHPfqWjDGPCRp+WBdnOy+VYqeN5G0+hyl7TGQ0YAD0ZYzua/WvxPtpwBgUtrikUeEmmrzFmI38u sRdq13Bk7qmO06Vc9mu42Qv/T5mWZbZIblgvDNojMr3w== X-Received: by 2002:a17:90b:3505:b0:366:aba:4c86 with SMTP id 98e67ed59e1d1-36951dd5abemr2320416a91.27.1778821528123; Thu, 14 May 2026 22:05:28 -0700 (PDT) Received: from localhost ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-369515895d2sm1318167a91.8.2026.05.14.22.05.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 May 2026 22:05:27 -0700 (PDT) From: Zhang Cen To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, zerocling0077@gmail.com, 2045gemini@gmail.com, Zhang Cen Subject: [PATCH] netpoll: normalize skb->dev to the netpoll device Date: Fri, 15 May 2026 13:05:11 +0800 Message-Id: <20260515050511.106309-1-rollkingzzc@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit __netpoll_send_skb() always transmits through np->dev and queues busy packets on np->dev->npinfo->txq, but it leaves skb->dev unchanged. Stacked callers such as DSA and macvlan can reach netpoll with skb->dev still naming the upper device while np->dev is the lower device that owns the netpoll state. If the skb has to be deferred, queue_process() later dequeues it from the lower device's txq but retries it through skb->dev. That can re-enter the upper ndo_start_xmit path on an already transformed skb, and if the upper device disappears before the lower txq drains the workqueue can dereference a stale skb->dev pointer. The buggy scenario involves two paths, with each column showing the order within that path: path A label: netpoll enqueue path path B label: upper-device teardown 1. A stacked ndo_start_xmit calls 1. Another task unregisters the netpoll_send_skb() on a lower upper stacked net_device while device netpoll instance. the lower npinfo stays alive. 2. __netpoll_send_skb() uses 2. free_netdev() releases the upper np->dev and queues the skb on device. np->dev->npinfo->txq. 3. The queued skb still keeps 3. The lower txq still owns the skb->dev pointing at the upper deferred skb. device. 4. queue_process() later dequeues 4. queue_process() dereferences from the lower txq and retries that stale upper skb->dev. via skb->dev. Normalize skb->dev to np->dev before the direct transmit attempt and before any fallback enqueue. This keeps both the immediate and deferred netpoll paths in the same device and queue domain that already owns npinfo->txq. Sanitizer validation reported: KASAN slab-use-after-free in queue_process() Read of size 8 Call trace: dump_stack_lvl() (?:?) print_report() (?:?) srso_alias_return_thunk() (arch/x86/include/asm/nospec-branch.h:375) __virt_addr_valid() (?:?) kasan_complete_mode_report_info() (?:?) kasan_report() (?:?) queue_process() (net/core/netpoll.c:88) kasan_check_range() (?:?) __kasan_check_read() (?:?) process_one_work() (kernel/workqueue.c:3200) assign_work() (kernel/workqueue.c:1201) worker_thread() (?:?) kthread() (?:?) ret_from_fork() (?:?) __switch_to() (?:?) __switch_to_asm() (arch/x86/include/asm/switch_to.h:9) ret_from_fork_asm() (?:?) kasan_save_stack() (mm/kasan/common.c:52) kasan_save_track() (mm/kasan/common.c:74) kasan_save_free_info() (?:?) __kasan_slab_free() (?:?) kfree() (?:?) kvfree() (mm/slub.c:6876) netdev_release() (net/core/net-sysfs.c:2227) device_release() (?:?) kobject_put() (lib/kobject.c:730) put_device() (drivers/base/core.c:3810) free_netdev() (net/core/dev.c:12164) full_proxy_write() (?:?) vfs_write() (fs/read_write.c:668) ksys_write() (fs/read_write.c:729) __x64_sys_write() (?:?) x64_sys_call() (arch/x86/entry/syscall_64.c:35) do_syscall_64() (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe() (?:?) Signed-off-by: Zhang Cen --- --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -319,6 +319,8 @@ lockdep_assert_irqs_disabled(); dev = np->dev; + /* npinfo->txq belongs to np->dev, so retries must stay bound to it. */ + skb->dev = dev; rcu_read_lock(); npinfo = rcu_dereference_bh(dev->npinfo);