* Re: [PATCH] net: stmmac: Avoid freeing and re-requesting IRQ during XDP set prog
From: Daniel Thompson @ 2026-07-07 9:48 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev
Cc: Alex Elder, netdev, linux-stm32, linux-arm-kernel, linux-kernel,
bpf
In-Reply-To: <20260706-tc956x-stmmac-no_irq_teardown-v1-1-df009d0272bf@riscstar.com>
On Mon, Jul 06, 2026 at 05:17:58PM +0100, Daniel Thompson wrote:
> Currently stmmac will run a full cycle of IRQ tear down and setup when
> setting up a new XDP program. This makes tuning TSN systems difficult
> because whenever a new XDP program is installed then the irq threads will
> be stopped and restarted which will undo any thread tuning.
>
> The problem is avoided by removing stmmac_free_irq()/stmmac_request_irq()
> from stmmac_xdp_release()/stmmac_xdp_open().
>
> stmmac_free_irq() implicitly synchronizes interrupts and, with that
> removed, I was unable to prove that later actions in
> stmmac_xdp_release() are safe when there are concurrent interrupts. To
> avoid problems let's also move the code to disable DMA interrupts earlier
> in the sequence and explicitly sync the interrupts handler(s).
>
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
> <snip>
> @@ -7156,10 +7201,8 @@ int stmmac_xdp_open(struct net_device *dev)
> stmmac_reset_queues_param(priv);
>
> /* DMA CSR Channel configuration */
> - for (chan = 0; chan < dma_csr_ch; chan++) {
> + for (chan = 0; chan < dma_csr_ch; chan++)
> stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> - stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> - }
Sashiko picked up that stmmac_init_chan() has the effect of enabling DMA
irqs, making this code unsafe.
Given stmmac_xdp_open() can only be called on a running interface (and that
stmmac_xdp_open() explicitly sets sph) then re-initializing with stmmac_init_chan()
should have no effect and we can drop that as well.
I'll double check with a code review across all the dwmac versions
before pushing out a v2!
Daniel.
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: ethernet: qualcomm: Unconstify function arguments passed by value
From: patchwork-bot+netdevbpf @ 2026-07-07 9:50 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: jie.luo, andrew+netdev, davem, edumazet, kuba, pabeni, netdev,
linux-kernel
In-Reply-To: <20260702094908.79859-3-krzysztof.kozlowski@oss.qualcomm.com>
Hello:
This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Thu, 2 Jul 2026 11:49:09 +0200 you wrote:
> There is no benefit in marking "const" a pass-by-value (not a pointer)
> function argument, because it is passed as a copy on the stack. No code
> readability improvements, no additional compiler-time safety for misuse.
> Drop such redundant "const".
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> [...]
Here is the summary with links:
- [net-next,1/2] net: ethernet: qualcomm: Unconstify function arguments passed by value
https://git.kernel.org/netdev/net-next/c/e0421c6fd39d
- [net-next,2/2] net: ethernet: qualcomm: Constify "queue_map" in ppe_ring_queue_map_set()
https://git.kernel.org/netdev/net-next/c/cefd16657c1d
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 v6 3/3] net: libwx: support vf per-queue statistics via ethtool -S
From: Paolo Abeni @ 2026-07-07 9:50 UTC (permalink / raw)
To: mengyuanlou; +Cc: netdev, jiawenwu, duanqiangwen, horms, kuba, pabeni
In-Reply-To: <20260701100145.23738-4-mengyuanlou@net-swift.com>
From: AI Reviewer <ai@example.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
Now I have enough information to produce the report.
commit e59c58bb080afb34cac34c91b8c320a1f05134e6
Author: Mengyuan Lou <mengyuanlou@net-swift.com>
net: libwx: support vf per-queue statistics via ethtool -S
The patch wires wx_get_sset_count, wx_get_strings, and wx_get_ethtool_stats
into wx_ethtool_ops_vf, adds a small vf-only global stats table, and starts
calling wx_update_stats() from wxvf_service_task. It also adds NULL checks
for wx->rx_ring[i] / wx->tx_ring[i] inside wx_update_stats.
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
> index 22037f015ded..f72908630ea4 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
[ ... ]
> @@ -114,7 +133,7 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
> ethtool_sprintf(&p, "tx_queue_%u_packets", i);
> ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
> }
> - for (i = 0; i < WX_NUM_RX_QUEUES; i++) {
> + for (i = 0; i < WX_NUM_RX_QUEUES(netdev); i++) {
> ethtool_sprintf(&p, "rx_queue_%u_packets", i);
> ethtool_sprintf(&p, "rx_queue_%u_bytes", i);
> }
[ ... ]
> @@ -852,6 +878,9 @@ static const struct ethtool_ops wx_ethtool_ops_vf = {
> .set_coalesce = wx_set_coalesce,
> .get_ts_info = ethtool_op_get_ts_info,
> .get_link_ksettings = wx_get_link_ksettings_vf,
> + .get_sset_count = wx_get_sset_count,
> + .get_strings = wx_get_strings,
> + .get_ethtool_stats = wx_get_ethtool_stats,
> };
[Medium]
Before this change wx_ethtool_ops_vf had no get_sset_count / get_strings /
get_ethtool_stats callbacks, so the VF exposed no ethtool -S output at all.
Wiring these in also picks up the shared per-queue string loop that emits
tx_queue_%u_packets / tx_queue_%u_bytes and rx_queue_%u_packets /
rx_queue_%u_bytes.
Per-queue TX/RX packet and byte counters are a category that already has a
standard uAPI (netdev_stat_ops with queue_stats_rx / queue_stats_tx,
surfaced by netlink and ynl). Documentation/networking/statistics.rst and
the ethtool -S guidance state that new counters covering values that have a
standard uAPI should not be added to ethtool -S even when the driver does
not yet implement the standard interface.
The wangxun tree does not implement netdev_stat_ops (no
get_base_stats / get_queue_stats_rx / get_queue_stats_tx callbacks are
present under drivers/net/ethernet/wangxun/).
Would it be preferable to expose the per-queue counters on the VF via
netdev_stat_ops instead of adding them to ethtool -S here?
> void wx_set_ethtool_ops_vf(struct net_device *netdev)
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> index 260e14d5d541..349afbe60132 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
> @@ -2886,6 +2886,8 @@ void wx_update_stats(struct wx *wx)
> for (i = 0; i < wx->num_rx_queues; i++) {
> struct wx_ring *rx_ring = wx->rx_ring[i];
>
> + if (!rx_ring)
> + continue;
> non_eop_descs += rx_ring->rx_stats.non_eop_descs;
[ ... ]
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
> index 26de78e9a69e..1d84fe35d7d9 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
> @@ -409,6 +410,7 @@ static void wxvf_service_task(struct work_struct *work)
>
> wxvf_link_config_subtask(wx);
> wxvf_reset_subtask(wx);
> + wx_update_stats(wx);
> wx_service_event_complete(wx);
> }
[High]
Can this call race with VF PCI suspend and shutdown to produce a
use-after-free on wx->rx_ring[i] / wx->tx_ring[i]?
Both ngbevf and txgbevf use wxvf_suspend as their PM suspend callback and
wxvf_shutdown (which calls wxvf_suspend) as their pci_driver ->shutdown
callback:
static DEFINE_SIMPLE_DEV_PM_OPS(ngbevf_pm_ops, wxvf_suspend, wxvf_resume);
...
.shutdown = wxvf_shutdown,
wxvf_suspend() in wx_vf_common.c does:
int wxvf_suspend(struct device *dev_d)
{
struct pci_dev *pdev = to_pci_dev(dev_d);
struct wx *wx = pci_get_drvdata(pdev);
netif_device_detach(wx->netdev);
wx_clear_interrupt_scheme(wx);
pci_disable_device(pdev);
return 0;
}
wx_clear_interrupt_scheme() ends up freeing the q_vectors (via
kfree_rcu), and the ring allocations are embedded in the q_vector, so
wx->rx_ring[i] / wx->tx_ring[i] end up pointing at memory that will be
freed after an RCU grace period.
wxvf_suspend / wxvf_shutdown do not call timer_shutdown_sync on
wx->service_timer or cancel_work_sync on wx->service_task, and they do
not set WX_STATE_DOWN.
With this hunk in place, the service_task now walks wx->rx_ring[] and
wx->tx_ring[]:
void wx_update_stats(struct wx *wx)
{
...
for (i = 0; i < wx->num_rx_queues; i++) {
struct wx_ring *rx_ring = wx->rx_ring[i];
if (!rx_ring)
continue;
non_eop_descs += rx_ring->rx_stats.non_eop_descs;
...
}
...
for (i = 0; i < wx->num_tx_queues; i++) {
struct wx_ring *tx_ring = wx->tx_ring[i];
if (!tx_ring)
continue;
restart_queue += tx_ring->tx_stats.restart_queue;
...
}
If the service_task latches a non-NULL rx_ring / tx_ring pointer just
before wx_clear_interrupt_scheme runs, the added NULL check does not
help, and the subsequent ->rx_stats / ->tx_stats reads touch memory
that has been kfree_rcu'd. wxvf_remove() covers this by calling
timer_shutdown_sync + cancel_work_sync before wx_clear_interrupt_scheme,
but wxvf_suspend / wxvf_shutdown do not.
Should wxvf_suspend (and hence wxvf_shutdown) quiesce the service_timer
and service_task, or set WX_STATE_DOWN, before wx_clear_interrupt_scheme
now that wx_update_stats is on the service_task's call path?
--
This is an AI-generated review.
^ permalink raw reply
* Re: [PATCH net] nfc: clear active_target when the target list is replaced
From: Simon Horman @ 2026-07-07 10:00 UTC (permalink / raw)
To: dddddd
Cc: Simon Horman, netdev, david, davem, edumazet, kuba, pabeni, dzm91,
hust-os-kernel-patches
In-Reply-To: <20260625111835.2411251-1-dddddd@hust.edu.cn>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
nfc: clear active_target when the target list is replaced
This patch clears dev->active_target, stops the check_presence timer, and
resets RF and DEP link states in nfc_targets_found() if the currently
active target's array is being replaced. This prevents leaving a dangling
pointer when the target array is freed.
> diff --git a/net/nfc/core.c b/net/nfc/core.c
> index a92a6566e6a0d..950807906645a 100644
> --- a/net/nfc/core.c
> +++ b/net/nfc/core.c
> @@ -786,6 +786,21 @@ int nfc_targets_found(struct nfc_dev *dev,
>
> dev->targets_generation++;
>
> + if (dev->active_target && dev->targets) {
> + for (i = 0; i < dev->n_targets; i++) {
> + if (dev->active_target != &dev->targets[i])
> + continue;
> +
> + if (dev->ops->check_presence)
> + timer_delete_sync(&dev->check_pres_timer);
> +
> + dev->active_target = NULL;
> + dev->dep_link_up = false;
> + dev->rf_mode = NFC_RF_NONE;
> + break;
[Severity: High]
Could this cause a regression by bypassing the required driver and LLCP
teardown sequences?
By directly setting dev->dep_link_up = false, any subsequent user-space
call to nfc_dep_link_down() will return -EALREADY early. This permanently
skips nfc_llcp_mac_is_down(), which leaks LLCP sockets.
Also, it appears the hardware drivers will never receive the deactivate
signal since dev->ops->deactivate_target() and dev->ops->dep_link_down()
are bypassed. Could this lead to a hardware lockup or denial of service?
> + }
> + }
> +
> kfree(dev->targets);
> dev->targets = NULL;
[Severity: High]
This is a pre-existing issue, but I noticed that nfc_dep_link_is_up()
accesses and modifies core NFC state variables locklessly:
net/nfc/core.c:nfc_dep_link_is_up() {
dev->dep_link_up = true;
if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
...
target = nfc_find_target(dev, target_idx);
...
}
Drivers (like pn533) call nfc_dep_link_is_up() asynchronously without
holding device_lock(&dev->dev). Since nfc_targets_found() and
nfc_target_lost() can free and reallocate dev->targets while holding
the lock, could nfc_find_target() iterate over freed memory if it races
with them?
Furthermore, could this lockless access allow nfc_dep_link_is_up() to
assign a dangling pointer to dev->active_target right after it is
cleared by nfc_targets_found(), defeating the safety checks introduced
by this patch?
^ permalink raw reply
* Re: [PATCH net] nfc: clear active_target when the target list is replaced
From: Simon Horman @ 2026-07-07 10:01 UTC (permalink / raw)
To: dddddd
Cc: Simon Horman, netdev, david, davem, edumazet, kuba, pabeni, dzm91,
hust-os-kernel-patches
In-Reply-To: <20260625111835.2411251-1-dddddd@hust.edu.cn>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
nfc: clear active_target when the target list is replaced
This patch updates nfc_targets_found() so that when the active target
points into the dev->targets array about to be freed, the cached pointer
is cleared and a partial teardown (presence-check timer stop, dep_link_up
cleared, rf_mode reset) is performed before kfree(dev->targets).
> diff --git a/net/nfc/core.c b/net/nfc/core.c
> index a92a6566e6a0..950807906645 100644
> --- a/net/nfc/core.c
> +++ b/net/nfc/core.c
> @@ -786,6 +786,21 @@ int nfc_targets_found(struct nfc_dev *dev,
>
> dev->targets_generation++;
>
> + if (dev->active_target && dev->targets) {
> + for (i = 0; i < dev->n_targets; i++) {
> + if (dev->active_target != &dev->targets[i])
> + continue;
> +
> + if (dev->ops->check_presence)
> + timer_delete_sync(&dev->check_pres_timer);
> +
> + dev->active_target = NULL;
> + dev->dep_link_up = false;
> + dev->rf_mode = NFC_RF_NONE;
> + break;
> + }
> + }
> +
[Medium]
The commit message says this teardown mirrors what nfc_deactivate_target()
does, but nfc_deactivate_target() does not touch dev->dep_link_up at all.
Forcing dep_link_up = false here when the active target was set up via
nfc_dep_link_up() introduces a state mutation that is not described in
the commit log.
Can this leave DEP/LLCP state only partially torn down?
Compared to nfc_dep_link_down(), this new branch skips:
rc = dev->ops->dep_link_down(dev);
...
nfc_llcp_mac_is_down(dev);
nfc_genl_dep_link_down_event(dev);
so the driver is never told to bring the DEP link down, LLCP sockets
bound to the local are not released via nfc_llcp_socket_release(), and
no NFC_EVENT_DEP_LINK_DOWN is sent to userspace.
A subsequent userspace nfc_dep_link_down() will then be rejected here:
net/nfc/core.c:nfc_dep_link_down() {
...
if (dev->dep_link_up == false) {
rc = -EALREADY;
goto error;
}
...
}
so the normal cleanup path that calls nfc_llcp_mac_is_down() is no
longer reachable from userspace until device unregister.
Does this risk leaking the LLCP sockets that were created while
dep_link_up was true?
If the goal is just to clear the dangling active_target pointer, would
it be enough to clear dev->active_target (and stop the presence-check
timer) without also forcing dep_link_up = false and rf_mode = NFC_RF_NONE?
Alternatively, if a full DEP teardown is intended, should this path call
dev->ops->dep_link_down(dev) and nfc_llcp_mac_is_down(dev) like
nfc_dep_link_down() does?
^ permalink raw reply
* Re: [PATCH bpf-next 2/6] bpf: Add ksock kfuncs
From: Mahe Tardy @ 2026-07-07 10:06 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: andrew+netdev, andrii, ast, bpf, daniel, davem, eddyz87, edumazet,
john.fastabend, kuba, liamwisehart, martin.lau, netdev, pabeni,
song
In-Reply-To: <20260706230142.1691146-1-kuniyu@google.com>
On Mon, Jul 06, 2026 at 11:01:27PM +0000, Kuniyuki Iwashima wrote:
> From: Mahe Tardy <mahe.tardy@gmail.com>
> Date: Mon, 6 Jul 2026 09:35:21 +0000
> > diff --git a/net/core/bpf_ksock.c b/net/core/bpf_ksock.c
> [...]
> > +static bool bpf_ksock_send_enter(struct bpf_ksock_send_guard *guard)
>
> Can we do this better with assigning a single bit to task_struct ?
Yes, that would be way simpler but I avoided touching task_struct. If we
are okay with that then it could be simplified.
>
> > +{
> > + struct bpf_ksock_send_guard *entry;
> > + struct hlist_bl_node *pos;
> > + struct bpf_ksock_send_bucket *bucket;
> > +
> > + bucket = bpf_ksock_send_bucket(current);
> > + hlist_bl_lock(&bucket->head);
> > + hlist_bl_for_each_entry(entry, pos, &bucket->head, node) {
> > + if (entry->task == current) {
> > + hlist_bl_unlock(&bucket->head);
> > + return false;
> > + }
> > + }
> > +
> > + guard->task = current;
> > + INIT_HLIST_BL_NODE(&guard->node);
> > + hlist_bl_add_head(&guard->node, &bucket->head);
> > + hlist_bl_unlock(&bucket->head);
> > + return true;
> > +}
> > +
> > +static void bpf_ksock_send_exit(struct bpf_ksock_send_guard *guard)
> > +{
> > + struct bpf_ksock_send_bucket *bucket;
> > +
> > + bucket = bpf_ksock_send_bucket(guard->task);
> > + hlist_bl_lock(&bucket->head);
> > + hlist_bl_del(&guard->node);
> > + hlist_bl_unlock(&bucket->head);
> > +}
> [...]
> > +__bpf_kfunc struct bpf_ksock *
> > +bpf_ksock_create(const struct bpf_ksock_create_opts *opts, u32 opts__sz,
> > + int *err__uninit)
> > +{
> > + struct bpf_ksock_create_opts opts_copy;
> > + struct bpf_ksock *ks;
> > + struct net *net;
> > + int err;
> > +
> > + /*
> > + * sock_create() derives the network namespace, credentials, and cgroup
> > + * from current. Kernel threads, including BPF workqueue callbacks, do
> > + * not carry the context of the task that invoked the BPF program.
> > + */
> > + if (!bpf_ksock_has_user_task_context()) {
> > + err = -EOPNOTSUPP;
> > + goto err_out;
> > + }
> > +
> > + if (!opts || opts__sz != sizeof(struct bpf_ksock_create_opts)) {
> > + err = -EINVAL;
> > + goto err_out;
> > + }
> > +
> > + opts_copy = (struct bpf_ksock_create_opts){
> > + .family = READ_ONCE(opts->family),
> > + .type = READ_ONCE(opts->type),
> > + .protocol = READ_ONCE(opts->protocol),
> > + .reserved = READ_ONCE(opts->reserved),
> > + };
> > +
> > + if (opts_copy.reserved) {
> > + err = -EINVAL;
> > + goto err_out;
> > + }
> > +
> > + if (opts_copy.family != AF_INET && opts_copy.family != AF_INET6) {
> > + err = -EAFNOSUPPORT;
> > + goto err_out;
> > + }
> > +
> > + if (opts_copy.type != SOCK_DGRAM) {
> > + err = -EPROTONOSUPPORT;
> > + goto err_out;
> > + }
> > +
> > + if (opts_copy.protocol != IPPROTO_UDP && opts_copy.protocol != 0) {
> > + err = -EPROTONOSUPPORT;
> > + goto err_out;
> > + }
> > +
> > + ks = kzalloc_obj(*ks);
> > + if (!ks) {
> > + err = -ENOMEM;
> > + goto err_out;
> > + }
> > +
> > + net = current->nsproxy->net_ns;
> > + if (!bpf_ksock_net_try_charge(net)) {
> > + err = -ENOSPC;
> > + goto err_free;
> > + }
> > +
> > + /*
> > + * Use the normal current-task socket path so LSM/cgroup policy,
> > + * socket labels, and the active netns reference match a socket(2)
> > + * created by the BPF program's caller.
> > + */
> > + err = sock_create(opts_copy.family, opts_copy.type, opts_copy.protocol,
> > + &ks->sock);
>
> This also triggers LSM in __sock_create() so needs the loop
> detection, no ?
>
> Same for __sys_bind_socket() and __sys_connect_socket().
This should be okay as create/bind/connect can only be called from
SYSCALL progs and not LSM progs. We only care about recursion from the
kfuncs in the ksock_kfunc_btf_ids group which are also allowed from LSM
progs (release/acquire/send).
>
>
> > + if (err)
> > + goto err_uncharge;
> > +
> > + ks->sock->sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
> > + ks->sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
> > +
> > + refcount_set(&ks->usage, 1);
> > + put_unaligned(0, err__uninit);
> > + return ks;
> > +
> > +err_uncharge:
> > + bpf_ksock_net_uncharge(net);
> > +err_free:
> > + kfree(ks);
> > +err_out:
> > + put_unaligned(err, err__uninit);
> > + return NULL;
> > +}
> > +
> > +/**
> > + * bpf_ksock_bind() - Bind a BPF kernel socket to a local address.
> > + * @ks: The BPF kernel socket context.
> > + * @opts: Pointer to struct bpf_ksock_addr_opts with local address.
> > + * @opts__sz: Size of the opts struct.
> > + *
> > + * Binds the socket to the specified local address and port.
> > + * This is optional; if not called, the kernel will auto-assign.
> > + *
> > + * This function may sleep while binding the socket, so it can only be used in
> > + * sleepable BPF programs (SYSCALL).
> > + *
> > + * Return: 0 on success, negative errno on error.
> > + */
> > +__bpf_kfunc int bpf_ksock_bind(struct bpf_ksock *ks,
> > + const struct bpf_ksock_addr_opts *opts,
> > + u32 opts__sz)
> > +{
> > + struct sockaddr_storage addr = {};
>
> nit: we don't need to initialise here since bpf_ksock_get_addr() does.
Ah actually I didn't know that compound literal in C would zero the rest
of the struct. Thanks, let's remove those two then.
>
> > + int addrlen;
> > +
> > + if (!bpf_ksock_has_user_task_context())
> > + return -EOPNOTSUPP;
> > +
> > + addrlen = bpf_ksock_get_addr(opts, opts__sz, &addr);
> > + if (addrlen < 0)
> > + return addrlen;
> > +
> > + return __sys_bind_socket(ks->sock, &addr, addrlen);
> > +}
> > +
> > +/**
> > + * bpf_ksock_connect() - Connect a BPF kernel socket to a remote address.
> > + * @ks: The BPF kernel socket context.
> > + * @opts: Pointer to struct bpf_ksock_addr_opts with remote address.
> > + * @opts__sz: Size of the opts struct.
> > + *
> > + * Connects the socket to the specified remote address and port.
> > + *
> > + * This function may sleep while connecting the socket, so it can only be used
> > + * in sleepable BPF programs (SYSCALL).
> > + *
> > + * Return: 0 on success, negative errno on error.
> > + */
> > +__bpf_kfunc int bpf_ksock_connect(struct bpf_ksock *ks,
> > + const struct bpf_ksock_addr_opts *opts,
> > + u32 opts__sz)
> > +{
> > + struct sockaddr_storage addr = {};
>
> Same.
Noted
^ permalink raw reply
* [PATCH v7 0/3] Rust netlink support + use in Rust Binder
From: Alice Ryhl @ 2026-07-07 10:06 UTC (permalink / raw)
To: Carlos Llamas, Greg Kroah-Hartman, Andrew Lunn, Donald Hunter,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Matthew Maurer
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Christian Brauner, linux-kernel, rust-for-linux, netdev,
Alice Ryhl
The C Binder driver exposes messages over netlink when transactions
fail, so that a userpace daemon can respond to processes with many
failing transactions.
This patch series adds netlink support from Rust, then implements an
equivalent API in Rust Binder.
As Binder only uses broadcast messages, I did not add support for other
kinds of messages.
This series is based on top of the result of merging together the two
branches 'char-misc/char-misc-linus' and 'char-misc/char-misc-next'.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Changes in v7:
- Rebase on char-misc-linus and char-misc-next.
- Fix conflict with commit 77bfebf11077 ("rust_binder: fix BINDER_GET_EXTENDED_ERROR")
- Pick up tags
- Link to v6: https://lore.kernel.org/r/20260529-binder-netlink-v6-0-92dd74b6a32e@google.com
Changes in v6:
- Introduce MAINTAINERS entry update for net files.
- Move netlink.rs to rust/kernel/net/.
- Tweak info.reply logic in Binder patch.
- Link to v5: https://lore.kernel.org/r/20260525-binder-netlink-v5-0-a90e2923ebeb@google.com
Changes in v5:
- Remove patch 2.
- Squash patches 3 and 4.
- Link to v4: https://lore.kernel.org/r/20260504-binder-netlink-v4-0-601b41cd25b2@google.com
Changes in v4:
- Fix typo in 'report netlink transactions' commit message.
- Document that some methods are for const context only.
- Rebase and pick up tags.
- Link to v3: https://lore.kernel.org/r/20260415-binder-netlink-v3-0-84be9ba63ee2@google.com
Changes in v3:
- Fix spurious 'return' statements in Rust helpers (Patch 1).
- Sashiko review:
- Fix ynl_gen to handle empty multicast groups and correct multicast indexing (Patch 2).
- Fix transaction failed reply logic to report via Netlink inside reply_inner() (Patch 4).
- Link to v2: https://lore.kernel.org/r/20260408-binder-netlink-v2-0-c0d327d15435@google.com
Changes in v2:
- Make inclusion of to_pid conditional too.
- Add note about file name in second patch.
- Make it clear that the sk_buff wrapper is netlink-specific.
- Better handle bitfield in patch 1.
- Link to v1: https://lore.kernel.org/r/20260306-binder-netlink-v1-0-daceb5bc83f2@google.com
---
Alice Ryhl (2):
rust: net: add rust/kernel/net to NETWORKING [GENERAL]
rust: netlink: add raw netlink abstraction
Carlos Llamas (1):
rust_binder: report netlink transactions
MAINTAINERS | 2 +
drivers/android/Kconfig | 2 +-
drivers/android/binder/netlink.rs | 117 ++++++++++
drivers/android/binder/rust_binder_main.rs | 8 +-
drivers/android/binder/thread.rs | 11 +-
drivers/android/binder/transaction.rs | 40 ++++
rust/bindings/bindings_helper.h | 3 +
rust/helpers/helpers.c | 1 +
rust/helpers/net/genetlink.c | 46 ++++
rust/kernel/{net.rs => net/mod.rs} | 2 +
rust/kernel/net/netlink.rs | 337 +++++++++++++++++++++++++++++
rust/uapi/uapi_helper.h | 1 +
12 files changed, 566 insertions(+), 4 deletions(-)
---
base-commit: 2c7a7db3aa6370f46761b6d8eb821f5bde8901eb
change-id: 20260306-binder-netlink-c82110b2fb74
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply
* [PATCH v7 1/3] rust: net: add rust/kernel/net to NETWORKING [GENERAL]
From: Alice Ryhl @ 2026-07-07 10:06 UTC (permalink / raw)
To: Carlos Llamas, Greg Kroah-Hartman, Andrew Lunn, Donald Hunter,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Matthew Maurer
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Christian Brauner, linux-kernel, rust-for-linux, netdev,
Alice Ryhl
In-Reply-To: <20260707-binder-netlink-v7-0-42b40e4b1ac8@google.com>
To ensure that networking code can be found in a single shared place,
add it to the relevant NETWORKING entry. The net.rs file is moved into
the net/ directory so that it's included under the MAINTAINERS entry
without needing a separate rust/kernel/net.rs entry.
Reviewed-by: Carlos Llamas <cmllamas@google.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
MAINTAINERS | 2 ++
rust/kernel/{net.rs => net/mod.rs} | 0
2 files changed, 2 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a9..303a06da4279 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18849,6 +18849,8 @@ F: include/uapi/linux/sctp.h
F: lib/net_utils.c
F: lib/random32.c
F: net/
+F: rust/helpers/net/
+F: rust/kernel/net/
F: samples/pktgen/
F: tools/net/
F: tools/testing/selftests/net/
diff --git a/rust/kernel/net.rs b/rust/kernel/net/mod.rs
similarity index 100%
rename from rust/kernel/net.rs
rename to rust/kernel/net/mod.rs
--
2.55.0.rc2.803.g1fd1e6609c-goog
^ permalink raw reply related
* [PATCH v7 2/3] rust: netlink: add raw netlink abstraction
From: Alice Ryhl @ 2026-07-07 10:06 UTC (permalink / raw)
To: Carlos Llamas, Greg Kroah-Hartman, Andrew Lunn, Donald Hunter,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Matthew Maurer
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Christian Brauner, linux-kernel, rust-for-linux, netdev,
Alice Ryhl
In-Reply-To: <20260707-binder-netlink-v7-0-42b40e4b1ac8@google.com>
This implements a safe and relatively simple API over the netlink API,
that allows you to add different attributes to a netlink message and
broadcast it. As the first user of this API only makes use of broadcast,
only broadcast messages are supported here.
This API is intended to be safe and to be easy to use in *generated*
code. This is because netlink is generally used with yaml files that
describe the underlying API, and the python generator outputs C code
(or, soon, Rust code) that lets you use the API more easily. So for
example, if there is a string field, the code generator will output a
method that internall calls `put_string()` with the right attr type.
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Carlos Llamas <cmllamas@google.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/bindings/bindings_helper.h | 3 +
rust/helpers/helpers.c | 1 +
rust/helpers/net/genetlink.c | 46 ++++++
rust/kernel/net/mod.rs | 2 +
rust/kernel/net/netlink.rs | 337 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 389 insertions(+)
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 1124785e210b..ec96e811610d 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -93,6 +93,8 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/xarray.h>
+#include <net/genetlink.h>
+#include <net/netlink.h>
#include <trace/events/rust_sample.h>
/*
@@ -110,6 +112,7 @@
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN;
const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
+const size_t RUST_CONST_HELPER_GENLMSG_DEFAULT_SIZE = GENLMSG_DEFAULT_SIZE;
const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL_ACCOUNT = GFP_KERNEL_ACCOUNT;
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 998e31052e66..1d4ee51f576b 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -72,6 +72,7 @@
#include "maple_tree.c"
#include "mm.c"
#include "mutex.c"
+#include "net/genetlink.c"
#include "of.c"
#include "page.c"
#include "pci.c"
diff --git a/rust/helpers/net/genetlink.c b/rust/helpers/net/genetlink.c
new file mode 100644
index 000000000000..3530b69f6cf7
--- /dev/null
+++ b/rust/helpers/net/genetlink.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2026 Google LLC.
+ */
+
+#include <net/genetlink.h>
+
+#ifdef CONFIG_NET
+
+__rust_helper struct sk_buff *rust_helper_genlmsg_new(size_t payload, gfp_t flags)
+{
+ return genlmsg_new(payload, flags);
+}
+
+__rust_helper
+int rust_helper_genlmsg_multicast(const struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
+ unsigned int group, gfp_t flags)
+{
+ return genlmsg_multicast(family, skb, portid, group, flags);
+}
+
+__rust_helper void rust_helper_genlmsg_cancel(struct sk_buff *skb, void *hdr)
+{
+ genlmsg_cancel(skb, hdr);
+}
+
+__rust_helper void rust_helper_genlmsg_end(struct sk_buff *skb, void *hdr)
+{
+ genlmsg_end(skb, hdr);
+}
+
+__rust_helper void rust_helper_nlmsg_free(struct sk_buff *skb)
+{
+ nlmsg_free(skb);
+}
+
+__rust_helper
+int rust_helper_genl_has_listeners(const struct genl_family *family,
+ struct net *net, unsigned int group)
+{
+ return genl_has_listeners(family, net, group);
+}
+
+#endif
diff --git a/rust/kernel/net/mod.rs b/rust/kernel/net/mod.rs
index fe415cb369d3..8ecae7577ed2 100644
--- a/rust/kernel/net/mod.rs
+++ b/rust/kernel/net/mod.rs
@@ -4,3 +4,5 @@
#[cfg(CONFIG_RUST_PHYLIB_ABSTRACTIONS)]
pub mod phy;
+
+pub mod netlink;
diff --git a/rust/kernel/net/netlink.rs b/rust/kernel/net/netlink.rs
new file mode 100644
index 000000000000..22ef3dde36fa
--- /dev/null
+++ b/rust/kernel/net/netlink.rs
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2026 Google LLC.
+
+//! Rust support for generic netlink.
+//!
+//! Currently only supports exposing multicast groups.
+//!
+//! C header: [`include/net/genetlink.h`](srctree/include/net/genetlink.h)
+
+use kernel::{
+ alloc::{self, AllocError},
+ error::to_result,
+ prelude::*,
+ transmute::AsBytes,
+ types::Opaque,
+ ThisModule,
+};
+
+use core::{
+ mem::ManuallyDrop,
+ ptr::NonNull, //
+};
+
+/// The default netlink message size.
+pub const GENLMSG_DEFAULT_SIZE: usize = bindings::GENLMSG_DEFAULT_SIZE;
+
+/// A wrapper around `struct sk_buff` for generic netlink messages.
+///
+/// This type is intended to be specific for buffers used with netlink only, and other usecases for
+/// `struct sk_buff` are out-of-scope for this abstraction.
+///
+/// # Invariants
+///
+/// The pointer has ownership over a valid `sk_buff`.
+pub struct NetlinkSkBuff {
+ skb: NonNull<kernel::bindings::sk_buff>,
+}
+
+impl NetlinkSkBuff {
+ /// Creates a new `NetlinkSkBuff` with the given size.
+ pub fn new(size: usize, flags: alloc::Flags) -> Result<NetlinkSkBuff, AllocError> {
+ // SAFETY: `genlmsg_new` only requires its arguments to be valid integers.
+ let skb = unsafe { bindings::genlmsg_new(size, flags.as_raw()) };
+ let skb = NonNull::new(skb).ok_or(AllocError)?;
+ Ok(NetlinkSkBuff { skb })
+ }
+
+ /// Puts a generic netlink header into the `NetlinkSkBuff`.
+ pub fn genlmsg_put(
+ self,
+ portid: u32,
+ seq: u32,
+ family: &'static Family,
+ cmd: u8,
+ ) -> Result<GenlMsg, AllocError> {
+ let skb = self.skb.as_ptr();
+ // SAFETY: The skb and family pointers are valid.
+ let hdr = unsafe { bindings::genlmsg_put(skb, portid, seq, family.as_raw(), 0, cmd) };
+ let hdr = NonNull::new(hdr).ok_or(AllocError)?;
+ Ok(GenlMsg { skb: self, hdr })
+ }
+}
+
+impl Drop for NetlinkSkBuff {
+ fn drop(&mut self) {
+ // SAFETY: We have ownership over the `sk_buff`, so we may free it.
+ unsafe { bindings::nlmsg_free(self.skb.as_ptr()) }
+ }
+}
+
+/// A generic netlink message being constructed.
+///
+/// # Invariants
+///
+/// `hdr` references the header in this netlink message.
+pub struct GenlMsg {
+ skb: NetlinkSkBuff,
+ hdr: NonNull<c_void>,
+}
+
+impl GenlMsg {
+ /// Puts an attribute into the message.
+ #[inline]
+ fn put<T>(&mut self, attrtype: c_int, value: &T) -> Result
+ where
+ T: ?Sized + AsBytes,
+ {
+ let skb = self.skb.skb.as_ptr();
+ let len = size_of_val(value);
+ let ptr = core::ptr::from_ref(value).cast::<c_void>();
+ // SAFETY: `skb` is valid by `NetlinkSkBuff` type invariants, and the provided value is
+ // readable and initialized for its `size_of` bytes.
+ to_result(unsafe { bindings::nla_put(skb, attrtype, len as c_int, ptr) })
+ }
+
+ /// Puts a `u32` attribute into the message.
+ #[inline]
+ pub fn put_u32(&mut self, attrtype: c_int, value: u32) -> Result {
+ self.put(attrtype, &value)
+ }
+
+ /// Puts a string attribute into the message.
+ #[inline]
+ pub fn put_string(&mut self, attrtype: c_int, value: &CStr) -> Result {
+ self.put(attrtype, value.to_bytes_with_nul())
+ }
+
+ /// Puts a flag attribute into the message.
+ #[inline]
+ pub fn put_flag(&mut self, attrtype: c_int) -> Result {
+ let skb = self.skb.skb.as_ptr();
+ // SAFETY: `skb` is valid by `NetlinkSkBuff` type invariants, and a null pointer is valid
+ // when the length is zero.
+ to_result(unsafe { bindings::nla_put(skb, attrtype, 0, core::ptr::null()) })
+ }
+
+ /// Sends the generic netlink message as a multicast message.
+ #[inline]
+ pub fn multicast(
+ self,
+ family: &'static Family,
+ portid: u32,
+ group: u32,
+ flags: alloc::Flags,
+ ) -> Result {
+ let me = ManuallyDrop::new(self);
+ // SAFETY: The `skb` and `family` pointers are valid. We pass ownership of the `skb` to
+ // `genlmsg_multicast` by not dropping `self`.
+ unsafe {
+ bindings::genlmsg_end(me.skb.skb.as_ptr(), me.hdr.as_ptr());
+ to_result(bindings::genlmsg_multicast(
+ family.as_raw(),
+ me.skb.skb.as_ptr(),
+ portid,
+ group,
+ flags.as_raw(),
+ ))
+ }
+ }
+}
+impl Drop for GenlMsg {
+ fn drop(&mut self) {
+ // SAFETY: The `hdr` pointer references the header of this generic netlink message.
+ unsafe { bindings::genlmsg_cancel(self.skb.skb.as_ptr(), self.hdr.as_ptr()) };
+ }
+}
+
+/// Flags for a generic netlink family.
+struct FamilyFlags {
+ /// Whether the family supports network namespaces.
+ netnsok: bool,
+ /// Whether the family supports parallel operations.
+ parallel_ops: bool,
+}
+
+impl FamilyFlags {
+ /// Converts the flags to the bitfield representation used by `genl_family`.
+ const fn into_bitfield(self) -> bindings::__BindgenBitfieldUnit<[u8; 1]> {
+ // The below shifts are verified correct by test_family_flags_bitfield() below.
+ //
+ // Although bindgen generates helpers to change bitfields based on the C headers, these
+ // helpers unfortunately can't be used in const context. Since `Family` needs to be filled
+ // out at build-time, we use this helper instead.
+ let mut bits = 0;
+ if self.netnsok {
+ bits |= 1 << 0;
+ }
+ if self.parallel_ops {
+ bits |= 1 << 1;
+ }
+ // Convert from little endian to the target's endianness.
+ bits = u8::from_le(bits);
+ // SAFETY: This bitfield is represented as an u8.
+ unsafe { core::mem::transmute::<u8, bindings::__BindgenBitfieldUnit<[u8; 1]>>(bits) }
+ }
+}
+
+/// A generic netlink family.
+#[repr(transparent)]
+pub struct Family {
+ inner: Opaque<bindings::genl_family>,
+}
+
+// SAFETY: The `Family` type is thread safe.
+unsafe impl Sync for Family {}
+
+impl Family {
+ /// Creates a new `Family` instance.
+ ///
+ /// Intended to be used from const context only. Will panic if provided with invalid arguments.
+ ///
+ /// The name must be a nul-terminated string, but it is taken as `&[u8]` so that it can be used
+ /// more conveniently with the strings generated by bindgen.
+ pub const fn const_new(
+ module: &ThisModule,
+ name: &[u8],
+ version: u32,
+ mcgrps: &'static [MulticastGroup],
+ ) -> Family {
+ let n_mcgrps = mcgrps.len() as u8;
+ if n_mcgrps as usize != mcgrps.len() {
+ panic!("too many mcgrps");
+ }
+ let mut genl_family = bindings::genl_family {
+ version,
+ _bitfield_1: FamilyFlags {
+ netnsok: true,
+ parallel_ops: true,
+ }
+ .into_bitfield(),
+ module: module.as_ptr(),
+ mcgrps: mcgrps.as_ptr().cast(),
+ n_mcgrps,
+ ..pin_init::zeroed()
+ };
+ if CStr::from_bytes_with_nul(name).is_err() {
+ panic!("genl_family name not nul-terminated");
+ }
+ if genl_family.name.len() < name.len() {
+ panic!("genl_family name too long");
+ }
+ let mut i = 0;
+ while i < name.len() {
+ genl_family.name[i] = name[i];
+ i += 1;
+ }
+ Family {
+ inner: Opaque::new(genl_family),
+ }
+ }
+
+ /// Checks if there are any listeners for the given multicast group.
+ pub fn has_listeners(&self, group: u32) -> bool {
+ // SAFETY: The family and init_net pointers are valid.
+ unsafe {
+ bindings::genl_has_listeners(self.as_raw(), &raw mut bindings::init_net, group) != 0
+ }
+ }
+
+ /// Returns a raw pointer to the underlying `genl_family` structure.
+ pub fn as_raw(&self) -> *mut bindings::genl_family {
+ self.inner.get()
+ }
+}
+
+/// A generic netlink multicast group.
+#[repr(transparent)]
+pub struct MulticastGroup {
+ // No Opaque because fully immutable
+ group: bindings::genl_multicast_group,
+}
+
+// SAFETY: Pure data so thread safe.
+unsafe impl Sync for MulticastGroup {}
+
+impl MulticastGroup {
+ /// Creates a new `MulticastGroup` instance.
+ ///
+ /// Intended to be used from const context only. Will panic if provided with invalid arguments.
+ pub const fn const_new(name: &CStr) -> MulticastGroup {
+ let mut group: bindings::genl_multicast_group = pin_init::zeroed();
+
+ let name = name.to_bytes_with_nul();
+ if group.name.len() < name.len() {
+ panic!("genl_multicast_group name too long");
+ }
+ let mut i = 0;
+ while i < name.len() {
+ group.name[i] = name[i];
+ i += 1;
+ }
+
+ MulticastGroup { group }
+ }
+}
+
+/// A registration of a generic netlink family.
+///
+/// This type represents the registration of a [`Family`]. When an instance of this type is
+/// dropped, its respective generic netlink family will be unregistered from the system.
+///
+/// # Invariants
+///
+/// `self.family` always holds a valid reference to an initialized and registered [`Family`].
+pub struct Registration {
+ family: &'static Family,
+}
+
+impl Family {
+ /// Registers the generic netlink family with the kernel.
+ pub fn register(&'static self) -> Result<Registration> {
+ // SAFETY: `self.as_raw()` is a valid pointer to a `genl_family` struct.
+ // The `genl_family` struct is static, so it will outlive the registration.
+ to_result(unsafe { bindings::genl_register_family(self.as_raw()) })?;
+ Ok(Registration { family: self })
+ }
+}
+
+impl Drop for Registration {
+ fn drop(&mut self) {
+ // SAFETY: `self.family.as_raw()` is a valid pointer to a registered `genl_family` struct.
+ // The `Registration` struct ensures that `genl_unregister_family` is called exactly once
+ // for this family when it goes out of scope.
+ unsafe { bindings::genl_unregister_family(self.family.as_raw()) };
+ }
+}
+
+#[macros::kunit_tests(rust_netlink)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_family_flags_bitfield() {
+ for netnsok in [false, true] {
+ for parallel_ops in [false, true] {
+ let mut b_fam = bindings::genl_family {
+ ..Default::default()
+ };
+ b_fam.set_netnsok(if netnsok { 1 } else { 0 });
+ b_fam.set_parallel_ops(if parallel_ops { 1 } else { 0 });
+
+ let c_bitfield = FamilyFlags {
+ netnsok,
+ parallel_ops,
+ }
+ .into_bitfield();
+
+ // SAFETY: The bit field is stored as u8.
+ let b_val: u8 = unsafe { core::mem::transmute(b_fam._bitfield_1) };
+ // SAFETY: The bit field is stored as u8.
+ let c_val: u8 = unsafe { core::mem::transmute(c_bitfield) };
+ assert_eq!(b_val, c_val);
+ }
+ }
+ }
+}
--
2.55.0.rc2.803.g1fd1e6609c-goog
^ permalink raw reply related
* [PATCH v7 3/3] rust_binder: report netlink transactions
From: Alice Ryhl @ 2026-07-07 10:06 UTC (permalink / raw)
To: Carlos Llamas, Greg Kroah-Hartman, Andrew Lunn, Donald Hunter,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Matthew Maurer
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Christian Brauner, linux-kernel, rust-for-linux, netdev,
Alice Ryhl
In-Reply-To: <20260707-binder-netlink-v7-0-42b40e4b1ac8@google.com>
From: Carlos Llamas <cmllamas@google.com>
The Android Binder driver supports a netlink API that reports
transaction *failures* to a userspace daemon. This allows devices to
monitor processes with many failed transactions so that it can e.g. kill
misbehaving apps.
One very important thing that this monitors is when many oneway messages
are sent to a frozen process, so there is special handling to ensure
this scenario is surfaced over netlink.
Signed-off-by: Carlos Llamas <cmllamas@google.com>
Acked-by: Carlos Llamas <cmllamas@google.com>
Co-developed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
drivers/android/Kconfig | 2 +-
drivers/android/binder/netlink.rs | 117 +++++++++++++++++++++++++++++
drivers/android/binder/rust_binder_main.rs | 8 +-
drivers/android/binder/thread.rs | 11 ++-
drivers/android/binder/transaction.rs | 40 ++++++++++
rust/uapi/uapi_helper.h | 1 +
6 files changed, 175 insertions(+), 4 deletions(-)
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index e2e402c9d175..606a9d07f774 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -16,7 +16,7 @@ config ANDROID_BINDER_IPC
config ANDROID_BINDER_IPC_RUST
bool "Rust version of Android Binder IPC Driver"
- depends on RUST && MMU && !ANDROID_BINDER_IPC
+ depends on RUST && MMU && NET && !ANDROID_BINDER_IPC
help
This enables the Rust implementation of the Binder driver.
diff --git a/drivers/android/binder/netlink.rs b/drivers/android/binder/netlink.rs
new file mode 100644
index 000000000000..beb7ea2edaff
--- /dev/null
+++ b/drivers/android/binder/netlink.rs
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Based on: Documentation/netlink/specs/binder.yaml */
+
+#![allow(unreachable_pub, clippy::wrong_self_convention)]
+use kernel::{
+ net::netlink::{
+ Family,
+ GenlMsg,
+ MulticastGroup,
+ NetlinkSkBuff, //
+ },
+ prelude::*, //
+};
+
+pub static BINDER_NL_FAMILY: Family = Family::const_new(
+ &crate::THIS_MODULE,
+ kernel::uapi::BINDER_FAMILY_NAME,
+ kernel::uapi::BINDER_FAMILY_VERSION,
+ &BINDER_NL_FAMILY_MCGRPS,
+);
+
+static BINDER_NL_FAMILY_MCGRPS: [MulticastGroup; 1] = [MulticastGroup::const_new(c"report")];
+
+/// A multicast event sent to userspace subscribers to notify them about
+/// binder transaction failures. The generated report provides the full
+/// details of the specific transaction that failed. The intention is for
+/// programs to monitor these events and react to the failures as needed.
+pub struct Report {
+ skb: GenlMsg,
+}
+
+impl Report {
+ /// Create a new multicast message.
+ pub fn new(
+ size: usize,
+ portid: u32,
+ seq: u32,
+ flags: kernel::alloc::Flags,
+ ) -> Result<Self, kernel::alloc::AllocError> {
+ const BINDER_CMD_REPORT: u8 = kernel::uapi::BINDER_CMD_REPORT as u8;
+ let skb = NetlinkSkBuff::new(size, flags)?;
+ let skb = skb.genlmsg_put(portid, seq, &BINDER_NL_FAMILY, BINDER_CMD_REPORT)?;
+ Ok(Self { skb })
+ }
+
+ /// Broadcast this message.
+ pub fn multicast(self, portid: u32, flags: kernel::alloc::Flags) -> Result {
+ self.skb.multicast(&BINDER_NL_FAMILY, portid, 0, flags)
+ }
+
+ /// Check if this message type has listeners.
+ pub fn has_listeners() -> bool {
+ BINDER_NL_FAMILY.has_listeners(0)
+ }
+
+ /// The enum binder_driver_return_protocol returned to the sender.
+ pub fn error(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_ERROR: c_int = kernel::uapi::BINDER_A_REPORT_ERROR as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_ERROR, val)
+ }
+
+ /// The binder context where the transaction occurred.
+ pub fn context(&mut self, val: &CStr) -> Result {
+ const BINDER_A_REPORT_CONTEXT: c_int = kernel::uapi::BINDER_A_REPORT_CONTEXT as c_int;
+ self.skb.put_string(BINDER_A_REPORT_CONTEXT, val)
+ }
+
+ /// The PID of the sender process.
+ pub fn from_pid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FROM_PID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_PID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FROM_PID, val)
+ }
+
+ /// The TID of the sender thread.
+ pub fn from_tid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FROM_TID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_TID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FROM_TID, val)
+ }
+
+ /// The PID of the recipient process. This attribute may not be present
+ /// if the target could not be determined.
+ pub fn to_pid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_TO_PID: c_int = kernel::uapi::BINDER_A_REPORT_TO_PID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_TO_PID, val)
+ }
+
+ /// The TID of the recipient thread. This attribute may not be present
+ /// if the target could not be determined.
+ pub fn to_tid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_TO_TID: c_int = kernel::uapi::BINDER_A_REPORT_TO_TID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_TO_TID, val)
+ }
+
+ /// When present, indicates the failed transaction is a reply.
+ pub fn is_reply(&mut self) -> Result {
+ const BINDER_A_REPORT_IS_REPLY: c_int = kernel::uapi::BINDER_A_REPORT_IS_REPLY as c_int;
+ self.skb.put_flag(BINDER_A_REPORT_IS_REPLY)
+ }
+
+ /// The bitmask of enum transaction_flags from the transaction.
+ pub fn flags(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FLAGS: c_int = kernel::uapi::BINDER_A_REPORT_FLAGS as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FLAGS, val)
+ }
+
+ /// The application-defined code from the transaction.
+ pub fn code(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_CODE: c_int = kernel::uapi::BINDER_A_REPORT_CODE as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_CODE, val)
+ }
+
+ /// The transaction payload size in bytes.
+ pub fn data_size(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_DATA_SIZE: c_int = kernel::uapi::BINDER_A_REPORT_DATA_SIZE as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_DATA_SIZE, val)
+ }
+}
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 432390aab25b..df47aba05133 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -32,6 +32,7 @@
mod deferred_close;
mod defs;
mod error;
+mod netlink;
mod node;
mod page_range;
mod process;
@@ -282,19 +283,22 @@ fn ptr_align(value: usize) -> Option<usize> {
// SAFETY: We call register in `init`.
static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
-struct BinderModule {}
+struct BinderModule {
+ _netlink: kernel::net::netlink::Registration,
+}
impl kernel::Module for BinderModule {
fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
// SAFETY: The module initializer never runs twice, so we only call this once.
unsafe { crate::context::CONTEXTS.init() };
+ let netlink = crate::netlink::BINDER_NL_FAMILY.register()?;
BINDER_SHRINKER.register(c"android-binder")?;
// SAFETY: The module is being loaded, so we can initialize binderfs.
unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
- Ok(Self {})
+ Ok(Self { _netlink: netlink })
}
}
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 19f881948a84..33368f7fd551 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1284,6 +1284,15 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
}
}
+ if info.oneway_spam_suspect {
+ // If this is both a oneway spam suspect and a failure, we report it twice. This is
+ // useful in case the transaction failed with BR_TRANSACTION_PENDING_FROZEN.
+ info.report_netlink(BR_ONEWAY_SPAM_SUSPECT, &self.process.ctx);
+ }
+ if info.reply != 0 {
+ info.report_netlink(info.reply, &self.process.ctx);
+ }
+
Ok(())
}
@@ -1354,11 +1363,11 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
info.from_tid,
info.to_pid
);
-
let param = err.source.as_ref().map_or(0, |e| e.to_errno());
let ee = ExtendedError::new(info.debug_id as u32, err.reply, param);
orig.from
.deliver_reply(Err(BR_FAILED_REPLY), &orig, Some(ee));
+ info.reply = BR_FAILED_REPLY;
err.reply = BR_TRANSACTION_COMPLETE;
err
});
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index afef5b46eac2..6cb7b745c52e 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -3,6 +3,7 @@
// Copyright (C) 2025 Google LLC.
use kernel::{
+ net::netlink::GENLMSG_DEFAULT_SIZE,
prelude::*,
seq_file::SeqFile,
seq_print,
@@ -18,6 +19,7 @@
allocation::{Allocation, TranslatedFds},
defs::*,
error::{BinderError, BinderResult},
+ netlink::Report,
node::{Node, NodeRef},
process::{Process, ProcessInner},
ptr_align,
@@ -51,6 +53,44 @@ impl TransactionInfo {
pub(crate) fn is_oneway(&self) -> bool {
self.flags & TF_ONE_WAY != 0
}
+
+ pub(crate) fn report_netlink(&self, reply: u32, ctx: &crate::Context) {
+ if let Err(err) = self.report_netlink_inner(reply, ctx) {
+ pr_warn!(
+ "{}:{} netlink report failed: {err:?}\n",
+ self.from_pid,
+ self.from_tid
+ );
+ }
+ }
+
+ fn report_netlink_inner(&self, reply: u32, ctx: &crate::Context) -> kernel::error::Result {
+ if !Report::has_listeners() {
+ return Ok(());
+ }
+ let mut report = Report::new(GENLMSG_DEFAULT_SIZE, 0, 0, GFP_KERNEL)?;
+
+ report.error(reply)?;
+ report.context(&ctx.name)?;
+ report.from_pid(self.from_pid as u32)?;
+ report.from_tid(self.from_tid as u32)?;
+ if self.to_pid != 0 {
+ report.to_pid(self.to_pid as u32)?;
+ }
+ if self.to_tid != 0 {
+ report.to_tid(self.to_tid as u32)?;
+ }
+
+ if self.is_reply {
+ report.is_reply()?;
+ }
+ report.flags(self.flags)?;
+ report.code(self.code)?;
+ report.data_size(self.data_size as u32)?;
+
+ report.multicast(0, GFP_KERNEL)?;
+ Ok(())
+ }
}
use core::mem::offset_of;
diff --git a/rust/uapi/uapi_helper.h b/rust/uapi/uapi_helper.h
index 06d7d1a2e8da..86c7b6b284b0 100644
--- a/rust/uapi/uapi_helper.h
+++ b/rust/uapi/uapi_helper.h
@@ -11,6 +11,7 @@
#include <uapi/drm/nova_drm.h>
#include <uapi/drm/panthor_drm.h>
#include <uapi/linux/android/binder.h>
+#include <uapi/linux/android/binder_netlink.h>
#include <uapi/linux/mdio.h>
#include <uapi/linux/mii.h>
#include <uapi/linux/ethtool.h>
--
2.55.0.rc2.803.g1fd1e6609c-goog
^ permalink raw reply related
* Re: [PATCH net-next v13 09/10] net: ethtool: Introduce ethtool command to list ports
From: Paolo Abeni @ 2026-07-07 10:12 UTC (permalink / raw)
To: Maxime Chevallier, davem, Andrew Lunn, Jakub Kicinski,
Eric Dumazet, Russell King, Heiner Kallweit
Cc: netdev, linux-kernel, thomas.petazzoni, Christophe Leroy,
Herve Codina, Florian Fainelli, Vladimir Oltean,
Köry Maincent, Marek Behún, Oleksij Rempel,
Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <20260701110427.143945-10-maxime.chevallier@bootlin.com>
On 7/1/26 1:04 PM, Maxime Chevallier wrote:
> Expose the phy_port information to userspace, so that we can know how
> many ports are available on a given interface, as well as their
> capabilities. For MDI ports, we report the list of supported linkmodes
> based on what the PHY that drives this port says.
> For MII ports, i.e. empty SFP cages, we report the MII linkmodes that we
> can output on this port.
>
> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> ---
> MAINTAINERS | 1 +
> net/ethtool/Makefile | 2 +-
> net/ethtool/netlink.c | 25 +++
> net/ethtool/netlink.h | 9 +
> net/ethtool/port.c | 373 ++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 409 insertions(+), 1 deletion(-)
> create mode 100644 net/ethtool/port.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 15011f5752a9..d62eaafa8d53 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18794,6 +18794,7 @@ F: Documentation/devicetree/bindings/net/ethernet-connector.yaml
> F: Documentation/networking/phy-port.rst
> F: drivers/net/phy/phy_port.c
> F: include/linux/phy_port.h
> +F: net/ethtool/port.c
> K: struct\s+phy_port|phy_port_
>
> NETWORKING [GENERAL]
> diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
> index 629c10916670..9b5b09670008 100644
> --- a/net/ethtool/Makefile
> +++ b/net/ethtool/Makefile
> @@ -9,4 +9,4 @@ ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \
> channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
> tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \
> module.o cmis_fw_update.o cmis_cdb.o pse-pd.o plca.o \
> - phy.o tsconfig.o mse.o
> + phy.o tsconfig.o mse.o port.o
> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
> index 1af395b54330..c076c07d0a08 100644
> --- a/net/ethtool/netlink.c
> +++ b/net/ethtool/netlink.c
> @@ -26,6 +26,8 @@ static u32 ethnl_bcast_seq;
> ETHTOOL_FLAG_OMIT_REPLY)
> #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
>
> +char phy_interface_names[PHY_INTERFACE_MODE_MAX][ETH_GSTRING_LEN] __ro_after_init;
> +
> const struct nla_policy ethnl_header_policy[] = {
> [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
> [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
> @@ -431,6 +433,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
> [ETHTOOL_MSG_TSCONFIG_SET] = ðnl_tsconfig_request_ops,
> [ETHTOOL_MSG_PHY_GET] = ðnl_phy_request_ops,
> [ETHTOOL_MSG_MSE_GET] = ðnl_mse_request_ops,
> + [ETHTOOL_MSG_PORT_GET] = ðnl_port_request_ops,
> };
>
> static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
> @@ -1572,6 +1575,15 @@ static const struct genl_ops ethtool_genl_ops[] = {
> .policy = ethnl_mse_get_policy,
> .maxattr = ARRAY_SIZE(ethnl_mse_get_policy) - 1,
> },
> + {
> + .cmd = ETHTOOL_MSG_PORT_GET,
> + .doit = ethnl_default_doit,
> + .start = ethnl_port_dump_start,
> + .dumpit = ethnl_port_dumpit,
> + .done = ethnl_port_dump_done,
> + .policy = ethnl_port_get_policy,
> + .maxattr = ARRAY_SIZE(ethnl_port_get_policy) - 1,
> + },
Both sashikos instances points to multiple races with dumps. I suspect
some explicit locking is required.
https://sashiko.dev/#/patchset/20260701110427.143945-1-maxime.chevallier%40bootlin.com
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260701110427.143945-1-maxime.chevallier%40bootlin.com
I *think* this is hopefully the last pending issue.
/P
^ permalink raw reply
* Re: [PATCH net v3] ipv4: igmp: remove multicast group from hash table on device destruction
From: patchwork-bot+netdevbpf @ 2026-07-07 10:20 UTC (permalink / raw)
To: Yuyang Huang
Cc: davem, xiyou.wangcong, dsahern, edumazet, idosch, kuba, pabeni,
horms, linux-kernel, netdev, stable
In-Reply-To: <20260701235014.73505-1-yuyanghuang@google.com>
Hello:
This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Thu, 2 Jul 2026 08:50:14 +0900 you wrote:
> When a device is destroyed under RTNL, ip_mc_destroy_dev() iterates through
> the multicast list and calls ip_ma_put() on each membership, scheduling
> them for RCU reclamation. However, they are not unlinked from the device's
> multicast hash table (mc_hash).
>
> Since the device remains published in dev->ip_ptr until after
> ip_mc_destroy_dev() completes, concurrent RCU readers traversing mc_hash
> can still locate and access the multicast group after its refcount is
> decremented. If the RCU callback runs and frees the group while a reader is
> accessing it, a use-after-free occurs.
>
> [...]
Here is the summary with links:
- [net,v3] ipv4: igmp: remove multicast group from hash table on device destruction
https://git.kernel.org/netdev/net/c/7993211bde16
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 rdma-next v9] RDMA: Change capability fields in ib_device_attr from int to u32
From: Erni Sri Satya Vennela @ 2026-07-07 10:20 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Jason Gunthorpe, mkalderon, zyjzyj2000, sagi, mgurtovoy,
haris.iqbal, jinpu.wang, bvanassche, kbusch, Jens Axboe,
Christoph Hellwig, kch, smfrench, linkinjeon, metze, tom, cel,
jlayton, neil, okorniev, Dai.Ngo, trondmy, anna, achender, davem,
edumazet, kuba, pabeni, horms, kees, andriy.shevchenko, clm,
ebadger, linux-rdma, linux-kernel, target-devel, linux-nvme,
linux-cifs, samba-technical, linux-nfs, netdev, rds-devel,
Jason Gunthorpe
In-Reply-To: <20260706084950.GK15188@unreal>
On Mon, Jul 06, 2026 at 11:49:50AM +0300, Leon Romanovsky wrote:
> > ---
> > drivers/infiniband/core/cq.c | 3 +-
> > drivers/infiniband/hw/qedr/verbs.c | 2 +-
> > drivers/infiniband/sw/rxe/rxe_qp.c | 22 +++++-----
> > drivers/infiniband/sw/rxe/rxe_srq.c | 16 +++----
> > drivers/infiniband/ulp/ipoib/ipoib_cm.c | 10 ++---
> > drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 3 +-
> > drivers/infiniband/ulp/iser/iser_verbs.c | 5 +--
> > drivers/infiniband/ulp/isert/ib_isert.c | 7 ++-
> > drivers/infiniband/ulp/rtrs/rtrs-clt.c | 11 ++---
> > drivers/infiniband/ulp/rtrs/rtrs-srv.c | 11 ++---
> > drivers/infiniband/ulp/srp/ib_srp.c | 2 +-
> > drivers/infiniband/ulp/srpt/ib_srpt.c | 21 +++++----
> > drivers/nvme/host/rdma.c | 8 ++--
> > drivers/nvme/target/rdma.c | 22 ++++++----
> > fs/smb/smbdirect/accept.c | 5 ++-
> > fs/smb/smbdirect/connect.c | 5 ++-
> > fs/smb/smbdirect/connection.c | 8 ++--
> > include/linux/sunrpc/svc_rdma.h | 4 +-
> > include/rdma/ib_verbs.h | 50 +++++++++++-----------
> > net/rds/ib.c | 10 ++---
> > net/rds/ib_cm.c | 10 ++---
> > net/sunrpc/xprtrdma/frwr_ops.c | 7 +--
> > net/sunrpc/xprtrdma/svc_rdma_transport.c | 5 +--
> > net/sunrpc/xprtrdma/verbs.c | 2 +-
> > 24 files changed, 122 insertions(+), 127 deletions(-)
>
> The following code is still missing.
I'll make this change in the next version.
>Also, what about mxa_srq?
> Why wasn't it converted as well?
I originally left max_srq as int because its only consumer pairs it with
num_comp_vectors (a signed int) in nvmet_rdma, so keeping it int let
that site stay a plain min() instead of a min_t().
num_comp_vectors is the completion-vector count, legitimately int and
never anywhere near INT_MAX, so I'd prefer to leave it signed rather
than convert it everywhere. Does that work for you, or would you rather
num_comp_vectors be converted too?
If it needs converting, I'll do it as a separate patch, since it lives
in a different struct (ib_device) and touches many call sites.
Otherwise, using min_t() for just this one call is fine too.
Thanks,
Vennela
>
> diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
> index f599c24b34e8..aae4f3f6bcba 100644
> --- a/drivers/infiniband/core/nldev.c
> +++ b/drivers/infiniband/core/nldev.c
> @@ -454,7 +454,8 @@ static int fill_res_info(struct sk_buff *msg, struct ib_device *device,
> };
>
> struct nlattr *table_attr;
> - int ret, i, curr, max;
> + u64 curr, max;
> + int ret, i;
>
> if (fill_nldev_handle(msg, device))
> return -EMSGSIZE;
> diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
> index cfee2071586c..1b2f9df49e28 100644
> --- a/drivers/infiniband/core/restrack.c
> +++ b/drivers/infiniband/core/restrack.c
> @@ -61,7 +61,7 @@ void rdma_restrack_clean(struct ib_device *dev)
> * @type: actual type of object to operate
> * @show_details: count driver specific objects
> */
> -int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> +u32 rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> bool show_details)
> {
> struct rdma_restrack_root *rt = &dev->res[type];
> diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
> index 451f99e3717d..c081384740ce 100644
> --- a/include/rdma/restrack.h
> +++ b/include/rdma/restrack.h
> @@ -123,7 +123,7 @@ struct rdma_restrack_entry {
> u32 id;
> };
>
> -int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> +u32 rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> bool show_details);
> /**
> * rdma_is_kernel_res() - check the owner of resource
^ permalink raw reply
* Re: [PATCH rdma-next v9] RDMA: Change capability fields in ib_device_attr from int to u32
From: Leon Romanovsky @ 2026-07-07 10:25 UTC (permalink / raw)
To: Erni Sri Satya Vennela
Cc: Jason Gunthorpe, mkalderon, zyjzyj2000, sagi, mgurtovoy,
haris.iqbal, jinpu.wang, bvanassche, kbusch, Jens Axboe,
Christoph Hellwig, kch, smfrench, linkinjeon, metze, tom, cel,
jlayton, neil, okorniev, Dai.Ngo, trondmy, anna, achender, davem,
edumazet, kuba, pabeni, horms, kees, andriy.shevchenko, clm,
ebadger, linux-rdma, linux-kernel, target-devel, linux-nvme,
linux-cifs, samba-technical, linux-nfs, netdev, rds-devel,
Jason Gunthorpe
In-Reply-To: <akzS9EdxScQsx9n8@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
On Tue, Jul 07, 2026 at 03:20:36AM -0700, Erni Sri Satya Vennela wrote:
> On Mon, Jul 06, 2026 at 11:49:50AM +0300, Leon Romanovsky wrote:
> > > ---
> > > drivers/infiniband/core/cq.c | 3 +-
> > > drivers/infiniband/hw/qedr/verbs.c | 2 +-
> > > drivers/infiniband/sw/rxe/rxe_qp.c | 22 +++++-----
> > > drivers/infiniband/sw/rxe/rxe_srq.c | 16 +++----
> > > drivers/infiniband/ulp/ipoib/ipoib_cm.c | 10 ++---
> > > drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 3 +-
> > > drivers/infiniband/ulp/iser/iser_verbs.c | 5 +--
> > > drivers/infiniband/ulp/isert/ib_isert.c | 7 ++-
> > > drivers/infiniband/ulp/rtrs/rtrs-clt.c | 11 ++---
> > > drivers/infiniband/ulp/rtrs/rtrs-srv.c | 11 ++---
> > > drivers/infiniband/ulp/srp/ib_srp.c | 2 +-
> > > drivers/infiniband/ulp/srpt/ib_srpt.c | 21 +++++----
> > > drivers/nvme/host/rdma.c | 8 ++--
> > > drivers/nvme/target/rdma.c | 22 ++++++----
> > > fs/smb/smbdirect/accept.c | 5 ++-
> > > fs/smb/smbdirect/connect.c | 5 ++-
> > > fs/smb/smbdirect/connection.c | 8 ++--
> > > include/linux/sunrpc/svc_rdma.h | 4 +-
> > > include/rdma/ib_verbs.h | 50 +++++++++++-----------
> > > net/rds/ib.c | 10 ++---
> > > net/rds/ib_cm.c | 10 ++---
> > > net/sunrpc/xprtrdma/frwr_ops.c | 7 +--
> > > net/sunrpc/xprtrdma/svc_rdma_transport.c | 5 +--
> > > net/sunrpc/xprtrdma/verbs.c | 2 +-
> > > 24 files changed, 122 insertions(+), 127 deletions(-)
> >
> > The following code is still missing.
>
> I'll make this change in the next version.
>
> >Also, what about mxa_srq?
> > Why wasn't it converted as well?
>
> I originally left max_srq as int because its only consumer pairs it with
> num_comp_vectors (a signed int) in nvmet_rdma, so keeping it int let
> that site stay a plain min() instead of a min_t().
>
> num_comp_vectors is the completion-vector count, legitimately int and
> never anywhere near INT_MAX, so I'd prefer to leave it signed rather
> than convert it everywhere. Does that work for you, or would you rather
> num_comp_vectors be converted too?
In this patch no, but it is worth to write this in commit message.
Thanks
>
> If it needs converting, I'll do it as a separate patch, since it lives
> in a different struct (ib_device) and touches many call sites.
> Otherwise, using min_t() for just this one call is fine too.
>
> Thanks,
> Vennela
>
> >
> > diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
> > index f599c24b34e8..aae4f3f6bcba 100644
> > --- a/drivers/infiniband/core/nldev.c
> > +++ b/drivers/infiniband/core/nldev.c
> > @@ -454,7 +454,8 @@ static int fill_res_info(struct sk_buff *msg, struct ib_device *device,
> > };
> >
> > struct nlattr *table_attr;
> > - int ret, i, curr, max;
> > + u64 curr, max;
> > + int ret, i;
> >
> > if (fill_nldev_handle(msg, device))
> > return -EMSGSIZE;
> > diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
> > index cfee2071586c..1b2f9df49e28 100644
> > --- a/drivers/infiniband/core/restrack.c
> > +++ b/drivers/infiniband/core/restrack.c
> > @@ -61,7 +61,7 @@ void rdma_restrack_clean(struct ib_device *dev)
> > * @type: actual type of object to operate
> > * @show_details: count driver specific objects
> > */
> > -int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> > +u32 rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> > bool show_details)
> > {
> > struct rdma_restrack_root *rt = &dev->res[type];
> > diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
> > index 451f99e3717d..c081384740ce 100644
> > --- a/include/rdma/restrack.h
> > +++ b/include/rdma/restrack.h
> > @@ -123,7 +123,7 @@ struct rdma_restrack_entry {
> > u32 id;
> > };
> >
> > -int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> > +u32 rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
> > bool show_details);
> > /**
> > * rdma_is_kernel_res() - check the owner of resource
^ permalink raw reply
* Re: [PATCH net] net: ti: icssg-prueth: Fix link-local addresses being forwarded out of slave ports
From: Paolo Abeni @ 2026-07-07 10:30 UTC (permalink / raw)
To: MD Danish Anwar, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Simon Horman, Meghana Malladi
Cc: linux-arm-kernel, netdev, linux-kernel
In-Reply-To: <20260701112535.4027920-1-danishanwar@ti.com>
On 7/1/26 1:25 PM, MD Danish Anwar wrote:
> Link-local multicast addresses (01:80:c2:00:00:0x) must only be
> delivered to the host port (P0) and must not be forwarded out of
> the physical slave ports. icssg_fdb_add_del() was programming these
> addresses with P1/P2 membership bits set, causing the firmware to
> forward them out of slave ports.
>
> Clear P1/P2 membership and set only P0 membership when
> is_link_local_ether_addr() returns true.
>
> Fixes: 487f7323f39a ("net: ti: icssg-prueth: Add helper functions to configure FDB")
> Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
> ---
> drivers/net/ethernet/ti/icssg/icssg_config.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
> index 3f8237c17d099..04a81402e3f3c 100644
> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c
> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
> @@ -732,6 +732,16 @@ int icssg_fdb_add_del(struct prueth_emac *emac, const unsigned char *addr,
> u8 fid = vid;
> int ret;
>
> + /* Link-local addresses (01:80:c2:00:00:0x) must only be delivered to
> + * the host port (P0). Clear P1/P2 membership to prevent the firmware
> + * from forwarding them out of the physical slave ports.
> + */
> + if (is_link_local_ether_addr(addr)) {
> + fid_c2 |= ICSSG_FDB_ENTRY_P0_MEMBERSHIP;
> + fid_c2 &= ~(ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
> + ICSSG_FDB_ENTRY_P2_MEMBERSHIP);
> + }
Sashiko gemeni mentioned it could be safer to reject entirely wrong masks:
https://sashiko.dev/#/patchset/20260701112535.4027920-1-danishanwar%40ti.com
It's not clear to me if the mentioned bad scenario is actually possibly,
please have a look.
/P
^ permalink raw reply
* Missing signoff in the bpf-next tree
From: Mark Brown @ 2026-07-07 10:30 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov, Andrii Nakryiko, bpf,
Networking
Cc: linux-kernel, linux-next
[-- Attachment #1: Type: text/plain, Size: 136 bytes --]
Commit
83a93e3b80bd3 ("selftests/bpf: libarena: Replace leftover st_ prefix with test_")
is missing a Signed-off-by from its author
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] arm64: dts: qcom: sm8450: Add IPA support
From: Konrad Dybcio @ 2026-07-07 10:35 UTC (permalink / raw)
To: Esteban Urrutia, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Alex Elder
Cc: linux-arm-msm, devicetree, linux-kernel, netdev
In-Reply-To: <1e151b08-5d3b-4b75-8d71-635617868285@proton.me>
On 6/30/26 3:57 AM, Esteban Urrutia wrote:
> On 6/29/26 10:18 AM, Konrad Dybcio wrote:
>> Please alter the size of the register range that I mentioned this under,
>> as the range is wider than what you specified - the driver takes a big
>> offset from this base and accesses far outside the bounds of that range
> Just to make sure:
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
> index dd151a2c48ec..100daf8120ce 100644
> --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
> @@ -2643,7 +2643,7 @@ ipa: ipa@3f40000 {
> compatible = "qcom,sm8450-ipa";
>
> reg = <0 0x3f40000 0 0x10000>,
> - <0 0x3f50000 0 0x5000>,
> + <0 0x3f50000 0 0xb0000>,
> <0 0x3e04000 0 0xfc000>;
> reg-names = "ipa-reg",
> "ipa-shared",
>
> Is this what you're referring to?
Yes
Konrad
^ permalink raw reply
* Re: [PATCH net] bonding: fix devconf_all NULL dereference when IPv6 is disabled
From: Vadim Fedorenko @ 2026-07-07 10:35 UTC (permalink / raw)
To: zhangzl2013, Jay Vosburgh, Andrew Lunn, Jakub Kicinski
Cc: David S . Miller, Eric Dumazet, Paolo Abeni, Hangbin Liu, netdev,
linux-kernel, Qianheng Peng, Zhaolong Zhang
In-Reply-To: <20260707010622.487333-1-zhangzl2013@126.com>
On 07/07/2026 02:06, zhangzl2013@126.com wrote:
> From: Zhaolong Zhang <zhangzl68@chinatelecom.cn>
>
> When booting with the 'ipv6.disable=1' parameter, the devconf_all is
> never initialized because inet6_init() exits before addrconf_init() is
> called which initializes it. bond_send_validate(), however, will still
> call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to
> NULL derefence of net->ipv6.devconf_all in ip6_pol_route().
>
> BUG: kernel NULL pointer dereference, address: 000000000000000c
> [...]
> Workqueue: bond0 bond_arp_monitor [bonding]
> RIP: 0010:ip6_pol_route+0x69/0x480
> [...]
> Call Trace:
> <TASK>
> ? srso_return_thunk+0x5/0x5f
> ? __pfx_ip6_pol_route_output+0x10/0x10
> fib6_rule_lookup+0xfe/0x260
> ? wakeup_preempt+0x8a/0x90
> ? srso_return_thunk+0x5/0x5f
> ? srso_return_thunk+0x5/0x5f
> ? sched_balance_rq+0x369/0x810
> ip6_route_output_flags+0xd7/0x170
> bond_ns_send_all+0xde/0x280 [bonding]
> bond_ab_arp_probe+0x296/0x320 [bonding]
> ? srso_return_thunk+0x5/0x5f
> bond_activebackup_arp_mon+0xb4/0x2c0 [bonding]
> process_one_work+0x196/0x370
> worker_thread+0x1af/0x320
> ? srso_return_thunk+0x5/0x5f
> ? __pfx_worker_thread+0x10/0x10
> kthread+0xe3/0x120
> ? __pfx_kthread+0x10/0x10
> ret_from_fork+0x199/0x260
> ? __pfx_kthread+0x10/0x10
> ret_from_fork_asm+0x1a/0x30
> </TASK>
>
> Fix this by adding ipv6_mod_enabled() condition check in the caller.
>
> Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets")
> Signed-off-by: Qianheng Peng <pengqh1@chinatelecom.cn>
> Signed-off-by: Zhaolong Zhang <zhangzl68@chinatelecom.cn>
> ---
> drivers/net/bonding/bond_main.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index e044fc733b8c..522eab060f9e 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -3455,7 +3455,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave)
> {
> bond_arp_send_all(bond, slave);
> #if IS_ENABLED(CONFIG_IPV6)
> - bond_ns_send_all(bond, slave);
> + if (likely(ipv6_mod_enabled()))
> + bond_ns_send_all(bond, slave);
> #endif
> }
>
ipv6_mod_enabled() doesn't depend on CONFIG_IPV6, please, remove
#if IS_ENABLED as well
^ permalink raw reply
* Re: [PATCH net-next v2 3/3] net: ti: icssm-prueth: Support duplicate HW offload feature for HSR and PRP
From: Parvathi Pudi @ 2026-07-07 10:36 UTC (permalink / raw)
To: Paolo Abeni
Cc: parvathi, andrew+netdev, davem, edumazet, kuba, danishanwar,
rogerq, pmohan, afd, basharath, arnd, linux-kernel, netdev,
linux-arm-kernel, pratheesh, j-rameshbabu, Vignesh Raghavendra,
praneeth, srk, rogerq, m-malladi, krishna, mohan
In-Reply-To: <20260706091338.134754-1-pabeni@redhat.com>
Hi,
> From: AI Reviewer <ai@example.com>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://sashiko.dev/
> ---
> net: ti: icssm-prueth: Support duplicate HW offload feature for HSR and PRP
>
> This commit introduces hardware duplicate offload for HSR and PRP modes. It
> implements a common shared queue between the two ports, writing frames once
> to OCMC RAM and relying on the firmware to replicate the transmission.
>
>> diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> index 2ab78a98f8568..cbe666a212c3b 100644
>> --- a/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> @@ -97,6 +125,17 @@ static void icssm_prueth_write_reg(struct prueth *prueth,
>> static enum pruss_mem pruss_mem_ids[] = { PRUSS_MEM_DRAM0, PRUSS_MEM_DRAM1,
>> PRUSS_MEM_SHRD_RAM2 };
>>
>> +struct prp_txopt_rct {
>> + __be16 sequence_nr;
>> + __be16 lan_id_and_lsdu_size;
>> + __be16 prp_suffix;
>> +};
>
> [Severity: High]
> Does this structure definition need the __packed attribute?
>
> This struct consists of three 16-bit fields but lacks the __packed attribute,
> so it inherits a 2-byte alignment requirement. Later in
> icssm_prueth_tx_enqueue, a pointer to this structure is derived directly
> from skb_tail_pointer.
>
> If an ethernet frame payload has an odd byte length, wouldn't casting and
> dereferencing this pointer cause an unaligned 16-bit memory access, resulting
> in hardware traps or panics on architectures that do not support it?
>
> [ ... ]
>> @@ -549,15 +588,24 @@ static int icssm_prueth_tx_enqueue(struct prueth_emac
>> *emac,
> [ ... ]
>> + other_emac = emac->prueth->emac[(emac->port_id == PRUETH_PORT_MII0) ?
>> + PRUETH_PORT_MII1 - 1 : PRUETH_PORT_MII0 - 1];
>> +
>> + if (prueth_is_lre(prueth) && (emac->link || other_emac->link))
>> + link_up = true;
>
> [Severity: High]
> Could this logical OR cause the shared transmission queue to stall completely
> if only one of the slave links goes down?
>
> If one port loses its link, its emac->link is 0, but the other active port
> will still evaluate link_up as true. The active port would continue sending
> duplicate frames to the shared queue.
>
> [ ... ]
>> @@ -605,6 +659,29 @@ static int icssm_prueth_tx_enqueue(struct prueth_emac
>> *emac,
> [ ... ]
>> + if (free_blocks_other_port < free_blocks)
>> + free_blocks = free_blocks_other_port;
>> + }
>
> [Severity: High]
> Following up on the link_up logic above, since the available queue space is
> bounded by the slowest reader here, wouldn't the inactive port's read pointer
> remain frozen?
>
> This appears to exhaust the free_blocks pool, causing the active port to
> eventually spin and return -ENOBUFS permanently, defeating the redundancy.
>
> [ ... ]
>> + } else {
>> + /* Read PRP RCT to extract sequence number and LAN ID */
>> + struct prp_txopt_rct *rct =
>> + (struct prp_txopt_rct *)(skb_tail_pointer(skb) -
>> + ICSSM_LRE_TAG_SIZE);
>> +
>> + if (rct->prp_suffix == htons(ETH_P_PRP)) {
>
> [Severity: High]
> Is it safe to directly dereference rct->prp_suffix here?
>
> As mentioned above regarding the struct definition, this might lead to an
> unaligned memory access on certain architectures. Perhaps using the
> get_unaligned_be16 helper would be safer here, or adding the __packed
> attribute to the structure definition.
>
> [ ... ]
>> @@ -1341,18 +1516,30 @@ static enum netdev_tx icssm_emac_ndo_start_xmit(struct
>> sk_buff *skb,
> [ ... ]
>> + raw_spin_lock(lock_queue);
>> + ret = icssm_prueth_tx_enqueue(emac, skb, qid);
>> + raw_spin_unlock(lock_queue);
>
> [Severity: High]
> Does this need to use the irqsave variant to protect against cross-device
> deadlocks with netpoll?
>
> The lre_host_queue_lock is shared between the two ports. If a hardirq
> preempts a CPU while it holds this lock during a transmission, and the
> interrupt handler invokes a printk that triggers netconsole over the second
> interface, netpoll might bypass the netif_tx_lock.
>
> When the second interface calls into ndo_start_xmit, it would attempt to
> acquire the exact same lre_host_queue_lock, causing it to spin forever on
> the same CPU.
> --
> This is an AI-generated review.
We are in the process of reviewing the comments and will revert with additional
details.
Thanks and Regards,
Parvathi.
^ permalink raw reply
* Re: [PATCH net] net: ti: icssg-prueth: Fix link-local addresses being forwarded out of slave ports
From: MD Danish Anwar @ 2026-07-07 10:39 UTC (permalink / raw)
To: Paolo Abeni, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Simon Horman, Meghana Malladi
Cc: linux-arm-kernel, netdev, linux-kernel
In-Reply-To: <71a1bacf-c54f-45b0-80df-7175261cf2ac@redhat.com>
Hi Paolo,
On 07/07/26 4:00 pm, Paolo Abeni wrote:
> On 7/1/26 1:25 PM, MD Danish Anwar wrote:
>> Link-local multicast addresses (01:80:c2:00:00:0x) must only be
>> delivered to the host port (P0) and must not be forwarded out of
>> the physical slave ports. icssg_fdb_add_del() was programming these
>> addresses with P1/P2 membership bits set, causing the firmware to
>> forward them out of slave ports.
>>
>> Clear P1/P2 membership and set only P0 membership when
>> is_link_local_ether_addr() returns true.
>>
>> Fixes: 487f7323f39a ("net: ti: icssg-prueth: Add helper functions to configure FDB")
>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
>> ---
>> drivers/net/ethernet/ti/icssg/icssg_config.c | 10 ++++++++++
>> 1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
>> index 3f8237c17d099..04a81402e3f3c 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
>> @@ -732,6 +732,16 @@ int icssg_fdb_add_del(struct prueth_emac *emac, const unsigned char *addr,
>> u8 fid = vid;
>> int ret;
>>
>> + /* Link-local addresses (01:80:c2:00:00:0x) must only be delivered to
>> + * the host port (P0). Clear P1/P2 membership to prevent the firmware
>> + * from forwarding them out of the physical slave ports.
>> + */
>> + if (is_link_local_ether_addr(addr)) {
>> + fid_c2 |= ICSSG_FDB_ENTRY_P0_MEMBERSHIP;
>> + fid_c2 &= ~(ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
>> + ICSSG_FDB_ENTRY_P2_MEMBERSHIP);
>> + }
>
> Sashiko gemeni mentioned it could be safer to reject entirely wrong masks:
>
> https://sashiko.dev/#/patchset/20260701112535.4027920-1-danishanwar%40ti.com
>
> It's not clear to me if the mentioned bad scenario is actually possibly,
> please have a look.
>
I had a look at the Sashiko comment. This seems to be a false positive
to me.
Link-local addresses (01:80:c2:00:00:0x) are IEEE 802.1D Table 7-10
reserved addresses that bridges MUST NOT forward. They are consumed
locally by STP, LACP, LLDP, PAE, etc.
No valid protocol or user configuration would add an MDB entry for these
addresses on a slave port — doing so is a misconfiguration regardless of
hardware.
The silent enforcement in icssg_fdb_add_del() ensures the hardware
always reflects the mandatory protocol behavior. Returning -EOPNOTSUPP
would only matter if there were a legitimate caller we needed to reject
— there isn't one.
I think silently adding host port to FDB membership for Link Local
addresses is OK. This Sashiko comment can be ignored.
--
Thanks and Regards,
Danish
^ permalink raw reply
* Re: [PATCH] net: stmmac: Avoid freeing and re-requesting IRQ during XDP set prog
From: Maciej Fijalkowski @ 2026-07-07 10:42 UTC (permalink / raw)
To: Daniel Thompson
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Alex Elder, netdev,
linux-stm32, linux-arm-kernel, linux-kernel, bpf
In-Reply-To: <20260706-tc956x-stmmac-no_irq_teardown-v1-1-df009d0272bf@riscstar.com>
On Mon, Jul 06, 2026 at 05:17:58PM +0100, Daniel Thompson wrote:
> Currently stmmac will run a full cycle of IRQ tear down and setup when
> setting up a new XDP program. This makes tuning TSN systems difficult
> because whenever a new XDP program is installed then the irq threads will
> be stopped and restarted which will undo any thread tuning.
>
> The problem is avoided by removing stmmac_free_irq()/stmmac_request_irq()
> from stmmac_xdp_release()/stmmac_xdp_open().
>
> stmmac_free_irq() implicitly synchronizes interrupts and, with that
> removed, I was unable to prove that later actions in
> stmmac_xdp_release() are safe when there are concurrent interrupts. To
> avoid problems let's also move the code to disable DMA interrupts earlier
> in the sequence and explicitly sync the interrupts handler(s).
>
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Is that a fix or a new feature? You need to specify the tree you're
targetting this change (net/net-next).
You've also got Sashiko review so please resolve reported issues there.
However the scope reduction of toggling interface state when loading XDP
prog seems correct approach. For intel drivers we started with resetting
whole PF and then realized it's pretty much an overkill and we can achieve
prog load via only down/up of an interface.
> ---
> This patch was developed (and tested) as part of the TC956x work that
> Alex Elder and I have been working on. However the change should work with
> any driver that uses the stmmac core so it makes sense to submit it as
> a separate patch.
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 61 ++++++++++++++++++-----
> 1 file changed, 48 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 2a0d7eff88d3ff1ffa57e224c25f9e77bc28ed10..acd145f1f3069fde6043a9118c793758c5c8f4c0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2531,6 +2531,23 @@ static void stmmac_enable_all_dma_irq(struct stmmac_priv *priv)
> }
> }
>
> +static void stmmac_disable_all_dma_irq(struct stmmac_priv *priv)
> +{
> + u8 rx_channels_count = priv->plat->rx_queues_to_use;
> + u8 tx_channels_count = priv->plat->tx_queues_to_use;
> + u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
> + u8 chan;
> +
> + for (chan = 0; chan < dma_csr_ch; chan++) {
> + struct stmmac_channel *ch = &priv->channel[chan];
> + unsigned long flags;
> +
> + spin_lock_irqsave(&ch->lock, flags);
> + stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> + spin_unlock_irqrestore(&ch->lock, flags);
> + }
> +}
> +
> /**
> * stmmac_start_all_dma - start all RX and TX DMA channels
> * @priv: driver private structure
> @@ -3814,6 +3831,33 @@ static void stmmac_free_irq(struct net_device *dev,
> }
> }
>
> +static void stmmac_synchronize_irq(struct net_device *dev)
> +{
> + struct stmmac_priv *priv = netdev_priv(dev);
> + struct stmmac_msi *msi = priv->msi;
> + int j;
> +
> + for (j = priv->plat->tx_queues_to_use - 1; msi && j >= 0; j--) {
> + if (msi->tx_irq[j] > 0)
> + synchronize_irq(msi->tx_irq[j]);
> + }
> +
> + for (j = priv->plat->rx_queues_to_use - 1; msi && j >= 0; j--) {
> + if (msi->rx_irq[j] > 0)
> + synchronize_irq(msi->rx_irq[j]);
> + }
> +
> + if (msi && msi->sfty_ue_irq > 0 && msi->sfty_ue_irq != dev->irq)
> + synchronize_irq(msi->sfty_ue_irq);
> + if (msi && msi->sfty_ce_irq > 0 && msi->sfty_ce_irq != dev->irq)
> + synchronize_irq(msi->sfty_ce_irq);
> + if (priv->wol_irq > 0 && priv->wol_irq != dev->irq)
> + synchronize_irq(priv->wol_irq);
> + if (priv->sfty_irq > 0 && priv->sfty_irq != dev->irq)
> + synchronize_irq(priv->sfty_irq);
> + synchronize_irq(dev->irq);
> +}
> +
> static int stmmac_msi_init(struct stmmac_priv *priv,
> struct stmmac_resources *res)
> {
> @@ -7108,8 +7152,9 @@ void stmmac_xdp_release(struct net_device *dev)
> for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
> hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
>
> - /* Free the IRQ lines */
> - stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
> + /* Silence DMA interrupts */
> + stmmac_disable_all_dma_irq(priv);
> + stmmac_synchronize_irq(dev);
>
> /* Stop TX/RX DMA channels */
> stmmac_stop_all_dma(priv);
> @@ -7156,10 +7201,8 @@ int stmmac_xdp_open(struct net_device *dev)
> stmmac_reset_queues_param(priv);
>
> /* DMA CSR Channel configuration */
> - for (chan = 0; chan < dma_csr_ch; chan++) {
> + for (chan = 0; chan < dma_csr_ch; chan++)
> stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> - stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1);
> - }
>
> /* Adjust Split header */
> sph_en = (priv->hw->rx_csum > 0) && priv->sph_active;
> @@ -7197,10 +7240,6 @@ int stmmac_xdp_open(struct net_device *dev)
> /* Start Rx & Tx DMA Channels */
> stmmac_start_all_dma(priv);
>
> - ret = stmmac_request_irq(dev);
> - if (ret)
> - goto irq_error;
> -
> /* Enable NAPI process*/
> stmmac_enable_all_queues(priv);
> netif_carrier_on(dev);
> @@ -7209,10 +7248,6 @@ int stmmac_xdp_open(struct net_device *dev)
>
> return 0;
>
> -irq_error:
> - for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
> - hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
> -
> init_error:
> free_dma_desc_resources(priv, &priv->dma_conf);
> dma_desc_error:
>
> ---
> base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
> change-id: 20260706-tc956x-stmmac-no_irq_teardown-8a7592b9f8c1
>
> Best regards,
> --
> Daniel Thompson <daniel@riscstar.com>
>
>
^ permalink raw reply
* Re: [PATCH net-next v2] ipv4: hold a consistent view of rt->dst.dev under RCU
From: luoxuanqiang @ 2026-07-07 10:41 UTC (permalink / raw)
To: Paolo Abeni, Ido Schimmel
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, David Ahern,
Simon Horman, Kuniyuki Iwashima, netdev, linux-kernel,
Xuanqiang Luo
In-Reply-To: <ef3a91ba-f4c5-4d89-a88b-465b5b7fab12@redhat.com>
在 2026/7/7 17:02, Paolo Abeni 写道:
> On 7/7/26 3:26 AM, luoxuanqiang wrote:
>> 在 2026/7/6 00:46, Ido Schimmel 写道:
>>> On Wed, Jul 01, 2026 at 11:24:34AM +0800,xuanqiang.luo@linux.dev wrote:
>>>> From: Xuanqiang Luo<luoxuanqiang@kylinos.cn>
>>>>
>>>> rt_flush_dev() walks the per-CPU uncached route list and rewrites
>>>> rt->dst.dev in-place to blackhole_netdev under spin_lock_bh().
>>>> This lock does not exclude RCU readers, which may load rt->dst.dev
>>>> multiple times within a single rcu_read_lock() region.
>>>>
>>>> ip_rt_send_redirect() is a typical example: it reads rt->dst.dev
>>>> three times to obtain in_dev, the L3 master ifindex, and net.
>>>> A concurrent device unregistration can repoint rt->dst.dev to
>>>> blackhole_netdev between those reads, making the reader combine
>>>> state from two different net_devices — for instance, an in_dev
>>>> from the real device but a netns and peer lookup from the blackhole
>>>> device. ip_rt_get_source() has the same problem: it reads
>>>> rt->dst.dev four times to obtain the output ifindex, the netns,
>>>> and the source address, so a concurrent flush can cause the source
>>>> selection to mix state from different devices.
>>> Why only change ip_rt_send_redirect() and ip_rt_get_source() when the
>>> patch is titled "ipv4: hold a consistent view of rt->dst.dev under RCU"?
>>> What is the criterion?
>> Thanks! You are right, the subject is too broad. I will make them
>> more accurate in the next version.
>>
>>>> Take a single dst_dev_rcu() snapshot of rt->dst.dev at the start
>>>> of each affected RCU reader and use that snapshot throughout, so
>>>> concurrent flushes cannot cause mid-function inconsistency.
>>>> Publish the in-place write in rt_flush_dev() with rcu_assign_pointer()
>>>> to match the readers.
>>> The rt_flush_dev() change should be a separate change. Note that
>>> dst_dev_put() was already converted to use rcu_assign_pointer().
>>>
>> I will split the rt_flush_dev() change into a separate patch.
>>
>>>> Fixes: caacf05e5ad1a ("ipv4: Properly purge netdev references on uncached routes.")
>>> Please remove the Fixes tag given you are targeting net-next.
>> Just to clarify: is the suggestion to drop the Fixes tag here solely
>> because this patch is targeted at net-next? Or are there any other
>> reasons?
> Generally speaking, yes: net-next patches should not include a fixes tag
> unless the blamed commit is on net-next only.
>
> More specifically, this patch is really a behavior improvement and not a
> vertical fix, as such we want to avoid it propagating on stable trees,
> as the fixes tag sometimes does.
>
> /P
>
Many thanks for the detailed explanation!
^ permalink raw reply
* [PATCH net v3] net/packet: avoid fanout hook re-registration after unregister
From: David Lee @ 2026-07-07 10:44 UTC (permalink / raw)
To: Willem de Bruijn
Cc: David Lee, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman,
Dominik 'Disconnect3d' Czarnota, netdev, linux-kernel,
Willem de Bruijn
packet_set_ring() temporarily detaches a socket from packet delivery while
reconfiguring its ring. It records the previous running state, clears
po->num, unregisters the protocol hook when needed, drops po->bind_lock,
and later restores po->num and re-registers the hook from the saved
was_running value.
That unlocked window can race with NETDEV_UNREGISTER. The notifier can
observe the socket as not running, skip __unregister_prot_hook(), and
invalidate the per-socket binding by setting po->ifindex to -1 and clearing
po->prot_hook.dev. A one-member fanout group can still retain its shared
fanout hook device pointer. When packet_set_ring() resumes, re-registering
solely from the stale was_running state can re-add the fanout hook after
the device has been unregistered.
Treat po->ifindex == -1 as an invalidated binding after reacquiring
po->bind_lock. This is distinct from ifindex 0, the normal
unbound/wildcard state: ifindex -1 marks an existing device binding that
was invalidated when the device was unregistered. Restore po->num as
before, but do not re-register the hook if device unregister already
detached the socket.
Fixes: dc99f600698d ("packet: Add fanout support.")
Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/
Assisted-by: Codex:gpt-5
Signed-off-by: David Lee <david.lee@trailofbits.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
Changes in v3:
- Drop Reported-by due to duplicated patch author.
- Add Link to the v1 discussion.
- Clarify that ifindex -1 is an invalidated-binding state.
- Add Reviewed-by tag.
Changes in v2:
- Add Fixes and Reported-by tags.
- Fix the incorrect Signed-off-by tag from v1.
Trail of Bits has a PoC that achieves local privilege escalation using this
bug on a custom kernel config with CONFIG_LIST_HARDENED disabled, which can
be shared further if needed.
net/packet/af_packet.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8e6f3a734ba0..000000000000 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
spin_lock(&po->bind_lock);
WRITE_ONCE(po->num, num);
- if (was_running)
+ /*
+ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock
+ * was dropped above. Do not re-add a fanout hook to a dead device.
+ */
+ if (was_running && READ_ONCE(po->ifindex) != -1)
register_prot_hook(sk);
spin_unlock(&po->bind_lock);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next v13 09/10] net: ethtool: Introduce ethtool command to list ports
From: Maxime Chevallier @ 2026-07-07 10:47 UTC (permalink / raw)
To: Paolo Abeni, davem, Andrew Lunn, Jakub Kicinski, Eric Dumazet,
Russell King, Heiner Kallweit
Cc: netdev, linux-kernel, thomas.petazzoni, Christophe Leroy,
Herve Codina, Florian Fainelli, Vladimir Oltean,
Köry Maincent, Marek Behún, Oleksij Rempel,
Nicolò Veronese, Simon Horman, mwojtas, Romain Gantois,
Daniel Golle, Dimitri Fedrau, Frank Wunderlich
In-Reply-To: <aaef7304-573a-419e-b631-30b300373a08@redhat.com>
Hi Paolo,
On 7/7/26 12:12, Paolo Abeni wrote:
>
> Both sashikos instances points to multiple races with dumps. I suspect
> some explicit locking is required.
>
> https://sashiko.dev/#/patchset/20260701110427.143945-1-maxime.chevallier%40bootlin.com
> https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260701110427.143945-1-maxime.chevallier%40bootlin.com
>
> I *think* this is hopefully the last pending issue.
True indeed, the other issues are sashiko saying "what if we detach a PHY and attach it
to another netdev", which can't happen :) I agree with some of the locking points that
were found, I'll address that likely as a separate cleanup.
Thanks :)
Maxime
>
> /P
>
^ permalink raw reply
* Re: [PATCH net 0/7] pull request: sfc 2026-07-01
From: Paolo Abeni @ 2026-07-07 10:59 UTC (permalink / raw)
To: alejandro.lucero-palau, netdev, kuba, davem, edumazet, horms,
dave.jiang
Cc: Alejandro Lucero
In-Reply-To: <20260701113805.14072-1-alejandro.lucero-palau@amd.com>
On 7/1/26 1:37 PM, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alucerop@amd.com>
>
> Dear net maintainers,
>
> here are the last CXL core changes for enabling CXL Type2 drivers to
> initialize a CXL-capable device plus the netdev sfc driver changes using
> this new CXL core Type2 support.
>
> Please pull or let me know of any problem!
Process note: this is 'net-next' material (as opposed to 'net'); the
target tree should be reported in each patch subj prefix.
/P
^ permalink raw reply
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