* Re: [PATCH v2 net-next] selftests/xsk: Preserve UMEM view in BIDIRECTIONAL test
From: Jakub Kicinski @ 2026-06-27 22:42 UTC (permalink / raw)
To: Maciej Fijalkowski
Cc: netdev, bpf, magnus.karlsson, stfomichev, pabeni, horms,
tushar.vyavahare, kerneljasonxing
In-Reply-To: <20260625115215.1101928-1-maciej.fijalkowski@intel.com>
On Thu, 25 Jun 2026 13:52:15 +0200 Maciej Fijalkowski wrote:
> Subject: [PATCH v2 net-next] selftests/xsk: Preserve UMEM view in BIDIRECTIONAL test
>
> Fixes: b17631032769 ("selftests/xsk: Move UMEM state from ifobject to xsk_socket_info")
Yup, doesn't apply, conflicts with the patches that went via net
but are now in both trees.
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH net v5] net: dsa: Fix skb ownership in taggers
From: Jakub Kicinski @ 2026-06-27 22:49 UTC (permalink / raw)
To: Linus Walleij
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Florian Fainelli, Jonas Gorski,
Hauke Mehrtens, Kurt Kanzenbach, Woojung Huh, UNGLinuxDriver,
Chester A. Unal, Daniel Golle, Matthias Brugger,
AngeloGioacchino Del Regno, Wei Fang, Clark Wang,
Clément Léger, George McCollister, David Yang, netdev,
Sashiko AI Review
In-Reply-To: <20260625-dsa-fix-free-skb-v5-1-b5931e4cbdb0@kernel.org>
On Thu, 25 Jun 2026 09:47:01 +0200 Linus Walleij wrote:
> NOTICE: Backporting patches to taggers (e.g. for stable kernels) after
> this point cannot be mechanical or they will introduce double
> kfree_skb().
Sorry for the backporting pain but since the DSA reviews have been
a bit sparse lately - I think we need to keep this code base free
of tribal knowledge, to the extent possible.
^ permalink raw reply
* Re: [PATCH net] net: enetc: check the number of BDs needed for xdp_frame
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Wei Fang
Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni, ast, daniel, hawk, john.fastabend,
sdf, wei.fang, imx, netdev, linux-kernel, bpf
In-Reply-To: <20260626073244.2168214-1-wei.fang@oss.nxp.com>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 26 Jun 2026 15:32:44 +0800 you wrote:
> From: Wei Fang <wei.fang@nxp.com>
>
> The size of xdp_redirect_arr array is ENETC_MAX_SKB_FRAGS. However, the
> number of fragments contained in xdp_frame may be greater than or equal
> to ENETC_MAX_SKB_FRAGS, which will cause the access to xdp_redirect_arr
> to be out of bounds.
>
> [...]
Here is the summary with links:
- [net] net: enetc: check the number of BDs needed for xdp_frame
https://git.kernel.org/netdev/net/c/555c5475e787
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net v5] net: dsa: Fix skb ownership in taggers
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Linus Walleij
Cc: andrew, olteanv, davem, edumazet, kuba, pabeni, horms,
florian.fainelli, jonas.gorski, hauke, kurt, woojung.huh,
UNGLinuxDriver, chester.a.unal, daniel, matthias.bgg,
angelogioacchino.delregno, wei.fang, xiaoning.wang, clement.leger,
george.mccollister, mmyangfl, netdev, sashiko-bot
In-Reply-To: <20260625-dsa-fix-free-skb-v5-1-b5931e4cbdb0@kernel.org>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 25 Jun 2026 09:47:01 +0200 you wrote:
> The tag_8021q.c tagger calls vlan_insert_tag() in dsa_8021q_xmit().
> vlan_insert_tag() will consume the skb with kfree_skb() on failure
> and return NULL.
>
> When NULL is returned as error code to ->xmit() in dsa_user_xmit()
> it will free the same skb again leading to a double-free.
>
> [...]
Here is the summary with links:
- [net,v5] net: dsa: Fix skb ownership in taggers
https://git.kernel.org/netdev/net/c/d4be5f6f9094
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net v2] sctp: fix SCTP_RESET_STREAMS stream list length limit
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Yousef Alhouseen
Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni, horms,
linux-sctp, netdev, linux-kernel
In-Reply-To: <20260625142354.2600-1-alhouseenyousef@gmail.com>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 25 Jun 2026 16:23:54 +0200 you wrote:
> SCTP_RESET_STREAMS carries a flexible array of u16 stream IDs, but the
> optlen clamps treat USHRT_MAX as a byte count and then multiply
> sizeof(__u16) by the fixed header size.
>
> That caps the copied and validated option buffer at about 64 KiB, which
> rejects valid requests containing more than about half of the u16 stream
> ID range.
>
> [...]
Here is the summary with links:
- [net,v2] sctp: fix SCTP_RESET_STREAMS stream list length limit
https://git.kernel.org/netdev/net/c/2b9f5ef53418
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net v2] netpoll: fix a use-after-free on shutdown path
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Breno Leitao
Cc: davem, edumazet, kuba, pabeni, horms, amwang, netdev,
linux-kernel, vlad.wing, asantostc, paulmck, kernel-team, stable,
pavan.chebbi
In-Reply-To: <20260625-netpoll_rcu_fix-v2-1-0748ffac1e98@debian.org>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 25 Jun 2026 05:03:18 -0700 you wrote:
> There is a use-after-free error on netpoll, which is clearly detected by
> KASAN.
>
> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x3b/0x80
> Read of size 1 at addr ... by task kworker/9:1
> Workqueue: events queue_process
> Call Trace:
> skb_dequeue+0x1e/0xb0
> queue_process+0x2c/0x600
> process_scheduled_works+0x4b6/0x850
> worker_thread+0x414/0x5a0
> Allocated by task 242:
> __netpoll_setup+0x201/0x4a0
> netpoll_setup+0x249/0x550
> enabled_store+0x32f/0x380
> Freed by task 0:
> kfree+0x1b7/0x540
> rcu_core+0x3f8/0x7a0
>
> [...]
Here is the summary with links:
- [net,v2] netpoll: fix a use-after-free on shutdown path
https://git.kernel.org/netdev/net/c/45f1458a8501
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net] MAINTAINERS: Update Marvell octeontx2 driver maintainers
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Ratheesh Kannoth
Cc: netdev, linux-kernel, sgoutham, davem, edumazet, kuba, pabeni,
andrew+netdev
In-Reply-To: <20260626044819.3004811-1-rkannoth@marvell.com>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 26 Jun 2026 10:18:19 +0530 you wrote:
> Update the maintainer entries for the Marvell OcteonTX (RVU) drivers to
> reflect recent organizational changes.
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
> MAINTAINERS | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
Here is the summary with links:
- [net] MAINTAINERS: Update Marvell octeontx2 driver maintainers
https://git.kernel.org/netdev/net/c/56114690ff3c
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net v3] sctp: add INIT verification after cookie unpacking
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Xin Long
Cc: netdev, linux-sctp, davem, kuba, edumazet, pabeni, horms,
marcelo.leitner
In-Reply-To: <ebcbbac574815b0850f371b4bdb02f2e602b94d3.1782341592.git.lucien.xin@gmail.com>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 24 Jun 2026 18:53:12 -0400 you wrote:
> In SCTP handshake, the INIT chunk is initially processed by the server
> and embedded into the cookie carried in INIT-ACK. The client then
> returns this cookie via COOKIE-ECHO, where the server unpacks it and
> reconstructs the original INIT chunk.
>
> When cookie authentication is enabled, the cookie contents are protected
> against tampering, so reusing the unpacked INIT without re-verification
> is safe.
>
> [...]
Here is the summary with links:
- [net,v3] sctp: add INIT verification after cookie unpacking
https://git.kernel.org/netdev/net/c/414c5447fe6a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net] net: airoha: dma map xmit frags with skb_frag_dma_map()
From: patchwork-bot+netdevbpf @ 2026-06-27 22:50 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, linux-arm-kernel,
linux-mediatek, netdev
In-Reply-To: <20260625-airoha-eth-skb_frag_dma_map-v1-1-31d9e460aae6@kernel.org>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 25 Jun 2026 11:42:46 +0200 you wrote:
> Map xmit skb fragments using skb_frag_dma_map() instead of
> dma_map_single(skb_frag_address()). skb_frag_address() relies on
> page_address() to obtain a kernel virtual address, which is not
> guaranteed to work for all page types (e.g. highmem pages or
> user-pinned pages from MSG_ZEROCOPY).
> skb_frag_dma_map() maps the fragment directly via its struct page and
> offset through dma_map_page(), avoiding the need for a kernel virtual
> address entirely.
> Introduce an enum airoha_dma_map_type to track how each queue entry was
> mapped (single vs page), so that the matching unmap function is called
> on completion and in error paths.
>
> [...]
Here is the summary with links:
- [net] net: airoha: dma map xmit frags with skb_frag_dma_map()
https://git.kernel.org/netdev/net/c/32f1c2bbb26a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next] Documentation: networking: Add a test plan for ethtool pause validation
From: Andrew Lunn @ 2026-06-27 23:46 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Maxime Chevallier, davem, Eric Dumazet, Paolo Abeni, Simon Horman,
Russell King, Heiner Kallweit, Jonathan Corbet, Shuah Khan,
Oleksij Rempel, Vladimir Oltean, Florian Fainelli,
thomas.petazzoni, netdev, linux-kernel, linux-doc
In-Reply-To: <20260627143028.5afed23a@kernel.org>
On Sat, Jun 27, 2026 at 02:30:28PM -0700, Jakub Kicinski wrote:
> On Sat, 27 Jun 2026 07:34:31 +0200 Maxime Chevallier wrote:
> > > This is very far from what existing python tests do in netdev.
> >
> > We can probably drop the class, as it is with this discussion, it's merely a way
> > to regroup doc common to similar tests. The rest really is the usual set of
> > ksft funcs you can feed to the run function, with a set of ksft_ethtool_*
> > annotators for generic checks.
>
> The common way of checking prereqs in the tests is to call a function
> called require_xyz() which then raises a skip. At a quick glance - the
> rss_api and xdp_metadata are good tests to get a sense of the usual format.
The counter example is the ksft_disruptive() decorator.
Pythons own unittest framework makes use of decorators to skip
tests. Its the Pythonic way.
Andrew
^ permalink raw reply
* [PATCH net] ieee802154: hwsim: free PIB after unregistering hardware
From: Yousef Alhouseen @ 2026-06-27 23:58 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt
Cc: Miquel Raynal, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, linux-wpan, netdev, linux-kernel,
stable, syzbot+4707bb8a43a42fca2b97, Yousef Alhouseen
hwsim_del() queues the currently published PIB for RCU freeing before
unregistering the hardware. The unregister path can still invoke driver
callbacks, including set_promiscuous_mode(), after that grace period has
started. A callback can consequently dereference the freed PIB.
Unregister the hardware first, then fetch and free the final PIB. This also
handles a PIB replacement performed by a callback during unregister.
Fixes: 1c9f4a3fce77 ("ieee802154: hwsim: fix rcu handling")
Reported-by: syzbot+4707bb8a43a42fca2b97@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4707bb8a43a42fca2b97
Cc: stable@vger.kernel.org
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
drivers/net/ieee802154/mac802154_hwsim.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 6daa0f198..2a2d8a9eb 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -1004,12 +1004,11 @@ static void hwsim_del(struct hwsim_phy *phy)
list_del_rcu(&e->list);
hwsim_free_edge(e);
}
- pib = rcu_dereference(phy->pib);
rcu_read_unlock();
- kfree_rcu(pib, rcu);
-
ieee802154_unregister_hw(phy->hw);
+ pib = rcu_dereference_protected(phy->pib, 1);
+ kfree_rcu(pib, rcu);
ieee802154_free_hw(phy->hw);
}
--
2.54.0
^ permalink raw reply related
* [PATCH] netdevsim: remove ethtool debugfs files before freeing netdev
From: Yousef Alhouseen @ 2026-06-28 0:28 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn
Cc: davem, Eric Dumazet, Paolo Abeni, netdev, linux-kernel, stable,
syzbot+6c25f4750230faf70be9, Yousef Alhouseen
The ethtool debugfs files point directly into struct netdevsim, which is
allocated as net_device private data. Their containing port directory is
removed only after nsim_destroy() calls free_netdev().
An open simple-attribute file can consequently dereference the freed
private data before the directory is removed. KASAN observed this in
debugfs_u32_get() during network namespace teardown.
Track and remove the ethtool subtree before free_netdev() on both the
normal and registration-failure paths. debugfs removal drains active
file users before returning.
Fixes: ff1f7c17fb20 ("netdevsim: add pause frame stats")
Reported-by: syzbot+6c25f4750230faf70be9@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=6c25f4750230faf70be9
Cc: stable@vger.kernel.org
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
drivers/net/netdevsim/ethtool.c | 6 ++++++
drivers/net/netdevsim/netdev.c | 2 ++
drivers/net/netdevsim/netdevsim.h | 2 ++
3 files changed, 10 insertions(+)
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 9350ba48eb81..025ea79879f3 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -252,6 +252,7 @@ void nsim_ethtool_init(struct netdevsim *ns)
ns->ethtool.channels = ns->nsim_bus_dev->num_queues;
ethtool = debugfs_create_dir("ethtool", ns->nsim_dev_port->ddir);
+ ns->ethtool_ddir = ethtool;
debugfs_create_u32("get_err", 0600, ethtool, &ns->ethtool.get_err);
debugfs_create_u32("set_err", 0600, ethtool, &ns->ethtool.set_err);
@@ -272,3 +273,8 @@ void nsim_ethtool_init(struct netdevsim *ns)
debugfs_create_u32("tx_max_pending", 0600, dir,
&ns->ethtool.ring.tx_max_pending);
}
+
+void nsim_ethtool_fini(struct netdevsim *ns)
+{
+ debugfs_remove(ns->ethtool_ddir);
+}
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 27e5f109f933..4e9d7e10b527 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -1165,6 +1165,7 @@ struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
return ns;
err_free_netdev:
+ nsim_ethtool_fini(ns);
free_netdev(dev);
return ERR_PTR(err);
}
@@ -1178,6 +1179,7 @@ void nsim_destroy(struct netdevsim *ns)
debugfs_remove(ns->vlan_dfs);
debugfs_remove(ns->qr_dfs);
debugfs_remove(ns->pp_dfs);
+ nsim_ethtool_fini(ns);
if (ns->nb.notifier_call)
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 4c9cc96dcec3..64f77f93d937 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -154,6 +154,7 @@ struct netdevsim {
struct dentry *pp_dfs;
struct dentry *qr_dfs;
struct dentry *vlan_dfs;
+ struct dentry *ethtool_ddir;
struct nsim_ethtool ethtool;
struct netdevsim __rcu *peer;
@@ -169,6 +170,7 @@ void nsim_destroy(struct netdevsim *ns);
bool netdev_is_nsim(struct net_device *dev);
void nsim_ethtool_init(struct netdevsim *ns);
+void nsim_ethtool_fini(struct netdevsim *ns);
void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev);
int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 2/6] remoteproc: qcom: Add M0 BTSS secure PIL driver
From: Bjorn Andersson @ 2026-06-28 3:07 UTC (permalink / raw)
To: george.moussalem
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Konrad Dybcio, Mathieu Poirier,
Philipp Zabel, linux-block, linux-kernel, linux-mmc, devicetree,
linux-wireless, ath10k, linux-arm-msm, linux-bluetooth, netdev,
linux-remoteproc
In-Reply-To: <20260625-ipq5018-bluetooth-v1-2-d999be0e04f7@outlook.com>
On Thu, Jun 25, 2026 at 06:10:06PM +0400, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Add support to bring up the M0 core of the bluetooth subsystem found in
> the IPQ5018 SoC.
>
> The signed firmware loaded is authenticated by TrustZone. If successful,
> the M0 core boots the firmware and the peripheral is taken out of reset
> using a Secure Channel Manager call to TrustZone.
>
The remoteproc framework deals with life cycle management of
coprocessors, but you don't want that - you want the BT driver to own
the life cycle.
Further, the fact that you split this in "BT" and "remoteproc", results
in you having two representations in DeviceTree and in the device model
for the same hardware.
I know we have examples of this in the kernel already, but they are all
racy...
Please see if you can embed the firmware loading, authentication and
PAS calls directly into the BT driver - to have a single entity managing
the life cycle of your M0 processor.
Regards,
Bjorn
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
> drivers/remoteproc/Kconfig | 12 ++
> drivers/remoteproc/Makefile | 1 +
> drivers/remoteproc/qcom_m0_btss_pil.c | 261 ++++++++++++++++++++++++++++++++++
> 3 files changed, 274 insertions(+)
>
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index c521c744e7db..6b52f78f1427 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -163,6 +163,18 @@ config PRU_REMOTEPROC
> processors on various TI SoCs. It's safe to say N here if you're
> not interested in the PRU or if you are unsure.
>
> +config QCOM_M0_BTSS_PIL
> + tristate "Qualcomm M0 BTSS Peripheral Image Loader"
> + depends on OF && ARCH_QCOM
> + select QCOM_MDT_LOADER
> + select QCOM_RPROC_COMMON
> + select QCOM_SCM
> + help
> + Say y here to support the Secure Peripheral Imager Loader for the
> + Qualcomm Bluetooth Subsystem running on the M0 remote processor found
> + in the IPQ5018 SoC. The M0 core is started and stopped using a
> + Secure Channel Manager call to TrustZone.
> +
> config QCOM_PIL_INFO
> tristate
>
> diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
> index 1c7598b8475d..df80faf8d0df 100644
> --- a/drivers/remoteproc/Makefile
> +++ b/drivers/remoteproc/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
> obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o
> obj-$(CONFIG_MESON_MX_AO_ARC_REMOTEPROC)+= meson_mx_ao_arc.o
> obj-$(CONFIG_PRU_REMOTEPROC) += pru_rproc.o
> +obj-$(CONFIG_QCOM_M0_BTSS_PIL) += qcom_m0_btss_pil.o
> obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil_info.o
> obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o
> obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o
> diff --git a/drivers/remoteproc/qcom_m0_btss_pil.c b/drivers/remoteproc/qcom_m0_btss_pil.c
> new file mode 100644
> index 000000000000..7168e270e4d4
> --- /dev/null
> +++ b/drivers/remoteproc/qcom_m0_btss_pil.c
> @@ -0,0 +1,261 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2026 The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/elf.h>
> +#include <linux/firmware/qcom/qcom_scm.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/qcom/mdt_loader.h>
> +
> +#include "qcom_common.h"
> +
> +#define BTSS_PAS_ID 0xc
> +
> +struct m0_btss {
> + struct device *dev;
> + phys_addr_t mem_phys;
> + phys_addr_t mem_reloc;
> + void __iomem *mem_region;
> + size_t mem_size;
> + struct reset_control *btss_reset;
> +};
> +
> +static int m0_btss_start(struct rproc *rproc)
> +{
> + int ret;
> +
> + if (!qcom_scm_pas_supported(BTSS_PAS_ID)) {
> + dev_err(rproc->dev.parent,
> + "PAS is not available for peripheral: 0x%x\n",
> + BTSS_PAS_ID);
> + return -ENODEV;
> + }
> +
> + ret = qcom_scm_pas_auth_and_reset(BTSS_PAS_ID);
> + if (ret) {
> + dev_err(rproc->dev.parent, "Failed to start rproc: %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int m0_btss_stop(struct rproc *rproc)
> +{
> + int ret;
> +
> + if (rproc->state == RPROC_RUNNING || rproc->state == RPROC_CRASHED) {
> + ret = qcom_scm_pas_shutdown(BTSS_PAS_ID);
> + if (ret) {
> + dev_err(rproc->dev.parent, "Failed to stop rproc: %d\n",
> + ret);
> + return ret;
> + }
> +
> + dev_info(rproc->dev.parent, "Successfully stopped rproc\n");
> + }
> +
> + return 0;
> +}
> +
> +static int m0_btss_load(struct rproc *rproc, const struct firmware *fw)
> +{
> + struct m0_btss *desc = rproc->priv;
> + const struct elf32_phdr *phdrs;
> + const struct firmware *seg_fw;
> + const struct elf32_phdr *phdr;
> + const struct elf32_hdr *ehdr;
> + void __iomem *metadata;
> + size_t metadata_size;
> + int i, ret;
> +
> + ehdr = (const struct elf32_hdr *)fw->data;
> + phdrs = (const struct elf32_phdr *)(ehdr + 1);
> +
> + ret = request_firmware(&fw, rproc->firmware, rproc->dev.parent);
> + if (ret) {
> + dev_err(rproc->dev.parent, "Failed to request firmware: %d\n",
> + ret);
> + return ret;
> + }
> +
> + metadata = qcom_mdt_read_metadata(fw, &metadata_size, rproc->firmware,
> + rproc->dev.parent);
> + if (IS_ERR(metadata)) {
> + ret = PTR_ERR(metadata);
> + dev_err(rproc->dev.parent,
> + "Failed to read firmware metadata: %d\n", ret);
> + goto release_fw;
> + }
> +
> + ret = qcom_scm_pas_init_image(BTSS_PAS_ID, metadata,
> + metadata_size, NULL);
> + if (ret) {
> + dev_err(rproc->dev.parent, "PAS init image failed: %d\n", ret);
> + goto free_metadata;
> + }
> +
> + for (i = 0; i < ehdr->e_phnum; i++) {
> + char *seg_name __free(kfree) = kstrdup(rproc->firmware,
> + GFP_KERNEL);
> + if (!seg_name)
> + return -ENOMEM;
> +
> + phdr = &phdrs[i];
> +
> + /* Only process valid loadable data segments */
> + if (phdr->p_type != PT_LOAD || !phdr->p_memsz)
> + continue;
> +
> + if (phdr->p_vaddr + phdr->p_filesz > desc->mem_size) {
> + dev_err(rproc->dev.parent,
> + "Segment data exceeds the reserved memory area!\n");
> + goto free_metadata;
> + }
> +
> + /* Check if firmware is split across multiple segment files */
> + if (phdr->p_offset > fw->size ||
> + phdr->p_offset + phdr->p_filesz > fw->size) {
> + sprintf(seg_name + strlen(seg_name) - 3, "b%02d", i);
> + ret = request_firmware(&seg_fw, seg_name,
> + rproc->dev.parent);
> + if (ret) {
> + dev_err(rproc->dev.parent,
> + "Could not find split segment binary: %s\n",
> + seg_name);
> + goto free_metadata;
> + }
> +
> + /*
> + * Use the virtual instead of the physical address as
> + * the offset
> + */
> + memcpy_toio(desc->mem_region + phdr->p_vaddr,
> + seg_fw->data, phdr->p_filesz);
> +
> + release_firmware(seg_fw);
> + } else {
> + memcpy_toio(desc->mem_region + phdr->p_vaddr,
> + fw->data + phdr->p_offset, phdr->p_filesz);
> + }
> + }
> +
> + return 0;
> +
> +free_metadata:
> + kfree(metadata);
> +release_fw:
> + release_firmware(fw);
> + return ret;
> +}
> +
> +static const struct rproc_ops m0_btss_ops = {
> + .start = m0_btss_start,
> + .stop = m0_btss_stop,
> + .load = m0_btss_load,
> + .get_boot_addr = rproc_elf_get_boot_addr,
> +};
> +
> +static int m0_btss_alloc_memory_region(struct m0_btss *desc)
> +{
> + struct device *dev = desc->dev;
> + struct resource res;
> + int ret;
> +
> + ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
> + if (ret) {
> + dev_err(dev, "unable to acquire memory-region resource\n");
> + return ret;
> + }
> +
> + desc->mem_phys = res.start;
> + desc->mem_reloc = res.start;
> + desc->mem_size = resource_size(&res);
> + desc->mem_region = devm_ioremap(dev, desc->mem_phys, desc->mem_size);
> + if (!desc->mem_region) {
> + dev_err(dev, "unable to map memory region: %pR\n", &res);
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static int m0_btss_pil_probe(struct platform_device *pdev)
> +{
> + // struct reset_control *btss_reset;
> + struct device *dev = &pdev->dev;
> + const char *fw_name = NULL;
> + struct m0_btss *desc;
> + struct clk *lpo_clk;
> + struct rproc *rproc;
> + int ret;
> +
> + ret = of_property_read_string(dev->of_node, "firmware-name",
> + &fw_name);
> + if (ret < 0)
> + return ret;
> +
> + rproc = devm_rproc_alloc(dev, "m0btss", &m0_btss_ops,
> + fw_name, sizeof(*desc));
> + if (!rproc) {
> + dev_err(dev, "failed to allocate rproc\n");
> + return -ENOMEM;
> + }
> +
> + desc = rproc->priv;
> + desc->dev = dev;
> +
> + ret = m0_btss_alloc_memory_region(desc);
> + if (ret)
> + return ret;
> +
> + lpo_clk = devm_clk_get_enabled(dev, "btss_lpo_clk");
> + if (IS_ERR(lpo_clk))
> + return dev_err_probe(dev, PTR_ERR(lpo_clk),
> + "Failed to get lpo clock\n");
> +
> + desc->btss_reset = devm_reset_control_get(dev, "btss_reset");
> + if (IS_ERR_OR_NULL(desc->btss_reset))
> + return dev_err_probe(dev, PTR_ERR(desc->btss_reset),
> + "unable to acquire btss_reset\n");
> +
> + ret = reset_control_deassert(desc->btss_reset);
> + if (ret)
> + return dev_err_probe(rproc->dev.parent, ret,
> + "Failed to deassert reset\n");
> +
> + rproc->auto_boot = false;
> + ret = devm_rproc_add(dev, rproc);
> + if (ret)
> + return ret;
> +
> + platform_set_drvdata(pdev, rproc);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id m0_btss_of_match[] = {
> + { .compatible = "qcom,ipq5018-btss-pil" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, m0_btss_of_match);
> +
> +static struct platform_driver m0_btss_pil_driver = {
> + .probe = m0_btss_pil_probe,
> + .driver = {
> + .name = "qcom-m0-btss-pil",
> + .of_match_table = m0_btss_of_match,
> + },
> +};
> +
> +module_platform_driver(m0_btss_pil_driver);
> +
> +MODULE_DESCRIPTION("Qualcomm M0 Bluetooth Subsystem Peripheral Image Loader");
> +MODULE_LICENSE("GPL");
>
> --
> 2.53.0
>
>
^ permalink raw reply
* Re: [PATCH 2/6] remoteproc: qcom: Add M0 BTSS secure PIL driver
From: Bjorn Andersson @ 2026-06-28 3:08 UTC (permalink / raw)
To: Konrad Dybcio
Cc: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
In-Reply-To: <38aceb33-b28e-4994-b277-de070b6dae2b@oss.qualcomm.com>
On Fri, Jun 26, 2026 at 01:20:25PM +0200, Konrad Dybcio wrote:
> On 6/25/26 4:10 PM, George Moussalem via B4 Relay wrote:
> > From: George Moussalem <george.moussalem@outlook.com>
> >
> > Add support to bring up the M0 core of the bluetooth subsystem found in
> > the IPQ5018 SoC.
> >
> > The signed firmware loaded is authenticated by TrustZone. If successful,
> > the M0 core boots the firmware and the peripheral is taken out of reset
> > using a Secure Channel Manager call to TrustZone.
> >
> > Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> > ---
>
> Can this not fit inside the existing PAS driver?
>
While the start/stop SCM calls look the same, this doesn't follow any of
the surrounding concepts. So I think this should follow the other
non-remoteproc uses of mdt_loader and scm directly instead.
Regards,
Bjorn
> Konrad
^ permalink raw reply
* Re: [PATCH] fix: net: mediatek: mtk_star_mdio_init: fix double of_node_put after devm_of_mdiobus_register
From: WenTao Liang @ 2026-06-28 4:00 UTC (permalink / raw)
To: Daniel Borkmann, netdev
Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, stable,
linux-kernel
In-Reply-To: <20260626152009.51599-1-vulab@iscas.ac.cn>
> 2026年6月26日 23:20,WenTao Liang <vulab@iscas.ac.cn> 写道:
>
> After devm_of_mdiobus_register succeeds, the mdio_node reference
> ownership is transferred to the mii_bus device (released via
> mdiobus_release on device teardown). However, the function
> unconditionally calls of_node_put(mdio_node) after registration, causing
> a double put.
>
> Only call of_node_put when devm_of_mdiobus_register fails (i.e., when
> ownership was not transferred). On success, the bus driver manages the
> reference lifecycle.
>
> Cc: stable@vger.kernel.org
> Fixes: 9ed0a3fac08b ("net: ethernet: mtk-star-emac: use devm_of_mdiobus_register()")
> Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
> ---
> drivers/net/ethernet/mediatek/mtk_star_emac.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c
> index b83886a41121..b949dd240e6b 100644
> --- a/drivers/net/ethernet/mediatek/mtk_star_emac.c
> +++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c
> @@ -1446,7 +1446,10 @@ static int mtk_star_mdio_init(struct net_device *ndev)
> priv->mii->priv = priv;
>
> ret = devm_of_mdiobus_register(dev, priv->mii, mdio_node);
> + if (ret)
> + of_node_put(mdio_node);
>
> + return ret;
> out_put_node:
> of_node_put(mdio_node);
> return ret;
> --
> 2.39.5 (Apple Git-154)
Please ignore this patch. I will resend a proper version after
learning the kernel submission process.
Apologies for the noise.
Best regards,
WenTao Liang
^ permalink raw reply
* Re: [PATCH] fix: net: renesas: rswitch_mii_register: fix double of_node_put after of_mdiobus_register
From: WenTao Liang @ 2026-06-28 4:02 UTC (permalink / raw)
To: netdev
Cc: Yoshihiro Shimoda, David S . Miller, Jakub Kicinski, Paolo Abeni,
stable, linux-kernel
In-Reply-To: <20260626152430.51835-1-vulab@iscas.ac.cn>
> 2026年6月26日 23:24,WenTao Liang <vulab@iscas.ac.cn> 写道:
>
> After of_mdiobus_register succeeds, the mdio_np reference ownership is
> transferred to the mii_bus device (released via fwnode_handle_put during
> mdiobus_release). The success path calls of_node_put(mdio_np) which,
> combined with the automatic release via bus teardown, results in a double
> put and refcount underflow.
>
> Move of_node_put so it is only called in the error path where
> of_mdiobus_register failed. On success, the bus driver manages the
> reference lifecycle.
>
> Cc: stable@vger.kernel.org
> Fixes: 3590918b5d07 ("net: ethernet: renesas: Add support for Ethernet Switch")
> Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
> ---
> drivers/net/ethernet/renesas/rswitch_main.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c
> index 6fe964816322..c33add28a70c 100644
> --- a/drivers/net/ethernet/renesas/rswitch_main.c
> +++ b/drivers/net/ethernet/renesas/rswitch_main.c
> @@ -1387,13 +1387,13 @@ static int rswitch_mii_register(struct rswitch_device *rdev)
> err = of_mdiobus_register(mii_bus, mdio_np);
> if (err < 0) {
> mdiobus_free(mii_bus);
> - goto out;
> + of_node_put(mdio_np);
> + return err;
> }
>
> rdev->etha->mii = mii_bus;
>
> -out:
> - of_node_put(mdio_np);
> + return 0;
>
> return err;
> }
> --
> 2.39.5 (Apple Git-154)
Please ignore this patch. I will resend a proper version after
learning the kernel submission process.
Apologies for the noise.
Best regards,
WenTao Liang
^ permalink raw reply
* Re: [PATCH] fix: net: marvell: orion_mdio_probe: fix clock reference leak on extra clock detection
From: WenTao Liang @ 2026-06-28 4:02 UTC (permalink / raw)
To: Andrew Lunn, netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
stable, linux-kernel
In-Reply-To: <20260626151926.51342-1-vulab@iscas.ac.cn>
> 2026年6月26日 23:19,WenTao Liang <vulab@iscas.ac.cn> 写道:
>
> The code calls of_clk_get(pdev->dev.of_node, ARRAY_SIZE(dev->clk)) to
> detect unsupported extra clocks. If an extra clock exists, the function
> prints a warning but discards the returned clk pointer without calling
> clk_put, leaking a clock reference on every probe.
>
> Store the returned clock and call clk_put after the warning to properly
> release the acquired reference.
>
> Cc: stable@vger.kernel.org
> Fixes: ea664b1bdc19 ("net: mvmdio: print warning when orion-mdio has too many clocks")
> Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
> ---
> drivers/net/ethernet/marvell/mvmdio.c | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
> index 3f4447e68888..4e5b5c5f7301 100644
> --- a/drivers/net/ethernet/marvell/mvmdio.c
> +++ b/drivers/net/ethernet/marvell/mvmdio.c
> @@ -339,11 +339,18 @@ static int orion_mdio_probe(struct platform_device *pdev)
> clk_prepare_enable(dev->clk[i]);
> }
>
> - if (!IS_ERR(of_clk_get(pdev->dev.of_node,
> - ARRAY_SIZE(dev->clk))))
> - dev_warn(&pdev->dev,
> - "unsupported number of clocks, limiting to the first "
> - __stringify(ARRAY_SIZE(dev->clk)) "\n");
> + {
> + struct clk *extra_clk;
> +
> + extra_clk = of_clk_get(pdev->dev.of_node,
> + ARRAY_SIZE(dev->clk));
> + if (!IS_ERR(extra_clk)) {
> + dev_warn(&pdev->dev,
> + "unsupported number of clocks, limiting to the first "
> + __stringify(ARRAY_SIZE(dev->clk)) "\n");
> + clk_put(extra_clk);
> + }
> + }
>
> if (type == BUS_TYPE_XSMI)
> orion_mdio_xsmi_set_mdc_freq(bus);
> --
> 2.39.5 (Apple Git-154)
Please ignore this patch. I will resend a proper version after
learning the kernel submission process.
Apologies for the noise.
Best regards,
WenTao Liang
^ permalink raw reply
* [PATCH v2] ptp: ocp: add I2C ISP support for ADVA TimeCard CPLD
From: Sagi Maimon @ 2026-06-28 5:38 UTC (permalink / raw)
To: jonathan.lemon, vadim.fedorenko, richardcochran, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: linux-kernel, netdev, Sagi Maimon
The ADVA TimeCard programs its on-board CPLD (Lattice MachXO3)
via I2C using in-system programming (ISP).
The CPLD resides on a secondary I2C bus controlled by the
embedded MicroBlaze. To allow programming, the driver must
take ownership of this bus and expose it to userspace.
Add support to:
- enable the i2c-dev interface to expose /dev/i2c-N
- provide sysfs control over the secondary I2C bus
Signed-off-by: Sagi Maimon <maimon.sagi@gmail.com>
---
Address comments from:
- Andrew Lunn: https://www.spinics.net/lists/netdev/msg1200997.html
Changes since v1:
- Add reasoning to the commit message
drivers/ptp/ptp_ocp.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 35e911f1ad78..1b4ccb4feca5 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -4224,6 +4224,34 @@ static const struct ocp_attr_group art_timecard_groups[] = {
{ },
};
+static ssize_t
+i2c_bus_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+
+ if (!bp->pps_select)
+ return -ENODEV;
+ return sysfs_emit(buf, "0x%08x\n",
+ ioread32(&bp->pps_select->__pad1));
+}
+
+static ssize_t
+i2c_bus_ctrl_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ if (!bp->pps_select)
+ return -ENODEV;
+ if (kstrtou32(buf, 0, &val))
+ return -EINVAL;
+ iowrite32(val, &bp->pps_select->__pad1);
+ return count;
+}
+
+static DEVICE_ATTR_RW(i2c_bus_ctrl);
+
static struct attribute *adva_timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gnss_sync.attr,
@@ -4272,6 +4300,7 @@ static struct attribute *adva_timecard_x1_attrs[] = {
&dev_attr_ts_window_adjust.attr,
&dev_attr_utc_tai_offset.attr,
&dev_attr_tod_correction.attr,
+ &dev_attr_i2c_bus_ctrl.attr,
NULL,
};
@@ -5235,6 +5264,7 @@ ptp_ocp_init(void)
const char *what;
int err;
+ request_module("i2c-dev");
ptp_ocp_debugfs_init();
what = "timecard class";
--
2.47.0
^ permalink raw reply related
* Re: [RFC PATCH net-next] netpoll: hold RCU while walking napi_list
From: Runyu Xiao @ 2026-06-28 5:04 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, edumazet, pabeni, horms, leitao, sashal, bigeasy, netdev,
linux-kernel, jianhao.xu
In-Reply-To: <20260627142105.29f1322c@kernel.org>
Hi,
On Sat, 27 Jun 2026 14:21:05 -0700 Jakub Kicinski wrote:
> Please provide the stack trace from the report, rather than just saying
> that you can trigger it.
Sure, sorry for not including it in the RFC. The warning was from the
reviewed reproducer used for the CONFIG_PROVE_RCU_LIST triage, not from
a production crash. The relevant part of the dmesg is:
WARNING: suspicious RCU usage
6.1.66 #3 Tainted: G O
-----------------------------
/home/ubuntu22/msv_workspace/shared/vuln_msv.c:45 RCU-list traversed in non-reader section!!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
no locks held by insmod/190.
stack backtrace:
CPU: 1 PID: 190 Comm: insmod Tainted: G O 6.1.66 #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<task>
dump_stack_lvl+0x45/0x5d
lockdep_rcu_suspicious.cold+0x2d/0x64
poll_napi.constprop.0+0x43/0x71 [vuln_msv]
netpoll_poll_dev.constprop.0+0x27/0x36 [vuln_msv]
? 0xffffffffc0005000
rcu_list_msv_init+0xe2/0x1000 [vuln_msv]
do_one_initcall+0x56/0x250
do_init_module+0x47/0x1c0
__do_sys_finit_module+0xa6/0x100
do_syscall_64+0x3b/0x90
entry_SYSCALL_64_after_hwframe+0x64/0xce
</task>
The reproducer keeps the shape intentionally small: netpoll_poll_dev()
is exercised directly and calls poll_napi(), which walks dev->napi_list
with list_for_each_entry_rcu() outside an explicit RCU read-side section.
It does not model a concurrent NAPI free.
Thanks.
^ permalink raw reply
* Re: [PATCH] fix: net/batman-adv: batadv_interface_kill_vid: extra batadv_meshif_vlan_put after destroy
From: WenTao Liang @ 2026-06-28 7:30 UTC (permalink / raw)
To: marek.lindner, sw, antonio, sven, davem, edumazet, kuba, pabeni
Cc: horms, b.a.t.m.a.n, netdev, linux-kernel, stable
In-Reply-To: <20260627034636.59693-1-vulab@iscas.ac.cn>
> 2026年6月27日 11:46,WenTao Liang <vulab@iscas.ac.cn> 写道:
>
> In batadv_interface_kill_vid(), batadv_meshif_vlan_get() acquires a
> reference on the vlan object. batadv_meshif_destroy_vlan() internally
> calls batadv_meshif_vlan_put() which balances that reference. However, an
> additional batadv_meshif_vlan_put(vlan) is called after
> batadv_meshif_destroy_vlan(), causing a refcount underflow and potential
> use-after-free of the vlan object.
>
> Remove the extra batadv_meshif_vlan_put(vlan) call.
>
> Cc: stable@vger.kernel.org
> Fixes: 5d2c05b21337 ("batman-adv: add per VLAN interface attribute framework")
> Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
> ---
> net/batman-adv/mesh-interface.c | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
> index e7aa45bc6b7a..cc974f243200 100644
> --- a/net/batman-adv/mesh-interface.c
> +++ b/net/batman-adv/mesh-interface.c
> @@ -691,9 +691,6 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
>
> batadv_meshif_destroy_vlan(bat_priv, vlan);
>
> - /* finally free the vlan object */
> - batadv_meshif_vlan_put(vlan);
> -
> return 0;
> }
>
> --
> 2.39.5 (Apple Git-154)
Please ignore this patch. I will resend a proper version after
learning the kernel submission process.
Apologies for the noise.
Best regards,
WenTao Liang
^ permalink raw reply
* [PATCH net] net: qualcomm: rmnet: validate MAP frame length before ingress parsing
From: Xiang Mei @ 2026-06-28 7:52 UTC (permalink / raw)
To: subash.a.kasiviswanathan, sean.tranchetti, netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, linux-kernel,
bestswngs, Xiang Mei
__rmnet_map_ingress_handler() casts skb->data to a struct rmnet_map_header
and trusts the on-wire pkt_len field without verifying that the skb
actually contains the bytes it is about to dereference. When ingress
deaggregation is disabled (RMNET_FLAGS_INGRESS_DEAGGREGATION cleared), the
skb is handed to __rmnet_map_ingress_handler() directly, bypassing the
length check that rmnet_map_deaggregate() performs.
Three distinct reads past skb->len are reachable, so three guards are
needed:
- The MAP header (flags, mux_id, pkt_len) is read on entry, before either
csum branch and even on the command and non-csum paths, so a runt frame
faults here regardless of data_format. Guard the header first.
- On the MAPv5 next-header path, rmnet_map_process_next_hdr_packet() reads
the v5 csum header at (skb->data + sizeof(map_header)); the entry guard
only covers the header, so this needs its own check.
- On the MAPv4 path, rmnet_map_checksum_downlink_packet() reads the csum
trailer at (skb->data + len); guard it under the same CKSUMV4 condition
the read uses, or valid non-csum frames would be dropped.
Each guard uses pskb_may_pull() before its read. The MAPv4 check uses
ntohs(pkt_len) (== payload + pad) directly rather than the derived len, so
it is unaffected by the u16 underflow in len when pad > pkt_len. Well-formed
frames always carry the header/trailer they declare, so only malformed
packets are dropped; this mirrors the length check rmnet_map_deaggregate()
already performs on the deaggregation path.
BUG: KASAN: slab-out-of-bounds in rmnet_map_checksum_downlink_packet
Read of size 1 at addr ffff88801118ed00 by task exploit/147
Call Trace:
...
rmnet_map_checksum_downlink_packet (drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c:413)
__rmnet_map_ingress_handler (drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c:96)
rmnet_rx_handler (drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c:129)
__netif_receive_skb_core.constprop.0 (net/core/dev.c:6089)
netif_receive_skb (net/core/dev.c:6460)
tun_get_user (drivers/net/tun.c:1955)
tun_chr_write_iter (drivers/net/tun.c:2001)
vfs_write (fs/read_write.c:688)
ksys_write (fs/read_write.c:740)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
...
Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index 9f3479500f85..83d011ed5942 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -61,6 +61,9 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
u16 len, pad;
u8 mux_id;
+ if (!pskb_may_pull(skb, sizeof(*map_header)))
+ goto free_skb;
+
if (map_header->flags & MAP_CMD_FLAG) {
/* Packet contains a MAP command (not data) */
if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS)
@@ -84,11 +87,19 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
if ((port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5) &&
(map_header->flags & MAP_NEXT_HEADER_FLAG)) {
+ if (!pskb_may_pull(skb, sizeof(*map_header) +
+ sizeof(struct rmnet_map_v5_csum_header)))
+ goto free_skb;
if (rmnet_map_process_next_hdr_packet(skb, len))
goto free_skb;
skb_pull(skb, sizeof(*map_header));
rmnet_set_skb_proto(skb);
} else {
+ if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4 &&
+ !pskb_may_pull(skb, sizeof(*map_header) +
+ ntohs(map_header->pkt_len) +
+ sizeof(struct rmnet_map_dl_csum_trailer)))
+ goto free_skb;
/* Subtract MAP header */
skb_pull(skb, sizeof(*map_header));
rmnet_set_skb_proto(skb);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next] ipv4: fib: fix route re-dump in inet_dump_fib() on multi-batch dump
From: Ido Schimmel @ 2026-06-28 8:19 UTC (permalink / raw)
To: Pengfei Zhang
Cc: dsahern, davem, edumazet, kuba, pabeni, horms, netdev,
linux-kernel, chenzhangqi, baohua, zhangpengfei16
In-Reply-To: <20260626085636.1524451-1-zhangfeionline@gmail.com>
On Fri, Jun 26, 2026 at 04:56:36PM +0800, Pengfei Zhang wrote:
> inet_dump_fib() saves its progress in cb->args[1] as a positional
> index within the current hash chain. Between batches, a concurrent
> fib_new_table() can insert a new table at the chain head, shifting
> all existing entries. On resume the saved index lands on a different
> table, causing already-dumped tables to be re-dumped and the
> originally suspended table to restart from the beginning.
>
> Fix by storing tb->tb_id in cb->args[1] instead of a positional
> index, mirroring the fix applied to inet6_dump_fib().
Wait for it to be applied, then reference the commit.
>
> Fixes: 1b43af5480c3 ("[IPV6]: Increase number of possible routing tables to 2^32")
Please drop the fixes tag given this is targeted at net-next.
Also, net-next is currently closed. Submit v2 when it opens:
https://netdev.bots.linux.dev/net-next.html
> Signed-off-by: Pengfei Zhang <zhangfeionline@gmail.com>
> ---
> Consider a hash slot containing two tables [A(pos=0), B(pos=1)] where
> B is large enough to require multiple batches. On the first batch, B
> suspends mid-walk and the loop saves:
>
> cb->args[1] = e; /* e=1, position of B in the chain */
>
> The lock is then released. At this point a concurrent fib_new_table()
> inserts table C at the chain head via hlist_add_head_rcu(), making the
> chain [C(pos=0), A(pos=1), B(pos=2)].
>
> On the next batch, inet_dump_fib() resumes with s_e=1 and iterates:
>
> s_e = cb->args[1]; /* s_e = 1 */
> hlist_for_each_entry_rcu(tb, head, tb_hlist) {
> if (e < s_e) /* skip C at pos=0 */
> goto next;
> /* e=1: tb now points to A, not B */
> if (dumped)
> memset(...); /* resets B's suspended progress */
> fib_table_dump(tb, ...); /* re-dumps A from scratch */
> dumped = 1;
> /* e=2: tb now points to B */
> fib_table_dump(tb, ...); /* re-dumps B from beginning */
> }
>
> Routes from A are dumped twice, and the portion of B that was already
> dumped in the first batch is dumped again.
>
> net/ipv4/fib_frontend.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
> index 42212970d..65fa245af 100644
> --- a/net/ipv4/fib_frontend.c
> +++ b/net/ipv4/fib_frontend.c
> @@ -1019,10 +1019,11 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
> .dump_routes = true,
> .dump_exceptions = true,
> };
> - unsigned int e = 0, s_e, h, s_h;
> struct hlist_head *head;
> int dumped = 0, err = 0;
> + unsigned int h, s_h;
Move this line below the next line to maintain reverse xmas tree
ordering:
https://docs.kernel.org/process/maintainer-netdev.html#local-variable-ordering-reverse-xmas-tree-rcs
> struct fib_table *tb;
> + u32 s_id;
>
> rcu_read_lock();
> if (cb->strict_check) {
> @@ -1054,29 +1055,28 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
> }
>
> s_h = cb->args[0];
> - s_e = cb->args[1];
> + s_id = cb->args[1];
>
> err = 0;
> - for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
> - e = 0;
> + for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_id = 0) {
> head = &net->ipv4.fib_table_hash[h];
> hlist_for_each_entry_rcu(tb, head, tb_hlist) {
> - if (e < s_e)
> - goto next;
> + if (s_id && tb->tb_id != s_id)
> + continue;
> +
> + s_id = 0;
> if (dumped)
> memset(&cb->args[2], 0, sizeof(cb->args) -
> 2 * sizeof(cb->args[0]));
> + cb->args[1] = tb->tb_id;
> err = fib_table_dump(tb, skb, cb, &filter);
> if (err < 0)
> goto out;
> dumped = 1;
> -next:
> - e++;
> }
> }
> out:
>
> - cb->args[1] = e;
> cb->args[0] = h;
>
> unlock:
> --
> 2.34.1
>
^ permalink raw reply
* [PATCH net 1/1] sctp: avoid auth_enable sysctl UAF during netns teardown
From: Ren Wei @ 2026-06-28 8:39 UTC (permalink / raw)
To: linux-sctp, netdev
Cc: marcelo.leitner, lucien.xin, davem, edumazet, pabeni, horms,
matttbe, yuantan098, yifanwucs, tomapufckgml, bird, roxy520tt,
n05ec
In-Reply-To: <cover.1782585631.git.roxy520tt@gmail.com>
From: Zhiling Zou <roxy520tt@gmail.com>
proc_sctp_do_auth() updates the SCTP control socket after changing
net.sctp.auth_enable. The handler gets the per-net SCTP state from
ctl->data, so an already opened sysctl file can still target a network
namespace while that namespace is being torn down.
SCTP unregisters its per-net sysctls from sctp_defaults_exit(), but
sctp_ctrlsock_exit() runs earlier because the control-socket pernet ops
are registered after the defaults ops. This leaves a teardown window
where auth_enable is still writable after inet_ctl_sock_destroy() has
released net->sctp.ctl_sock, leading to a use-after-free when the sysctl
handler locks and dereferences the stale socket.
Unregister the per-net SCTP sysctl table before destroying the control
socket. Make sctp_sysctl_net_unregister() tolerate a missing header and
clear the saved pointer so the later defaults exit path and init-error
path can safely share the same unregister helper.
Fixes: 15649fd5415e ("sctp: sysctl: auth_enable: avoid using current->nsproxy")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/sctp/protocol.c | 3 +++
net/sctp/sysctl.c | 9 +++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 587b0017a67d..ae381d304bd5 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1457,8 +1457,11 @@ static int __net_init sctp_ctrlsock_init(struct net *net)
static void __net_exit sctp_ctrlsock_exit(struct net *net)
{
+ sctp_sysctl_net_unregister(net);
+
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
+ net->sctp.ctl_sock = NULL;
}
static struct pernet_operations sctp_ctrlsock_ops = {
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 15e7db9a3ab2..fca840484ebf 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -615,11 +615,16 @@ int sctp_sysctl_net_register(struct net *net)
void sctp_sysctl_net_unregister(struct net *net)
{
+ struct ctl_table_header *header = net->sctp.sysctl_header;
const struct ctl_table *table;
- table = net->sctp.sysctl_header->ctl_table_arg;
- unregister_net_sysctl_table(net->sctp.sysctl_header);
+ if (!header)
+ return;
+
+ table = header->ctl_table_arg;
+ unregister_net_sysctl_table(header);
kfree(table);
+ net->sctp.sysctl_header = NULL;
}
static struct ctl_table_header *sctp_sysctl_header;
--
2.43.0
^ permalink raw reply related
* [PATCH] net: usb: rtl8150: handle link status read failures
From: Yousef Alhouseen @ 2026-06-28 9:39 UTC (permalink / raw)
To: Petko Manolov, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: linux-usb, netdev, linux-kernel, stable,
syzbot+9db6c624635564ad813c, Yousef Alhouseen
set_carrier() ignores the result of the USB control transfer and tests
the stack variable supplied as its receive buffer. If the device rejects
or aborts the request, that variable remains uninitialized and the driver
chooses an arbitrary carrier state.
Report carrier down when the link status cannot be read.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+9db6c624635564ad813c@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9db6c624635564ad813c
Cc: stable@vger.kernel.org
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
drivers/net/usb/rtl8150.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index c880c95c41a5..5606490aaea0 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -732,7 +732,11 @@ static void set_carrier(struct net_device *netdev)
rtl8150_t *dev = netdev_priv(netdev);
short tmp;
- get_registers(dev, CSCR, 2, &tmp);
+ if (get_registers(dev, CSCR, 2, &tmp)) {
+ netif_carrier_off(netdev);
+ return;
+ }
+
if (tmp & CSCR_LINK_STATUS)
netif_carrier_on(netdev);
else
--
2.54.0
^ permalink raw reply related
* [PATCH net v3 1/1] net/sched: sch_teql: Introduce slaves_lock to avoid race condition and UAF
From: Jamal Hadi Salim @ 2026-06-28 11:12 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, victor, jiri, security,
zdi-disclosures, stable, Jamal Hadi Salim
The teql master->slaves singly linked list is not protected against
multiple writes. It can be mod'ed concurently from teql_master_xmit(),
teql_dequeue(), teql_init() and teql_destroy() without holding any list
lock or RCU protection.
zdi-disclosures@trendmicro.com has demonstrated that the qdisc is freed
after an RCU grace period, but teql_master_xmit() running on another
CPU can still hold a stale pointer into the list, resulting in a
slab-use-after-free:
BUG: KASAN: slab-use-after-free in teql_master_xmit+0xf0f/0x16b0
Read of size 8 at addr ffff888013fb0440 by task poc/332
Freed 512-byte region [ffff888013fb0400, ffff888013fb0600) (kmalloc-512)
The fix?
Add a per-master slaves_lock spinlock that serializes all mutations of
master->slaves and the NEXT_SLAVE() links in teql_destroy() and
teql_qdisc_init(). teql_master_xmit() also takes the same slaves_lock
around those updates.
Annotate master->slaves and the per-slave ->next pointer with __rcu and
use the appropriate RCU accessors everywhere they are touched:
rcu_assign_pointer() on the writer side (under slaves_lock),
rcu_dereference_protected() for the writer-side loads (also under
slaves_lock), rcu_dereference_bh() for the loads in teql_master_xmit() and
rtnl_dereference() for the loads in teql_master_open()/teql_master_mtu(),
which run under RTNL.
Pair this with rcu_read_lock_bh()/rcu_read_unlock_bh() around the list
traversal in teql_master_xmit(), so that readers either observe a fully
linked list or are deferred until the in-flight mutation completes. The two
early-return paths in teql_master_xmit() are updated to release the RCU-bh
read-side critical section before returning, since leaving it held would
disable BH on that CPU for good.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: zdi-disclosures@trendmicro.com
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
v2->v3
1) Thanks to Simon's persistence:
The writeback in teql_master_xmit() should not blindly write NEXT_SLAVE(q)
into master->slaves. It should re-read master->slaves under slaves_lock and
only update it if q is still the current head
2) Appease sashiko by mentioning teql_dequeue() on the commit and ensuring
consistency on rcu_dereference_bh()/rcu_dereference_protected()
---
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index e7bbc9e5174d..78c74c1182d7 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -52,7 +52,8 @@
struct teql_master {
struct Qdisc_ops qops;
struct net_device *dev;
- struct Qdisc *slaves;
+ struct Qdisc __rcu *slaves;
+ spinlock_t slaves_lock; /* serializes writes to ->slaves */
struct list_head master_list;
unsigned long tx_bytes;
unsigned long tx_packets;
@@ -61,7 +62,7 @@ struct teql_master {
};
struct teql_sched_data {
- struct Qdisc *next;
+ struct Qdisc __rcu *next;
struct teql_master *m;
struct sk_buff_head q;
};
@@ -101,7 +102,9 @@ teql_dequeue(struct Qdisc *sch)
if (skb == NULL) {
struct net_device *m = qdisc_dev(q);
if (m) {
- dat->m->slaves = sch;
+ spin_lock_bh(&dat->m->slaves_lock);
+ rcu_assign_pointer(dat->m->slaves, sch);
+ spin_unlock_bh(&dat->m->slaves_lock);
netif_wake_queue(m);
}
} else {
@@ -132,34 +135,49 @@ teql_destroy(struct Qdisc *sch)
struct Qdisc *q, *prev;
struct teql_sched_data *dat = qdisc_priv(sch);
struct teql_master *master = dat->m;
+ struct netdev_queue *txq = NULL;
+ bool reset_master_queue = false;
if (!master)
return;
- prev = master->slaves;
+ spin_lock_bh(&master->slaves_lock);
+ prev = rcu_dereference_protected(master->slaves,
+ lockdep_is_held(&master->slaves_lock));
if (prev) {
do {
- q = NEXT_SLAVE(prev);
- if (q == sch) {
- NEXT_SLAVE(prev) = NEXT_SLAVE(q);
- if (q == master->slaves) {
- master->slaves = NEXT_SLAVE(q);
- if (q == master->slaves) {
- struct netdev_queue *txq;
-
- txq = netdev_get_tx_queue(master->dev, 0);
- master->slaves = NULL;
-
- dev_reset_queue(master->dev,
- txq, NULL);
- }
- }
- skb_queue_purge(&dat->q);
- break;
+ struct Qdisc *head, *next;
+
+ q = rcu_dereference_protected(NEXT_SLAVE(prev),
+ lockdep_is_held(&master->slaves_lock));
+ if (q != sch) {
+ prev = q;
+ continue;
}
- } while ((prev = q) != master->slaves);
+ next = rcu_dereference_protected(NEXT_SLAVE(q),
+ lockdep_is_held(&master->slaves_lock));
+ rcu_assign_pointer(NEXT_SLAVE(prev), next);
+
+ head = rcu_dereference_protected(master->slaves,
+ lockdep_is_held(&master->slaves_lock));
+ if (q == head) {
+ rcu_assign_pointer(master->slaves, next);
+ if (q == next) {
+ txq = netdev_get_tx_queue(master->dev, 0);
+ rcu_assign_pointer(master->slaves, NULL);
+ reset_master_queue = true;
+ }
+ }
+ skb_queue_purge(&dat->q);
+ break;
+ } while (prev != rcu_dereference_protected(master->slaves,
+ lockdep_is_held(&master->slaves_lock)));
}
+ spin_unlock_bh(&master->slaves_lock);
+
+ if (reset_master_queue)
+ dev_reset_queue(master->dev, txq, NULL);
}
static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
@@ -168,6 +186,7 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
struct net_device *dev = qdisc_dev(sch);
struct teql_master *m = (struct teql_master *)sch->ops;
struct teql_sched_data *q = qdisc_priv(sch);
+ struct Qdisc *first;
if (dev->hard_header_len > m->dev->hard_header_len)
return -EINVAL;
@@ -184,7 +203,9 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
skb_queue_head_init(&q->q);
- if (m->slaves) {
+ spin_lock_bh(&m->slaves_lock);
+ first = rcu_dereference_protected(m->slaves, lockdep_is_held(&m->slaves_lock));
+ if (first) {
if (m->dev->flags & IFF_UP) {
if ((m->dev->flags & IFF_POINTOPOINT &&
!(dev->flags & IFF_POINTOPOINT)) ||
@@ -192,8 +213,10 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
!(dev->flags & IFF_BROADCAST)) ||
(m->dev->flags & IFF_MULTICAST &&
!(dev->flags & IFF_MULTICAST)) ||
- dev->mtu < m->dev->mtu)
+ dev->mtu < m->dev->mtu) {
+ spin_unlock_bh(&m->slaves_lock);
return -EINVAL;
+ }
} else {
if (!(dev->flags&IFF_POINTOPOINT))
m->dev->flags &= ~IFF_POINTOPOINT;
@@ -204,14 +227,17 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
if (dev->mtu < m->dev->mtu)
m->dev->mtu = dev->mtu;
}
- q->next = NEXT_SLAVE(m->slaves);
- NEXT_SLAVE(m->slaves) = sch;
+ rcu_assign_pointer(q->next,
+ rcu_dereference_protected(NEXT_SLAVE(first),
+ lockdep_is_held(&m->slaves_lock)));
+ rcu_assign_pointer(NEXT_SLAVE(first), sch);
} else {
- q->next = sch;
- m->slaves = sch;
+ rcu_assign_pointer(q->next, sch);
+ rcu_assign_pointer(m->slaves, sch);
m->dev->mtu = dev->mtu;
m->dev->flags = (m->dev->flags&~FMASK)|(dev->flags&FMASK);
}
+ spin_unlock_bh(&m->slaves_lock);
return 0;
}
@@ -285,7 +311,9 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
int subq = skb_get_queue_mapping(skb);
struct sk_buff *skb_res = NULL;
- start = master->slaves;
+ rcu_read_lock_bh();
+
+ start = rcu_dereference_bh(master->slaves);
restart:
nores = 0;
@@ -317,10 +345,17 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_start_xmit(skb, slave, slave_txq, false) ==
NETDEV_TX_OK) {
__netif_tx_unlock(slave_txq);
- master->slaves = NEXT_SLAVE(q);
+ spin_lock_bh(&master->slaves_lock);
+ if (rcu_dereference_protected(master->slaves,
+ lockdep_is_held(&master->slaves_lock)) == q)
+ rcu_assign_pointer(master->slaves,
+ rcu_dereference_protected(NEXT_SLAVE(q),
+ lockdep_is_held(&master->slaves_lock)));
+ spin_unlock_bh(&master->slaves_lock);
netif_wake_queue(dev);
master->tx_packets++;
master->tx_bytes += length;
+ rcu_read_unlock_bh();
return NETDEV_TX_OK;
}
__netif_tx_unlock(slave_txq);
@@ -329,14 +364,21 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
busy = 1;
break;
case 1:
- master->slaves = NEXT_SLAVE(q);
+ spin_lock_bh(&master->slaves_lock);
+ if (rcu_dereference_protected(master->slaves,
+ lockdep_is_held(&master->slaves_lock)) == q)
+ rcu_assign_pointer(master->slaves,
+ rcu_dereference_protected(NEXT_SLAVE(q),
+ lockdep_is_held(&master->slaves_lock)));
+ spin_unlock_bh(&master->slaves_lock);
+ rcu_read_unlock_bh();
return NETDEV_TX_OK;
default:
nores = 1;
break;
}
__skb_pull(skb, skb_network_offset(skb));
- } while ((q = NEXT_SLAVE(q)) != start);
+ } while ((q = rcu_dereference_bh(NEXT_SLAVE(q))) != start);
if (nores && skb_res == NULL) {
skb_res = skb;
@@ -345,29 +387,32 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
if (busy) {
netif_stop_queue(dev);
+ rcu_read_unlock_bh();
return NETDEV_TX_BUSY;
}
master->tx_errors++;
drop:
master->tx_dropped++;
+ rcu_read_unlock_bh();
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static int teql_master_open(struct net_device *dev)
{
- struct Qdisc *q;
+ struct Qdisc *q, *first;
struct teql_master *m = netdev_priv(dev);
int mtu = 0xFFFE;
unsigned int flags = IFF_NOARP | IFF_MULTICAST;
- if (m->slaves == NULL)
+ first = rtnl_dereference(m->slaves);
+ if (!first)
return -EUNATCH;
flags = FMASK;
- q = m->slaves;
+ q = first;
do {
struct net_device *slave = qdisc_dev(q);
@@ -389,7 +434,7 @@ static int teql_master_open(struct net_device *dev)
flags &= ~IFF_BROADCAST;
if (!(slave->flags&IFF_MULTICAST))
flags &= ~IFF_MULTICAST;
- } while ((q = NEXT_SLAVE(q)) != m->slaves);
+ } while ((q = rtnl_dereference(NEXT_SLAVE(q))) != first);
m->dev->mtu = mtu;
m->dev->flags = (m->dev->flags&~FMASK) | flags;
@@ -417,14 +462,15 @@ static void teql_master_stats64(struct net_device *dev,
static int teql_master_mtu(struct net_device *dev, int new_mtu)
{
struct teql_master *m = netdev_priv(dev);
- struct Qdisc *q;
+ struct Qdisc *q, *first;
- q = m->slaves;
+ first = rtnl_dereference(m->slaves);
+ q = first;
if (q) {
do {
if (new_mtu > qdisc_dev(q)->mtu)
return -EINVAL;
- } while ((q = NEXT_SLAVE(q)) != m->slaves);
+ } while ((q = rtnl_dereference(NEXT_SLAVE(q))) != first);
}
WRITE_ONCE(dev->mtu, new_mtu);
@@ -444,6 +490,7 @@ static __init void teql_master_setup(struct net_device *dev)
struct teql_master *master = netdev_priv(dev);
struct Qdisc_ops *ops = &master->qops;
+ spin_lock_init(&master->slaves_lock);
master->dev = dev;
ops->priv_size = sizeof(struct teql_sched_data);
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox