Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH bpf-next v3 06/15] bpf: Add prog_list_init_item(), prog_list_replace_item(), and prog_list_id()
From: Emil Tsalapatis @ 2026-07-13 21:56 UTC (permalink / raw)
  To: Amery Hung, bpf
  Cc: netdev, alexei.starovoitov, andrii, daniel, eddyz87, memxor,
	martin.lau, shakeel.butt, roman.gushchin, kuniyu, kerneljasonxing,
	kernel-team
In-Reply-To: <20260706171918.317102-7-ameryhung@gmail.com>

On Mon Jul 6, 2026 at 1:19 PM EDT, Amery Hung wrote:
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> Add three helpers to abstract operations on a bpf_prog_list entry.
>
> Right now, bpf_prog_array_item is initialized from prog_list_prog(pl),
> which returns either pl->prog or pl->link->link.prog. This will not work
> when struct_ops is attached to a cgroup because the attachment is backed
> by a struct_ops map instead of a BPF prog.
>
> The same applies to __cgroup_bpf_query(). Instead of always copying a
> prog id to userspace, struct_ops cgroup attachment will need to copy the
> struct_ops map id.
>
> Refactor bpf_prog_array_item initialization into prog_list_init_item()
> and prog_list_replace_item(), and refactor id lookup into prog_list_id().
> These helpers will be extended to support pl->link->map in a later patch.
>
> This is a no-op change.

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

Followup on prog_list_prog() since I hadn't realized it was moved to the
helpers in this patchset: Maybe we can just make it not return NULL
since it's impossible instead of adding error handling to minimize
churn.

>
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> Signed-off-by: Amery Hung <ameryhung@gmail.com>
> ---
>  kernel/bpf/cgroup.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
> index b100c04cb9c8..b43f0bff184c 100644
> --- a/kernel/bpf/cgroup.c
> +++ b/kernel/bpf/cgroup.c
> @@ -399,6 +399,22 @@ static struct bpf_prog *prog_list_prog(struct bpf_prog_list *pl)
>  	return NULL;
>  }
>  
> +static void prog_list_init_item(struct bpf_prog_list *pl, struct bpf_prog_array_item *item)
> +{
> +	item->prog = prog_list_prog(pl);
> +	bpf_cgroup_storages_assign(item->cgroup_storage, pl->storage);
> +}
> +
> +static void prog_list_replace_item(struct bpf_prog_list *pl, struct bpf_prog_array_item *item)
> +{
> +	WRITE_ONCE(item->prog, pl->link->link.prog);
> +}
> +
> +static u32 prog_list_id(struct bpf_prog_list *pl)
> +{
> +	return prog_list_prog(pl)->aux->id;
> +}
> +
>  /* count number of elements in the list.
>   * it's slow but the list cannot be long
>   */
> @@ -492,9 +508,7 @@ static int compute_effective_progs(struct cgroup *cgrp,
>  				item = &progs->items[fstart];
>  				fstart++;
>  			}
> -			item->prog = prog_list_prog(pl);
> -			bpf_cgroup_storages_assign(item->cgroup_storage,
> -						   pl->storage);
> +			prog_list_init_item(pl, item);
>  			cnt++;
>  		}
>  
> @@ -1015,7 +1029,7 @@ static void replace_effective_prog(struct cgroup *cgrp,
>  				desc->bpf.effective[atype],
>  				lockdep_is_held(&cgroup_mutex));
>  		item = &progs->items[pos];
> -		WRITE_ONCE(item->prog, pl->link->link.prog);
> +		prog_list_replace_item(pl, item);
>  	}
>  }
>  
> @@ -1318,15 +1332,13 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
>  		} else {
>  			struct hlist_head *progs;
>  			struct bpf_prog_list *pl;
> -			struct bpf_prog *prog;
>  			u32 id;
>  
>  			progs = &cgrp->bpf.progs[atype];
>  			cnt = min_t(int, prog_list_length(progs, NULL), total_cnt);
>  			i = 0;
>  			hlist_for_each_entry(pl, progs, node) {
> -				prog = prog_list_prog(pl);
> -				id = prog->aux->id;
> +				id = prog_list_id(pl);
>  				if (copy_to_user(prog_ids + i, &id, sizeof(id)))
>  					return -EFAULT;
>  				if (++i == cnt)


^ permalink raw reply

* Re: [PATCH net 1/3] net: dsa: tag_ocelot_8021q: don't read an unset MAC header on transmit
From: Vladimir Oltean @ 2026-07-13 21:37 UTC (permalink / raw)
  To: Doruk (0sec)
  Cc: Andrew Lunn, Florian Fainelli, Woojung Huh, Nick Child,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, stable
In-Reply-To: <CAPdMp1qf4q42MAaRqqzYnhYyU9KvdryGQR+TWsFNvJ1oCTnPKw@mail.gmail.com>

On Mon, Jul 13, 2026 at 04:12:20PM -0500, Doruk (0sec) wrote:
> Hi Vladimir,
> 
> Thanks for the review.
> 
> I checked the DSA cases with CONFIG_NET_DSA_LOOP=y. Since dsa_loop
> normally uses DSA_TAG_PROTO_NONE, I used a local repro-only override
> of dsa_loop_get_protocol() to select the relevant tagger, then sent an
> AF_PACKET/SOCK_RAW frame with PACKET_QDISC_BYPASS and
> sll_protocol=ETH_P_IP through lan1.
> 
> That leaves skb->mac_header unset (65535) on the direct-xmit path.
> 
> For tag_ocelot_8021q, the eth_hdr(skb) version reproduces as:
> 
>   BUG: KASAN: slab-out-of-bounds in ocelot_xmit()
> 
> Switching that site to skb_eth_hdr(skb) makes the same reproducer run clean.
> 
> I also checked the LAN937X path the same way by forcing
> DSA_TAG_PROTO_LAN937X. The eth_hdr(skb) version reproduces as:
> 
>   BUG: KASAN: slab-out-of-bounds in lan937x_xmit()
> 
> and the skb_eth_hdr(skb) version runs clean with the same packet sender.
> 
> So yes, for these DSA TX paths this is a real bug on the
> PACKET_QDISC_BYPASS path, not just a future-proofing cleanup. I have
> not yet checked ibmveth with a pseries/ibmveth setup.

Thanks for clarifying your testing procedure (and please do not top-post
replies).

Yes, manually editing dsa_loop_get_protocol() is the current state of
the art technology.

> For the older DSA commits you listed, I think they should be treated
> as stable candidates if they remove eth_hdr()/skb_mac_header() use
> from the same TX path. I can go through those individually and send a
> follow-up with the exact stable list if that would be useful.

Since skb_mac_header() in TX paths is the real problem, I now think
those commits should need backporting too. I only reworked the
first-order callers of skb_mac_header(), not realizing that eth_hdr()
needs rework too - and not having a clear testing procedure at the time.

I think it would be great if you could prepare an email to the stable
mailing list and to the maintainers.

^ permalink raw reply

* Re: [PATCH nf] netfilter: nft_fib: bail out if input device is missing
From: Xiang Mei @ 2026-07-13 21:33 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: Florian Westphal, Phil Sutter, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, netfilter-devel,
	coreteam, netdev, linux-kernel, AutonomousCodeSecurity, tgopinath,
	kys
In-Reply-To: <alVUka8INN918W0K@chamomile>

On Mon, Jul 13, 2026 at 2:11 PM Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>
> Hi,
>
> On Mon, Jul 13, 2026 at 06:36:14PM +0000, Xiang Mei (Microsoft) wrote:
> > nft_fib_can_skip() dereferences the input device (indev->ifindex, and
> > in->flags via nft_fib_is_loopback()) without a NULL check, assuming the
> > hook switch only admits PRE_ROUTING/INGRESS/LOCAL_IN. But NF_NETDEV_EGRESS
> > == NF_INET_LOCAL_IN == 1, so a netdev-family base chain on the egress hook
> > passes both the switch and nft_fib_validate() (which also keys only on the
> > hook number). Egress packets have no input device, so nft_fib_can_skip()
> > dereferences NULL.
>
> By reading your description, does your kernel include this patch?
>
Thanks for pointing this out. I just rechecked my verification script
and found a bug that failed to pull the latest version of nf.
(I wrongly assumed it succeeded and checked on a code-based one month older).

Sorry for the false alarm. Nvm about this email; I fixed the issue,
and it won't happen again.

Xiang

> commit d07955dd34ecae17d35d8c7d0a273a3fba653a8c
> Author: Theodor Arsenij Larionov-Trichkine <theodorlarionov@gmail.com>
> Date:   Mon Jun 29 12:53:11 2026 +0200
>
>     netfilter: nft_fib: reject fib expression on the netdev egress hook
>

^ permalink raw reply

* Re: [PATCH bpf-next v3 05/15] bpf: Replace prog_list_prog() check with direct pl->prog and pl->link check
From: Emil Tsalapatis @ 2026-07-13 21:27 UTC (permalink / raw)
  To: Amery Hung, bpf
  Cc: netdev, alexei.starovoitov, andrii, daniel, eddyz87, memxor,
	martin.lau, shakeel.butt, roman.gushchin, kuniyu, kerneljasonxing,
	kernel-team
In-Reply-To: <20260706171918.317102-6-ameryhung@gmail.com>

On Mon Jul 6, 2026 at 1:19 PM EDT, Amery Hung wrote:
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> prog_list_length() and compute_effective_progs() use !prog_list_prog(pl)
> to skip a 'detaching' pl.
>
> When pl->link is not NULL, prog_list_prog(pl) returns
> the pl->link->link.prog. This does not work for the upcoming struct_ops
> patch where pl->link is not NULL but pl->link->link.prog is NULL,
> because a struct_ops map is attached to the cgroup instead of a BPF prog.
>
> To prepare for the upcoming struct_ops patch, this patch
> replaces the prog_list_prog() test with the
> "!pl->prog && !pl->link". In __cgroup_bpf_detach(),
> both pl->prog and pl->link are set to NULL, so testing
> "!pl->prog && !pl->link" is the same test to tell
> if a pl is being detached. This change should be a no-op.
>
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> Signed-off-by: Amery Hung <ameryhung@gmail.com>

This change itself is ok, but now prog_list_prog never returns NULL
under normal operation AFAICT. Can we add error handling in the
remaining two call sites? prog_list_id() especially, since it blindly
dereferences the result like so:

	return prog_list_prog(pl)->aux->id;

Imo it's worth it even if the code gets slightly more verbose.

> ---
>  kernel/bpf/cgroup.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
> index b64f6757096c..b100c04cb9c8 100644
> --- a/kernel/bpf/cgroup.c
> +++ b/kernel/bpf/cgroup.c
> @@ -408,7 +408,7 @@ static u32 prog_list_length(struct hlist_head *head, int *preorder_cnt)
>  	u32 cnt = 0;
>  
>  	hlist_for_each_entry(pl, head, node) {
> -		if (!prog_list_prog(pl))
> +		if (!pl->prog && !pl->link)
>  			continue;
>  		if (preorder_cnt && (pl->flags & BPF_F_PREORDER))
>  			(*preorder_cnt)++;
> @@ -482,7 +482,7 @@ static int compute_effective_progs(struct cgroup *cgrp,
>  
>  		init_bstart = bstart;
>  		hlist_for_each_entry(pl, &p->bpf.progs[atype], node) {
> -			if (!prog_list_prog(pl))
> +			if (!pl->prog && !pl->link)
>  				continue;
>  
>  			if (pl->flags & BPF_F_PREORDER) {


^ permalink raw reply

* Re: [PATCH net v2] nfc: llcp: reject PDUs shorter than the LLCP header
From: David Laight @ 2026-07-13 21:15 UTC (permalink / raw)
  To: Doruk Tan Ozturk
  Cc: david, vadim.fedorenko, horms, oe-linux-nfc, netdev, linux-kernel,
	stable
In-Reply-To: <20260713155848.55530-1-doruk@0sec.ai>

On Mon, 13 Jul 2026 17:58:48 +0200
Doruk Tan Ozturk <doruk@0sec.ai> wrote:

> Every LLCP PDU begins with a two-byte header (DSAP/SSAP + PTYPE), but the
> receive path never checked that a frame is at least LLCP_HEADER_SIZE bytes
> before parsing it.

Is there a similar problem with non-linear skb?
Maybe they can't get into this code, but who knows what can happen
with unusual configs.

	David


> A peer LLCP PDU travels: NFC-DEP frame -> nfc_tm_data_received() (target /
> NCI path) or nfc_llcp_recv() (initiator data-exchange callback) ->
> __nfc_llcp_recv() -> rx_work -> nfc_llcp_rx_skb() ->
> nfc_llcp_recv_connect(). For a CONNECT (or CC) PDU nfc_llcp_recv_connect()
> computes
> 
> 	tlv_array_len = skb->len - LLCP_HEADER_SIZE;
> 
> as a size_t and hands it to the TLV walk. When skb->len is 0 or 1 the
> subtraction wraps to a huge value and the walk runs far past the skb,
> causing an out-of-bounds read; nfc_llcp_ptype()/nfc_llcp_ssap() likewise
> read pdu->data[1] for such a short frame.
> 
> A nearby NFC device can reach this without authentication; LLCP link
> activation happens automatically after NFC-DEP.
> 
> Reject PDUs shorter than the LLCP header in __nfc_llcp_recv(), the common
> choke point shared by both the target (nfc_llcp_data_received()) and
> initiator (nfc_llcp_recv()) receive paths, so a short skb is freed before
> the rx_work worker is scheduled.
> 
> Reproduced with a KFENCE out-of-bounds read via /dev/virtual_nci on
> linux-next.
> 
> Found by 0sec (https://0sec.ai) using automated source analysis.
> 
> Fixes: d646960f7986 ("NFC: Initial LLCP support")
> Cc: stable@vger.kernel.org
> Assisted-by: 0sec:claude-opus-4-8
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> ---
> v2: move the check into __nfc_llcp_recv() so a short skb is dropped
>     before the rx_work worker is scheduled (Vadim Fedorenko), which also
>     covers the initiator nfc_llcp_recv() path. Reword the commit message
>     (drop the "same guard as AGF" wording) and add a KFENCE reproduction
>     note.
> 
>  net/nfc/llcp_core.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
> index aed5fe1afef0..72b6e707ad0c 100644
> --- a/net/nfc/llcp_core.c
> +++ b/net/nfc/llcp_core.c
> @@ -1565,6 +1565,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
>  
>  static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb)
>  {
> +	if (skb->len < LLCP_HEADER_SIZE) {
> +		kfree_skb(skb);
> +		return;
> +	}
> +
>  	local->rx_pending = skb;
>  	timer_delete(&local->link_timer);
>  	schedule_work(&local->rx_work);


^ permalink raw reply

* Re: [PATCH net 1/3] net: dsa: tag_ocelot_8021q: don't read an unset MAC header on transmit
From: Doruk (0sec) @ 2026-07-13 21:12 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Florian Fainelli, Woojung Huh, Nick Child,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, stable
In-Reply-To: <20260713200417.dghlrj4ca27b6nd4@skbuf>

Hi Vladimir,

Thanks for the review.

I checked the DSA cases with CONFIG_NET_DSA_LOOP=y. Since dsa_loop
normally uses DSA_TAG_PROTO_NONE, I used a local repro-only override
of dsa_loop_get_protocol() to select the relevant tagger, then sent an
AF_PACKET/SOCK_RAW frame with PACKET_QDISC_BYPASS and
sll_protocol=ETH_P_IP through lan1.

That leaves skb->mac_header unset (65535) on the direct-xmit path.

For tag_ocelot_8021q, the eth_hdr(skb) version reproduces as:

  BUG: KASAN: slab-out-of-bounds in ocelot_xmit()

Switching that site to skb_eth_hdr(skb) makes the same reproducer run clean.

I also checked the LAN937X path the same way by forcing
DSA_TAG_PROTO_LAN937X. The eth_hdr(skb) version reproduces as:

  BUG: KASAN: slab-out-of-bounds in lan937x_xmit()

and the skb_eth_hdr(skb) version runs clean with the same packet sender.

So yes, for these DSA TX paths this is a real bug on the
PACKET_QDISC_BYPASS path, not just a future-proofing cleanup. I have
not yet checked ibmveth with a pseries/ibmveth setup.

For the older DSA commits you listed, I think they should be treated
as stable candidates if they remove eth_hdr()/skb_mac_header() use
from the same TX path. I can go through those individually and send a
follow-up with the exact stable list if that would be useful.

Thanks,
Doruk

On Mon, 13 Jul 2026 23:04:17 +0300, Vladimir Oltean <olteanv@gmail.com> wrote:
> On Mon, Jul 13, 2026 at 09:40:08PM +0200, Doruk Tan Ozturk wrote:
> > ocelot_xmit() reads the Ethernet header via eth_hdr(skb) to test the
> > destination address against the link-local range.
> >
> > On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
> > reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
> > resolves to skb->head + (u16)~0 and the read is out of bounds.
> >
> > On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
> > done for the same class by
> > commit f5089008f90c ("macsec: don't read an unset MAC header in macsec_encrypt()")
> > and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()").
> >
> > Fixes: 43ba33b4f143 ("net: dsa: tag_ocelot_8021q: fix inability to inject STP BPDUs into BLOCKING ports")
> > Cc: stable@vger.kernel.org
> > Found by 0sec automated security-research tooling (https://0sec.ai).
> > Assisted-by: 0sec:claude-opus-4-8
> > Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> > ---
>
> Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
>
> I was not aware of the bug introduced by commit d346a3fae3ff ("packet:
> introduce PACKET_QDISC_BYPASS socket option"). Commits
> eabb1494c9f2 ("net: dsa: tag_ocelot: do not rely on skb_mac_header() for VLAN xmit")
> 499b2491d550 ("net: dsa: tag_ksz: do not rely on skb_mac_header() in TX paths")
> f9346f00b5af ("net: dsa: tag_sja1105: don't rely on skb_mac_header() in TX paths")
> 0bcf2e4aca6c ("net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX")
>
> were made assuming that the bug to avoid would be exclusively a future
> one (the revert of commit 6d1ccff62780 ("net: reset mac header in
> dev_start_xmit()")) and thus they were not marked as bug fixes.
>
> Are they true bug fixes, as in "can we reproduce these [using
> CONFIG_NET_DSA_LOOP=y on virtually any network adapter]"? If so, should
> all the commits above also be backported to stable?

^ permalink raw reply

* Re: [PATCH nf] netfilter: nft_fib: bail out if input device is missing
From: Pablo Neira Ayuso @ 2026-07-13 21:11 UTC (permalink / raw)
  To: Xiang Mei (Microsoft)
  Cc: Florian Westphal, Phil Sutter, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, netfilter-devel,
	coreteam, netdev, linux-kernel, AutonomousCodeSecurity, tgopinath,
	kys
In-Reply-To: <20260713183614.2975972-1-xmei5@asu.edu>

Hi,

On Mon, Jul 13, 2026 at 06:36:14PM +0000, Xiang Mei (Microsoft) wrote:
> nft_fib_can_skip() dereferences the input device (indev->ifindex, and
> in->flags via nft_fib_is_loopback()) without a NULL check, assuming the
> hook switch only admits PRE_ROUTING/INGRESS/LOCAL_IN. But NF_NETDEV_EGRESS
> == NF_INET_LOCAL_IN == 1, so a netdev-family base chain on the egress hook
> passes both the switch and nft_fib_validate() (which also keys only on the
> hook number). Egress packets have no input device, so nft_fib_can_skip()
> dereferences NULL.

By reading your description, does your kernel include this patch?

commit d07955dd34ecae17d35d8c7d0a273a3fba653a8c
Author: Theodor Arsenij Larionov-Trichkine <theodorlarionov@gmail.com>
Date:   Mon Jun 29 12:53:11 2026 +0200
 
    netfilter: nft_fib: reject fib expression on the netdev egress hook


^ permalink raw reply

* Re: [PATCH net] tipc: fix infinite loop in __tipc_nl_compat_dumpit
From: Helen Koike @ 2026-07-13 20:54 UTC (permalink / raw)
  To: jmaloy, davem, ying.xue, netdev, tipc-discussion, linux-kernel,
	kernel-dev, erik.hugne
In-Reply-To: <20260713204940.647668-1-koike@igalia.com>

(cc + Erik)

On 7/13/26 5:49 PM, Helen Koike wrote:
> cmd->dumpit callback can return a negative errno, causing an infinite
> loop due to the while(len) condition. As the loop never terminates,
> genl_mutex is never released, and other tasks waiting on it starve in D
> state.
> 
> Check dumpit's return value, propagate it and jump to err_out on error.
> 
> Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a
> Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat")
> Signed-off-by: Helen Koike <koike@igalia.com>
> ---
> 
> Tested locally using syzbot reproducer.
> ---
>   net/tipc/netlink_compat.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 
> diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
> index 2a786c56c8c5..d9a4f94ea2d4 100644
> --- a/net/tipc/netlink_compat.c
> +++ b/net/tipc/netlink_compat.c
> @@ -221,6 +221,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
>   		int rem;
>   
>   		len = (*cmd->dumpit)(buf, &cb);
> +		if (len < 0) {
> +			err = len;
> +			goto err_out;
> +		}
>   
>   		nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) {
>   			err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN,


^ permalink raw reply

* [PATCH net] tipc: fix infinite loop in __tipc_nl_compat_dumpit
From: Helen Koike @ 2026-07-13 20:49 UTC (permalink / raw)
  To: jmaloy, davem, erik.hugne, ying.xue, netdev, tipc-discussion,
	linux-kernel, koike, kernel-dev

cmd->dumpit callback can return a negative errno, causing an infinite
loop due to the while(len) condition. As the loop never terminates,
genl_mutex is never released, and other tasks waiting on it starve in D
state.

Check dumpit's return value, propagate it and jump to err_out on error.

Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a
Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat")
Signed-off-by: Helen Koike <koike@igalia.com>
---

Tested locally using syzbot reproducer.
---
 net/tipc/netlink_compat.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 2a786c56c8c5..d9a4f94ea2d4 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -221,6 +221,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
 		int rem;
 
 		len = (*cmd->dumpit)(buf, &cb);
+		if (len < 0) {
+			err = len;
+			goto err_out;
+		}
 
 		nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) {
 			err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN,
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH bpf-next v3 03/15] bpf: Add bpf_struct_ops accessor helpers
From: Emil Tsalapatis @ 2026-07-13 20:36 UTC (permalink / raw)
  To: Amery Hung, bpf
  Cc: netdev, alexei.starovoitov, andrii, daniel, eddyz87, memxor,
	martin.lau, shakeel.butt, roman.gushchin, kuniyu, kerneljasonxing,
	kernel-team
In-Reply-To: <20260706171918.317102-4-ameryhung@gmail.com>

On Mon Jul 6, 2026 at 1:19 PM EDT, Amery Hung wrote:
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> Add the helper functions bpf_struct_ops_map_kdata() and
> bpf_struct_ops_map_cfi_stubs() in bpf_struct_ops.c. They will be called
> from cgroup.c in the upcoming patch to create a struct_ops to cgroup
> attachment link.
>
> bpf_struct_ops_valid_to_reg() is also exposed for the upcoming caller
> in cgroup.c.
>
> The link update validation is also refactored into a new function
> bpf_struct_ops_link_update_check() such that it can be reused by the
> caller in cgroup.c in the upcoming patch.
>
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> Signed-off-by: Amery Hung <ameryhung@gmail.com>

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

> ---
>  include/linux/bpf.h         | 28 ++++++++++++++++++++
>  kernel/bpf/bpf_struct_ops.c | 53 +++++++++++++++++++++++++++----------
>  2 files changed, 67 insertions(+), 14 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 7ac8873839f4..047ffc029666 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2252,6 +2252,12 @@ u32 bpf_struct_ops_id(const void *kdata);
>  int bpf_struct_ops_for_each_prog(const void *kdata,
>  				 int (*cb)(struct bpf_prog *prog, void *data),
>  				 void *data);
> +void *bpf_struct_ops_map_kdata(struct bpf_map *map);
> +u32 bpf_struct_ops_kdata_map_id(void *kdata);
> +void *bpf_struct_ops_map_cfi_stubs(struct bpf_map *map);
> +bool bpf_struct_ops_valid_to_reg(struct bpf_map *map);
> +int bpf_struct_ops_link_update_check(struct bpf_map *new_map, struct bpf_map *old_map,
> +				     struct bpf_map *expected_old_map);
>  
>  #ifdef CONFIG_NET
>  /* Define it here to avoid the use of forward declaration */
> @@ -2316,6 +2322,28 @@ static inline void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struc
>  static inline void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc)
>  {
>  }
> +static inline void *bpf_struct_ops_map_kdata(struct bpf_map *map)
> +{
> +	return NULL;
> +}
> +static inline u32 bpf_struct_ops_kdata_map_id(void *kdata)
> +{
> +	return 0;
> +}
> +static inline void *bpf_struct_ops_map_cfi_stubs(struct bpf_map *map)
> +{
> +	return NULL;
> +}
> +static inline bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
> +{
> +	return false;
> +}
> +static inline int bpf_struct_ops_link_update_check(struct bpf_map *new_map,
> +						   struct bpf_map *old_map,
> +						   struct bpf_map *expected_old_map)
> +{
> +	return -EOPNOTSUPP;
> +}
>  
>  #endif
>  
> diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
> index c422ce41873e..3d650a7e9f68 100644
> --- a/kernel/bpf/bpf_struct_ops.c
> +++ b/kernel/bpf/bpf_struct_ops.c
> @@ -1236,7 +1236,23 @@ int bpf_struct_ops_for_each_prog(const void *kdata,
>  }
>  EXPORT_SYMBOL_GPL(bpf_struct_ops_for_each_prog);
>  
> -static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
> +void *bpf_struct_ops_map_kdata(struct bpf_map *map)
> +{
> +	struct bpf_struct_ops_map *st_map;
> +
> +	st_map = container_of(map, struct bpf_struct_ops_map, map);
> +	return st_map->kvalue.data;
> +}
> +
> +void *bpf_struct_ops_map_cfi_stubs(struct bpf_map *map)
> +{
> +	struct bpf_struct_ops_map *st_map;
> +
> +	st_map = container_of(map, struct bpf_struct_ops_map, map);
> +	return st_map->st_ops_desc->st_ops->cfi_stubs;
> +}
> +
> +bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
>  {
>  	struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map;
>  
> @@ -1289,6 +1305,26 @@ static int bpf_struct_ops_map_link_fill_link_info(const struct bpf_link *link,
>  	return 0;
>  }
>  
> +int bpf_struct_ops_link_update_check(struct bpf_map *new_map,
> +				     struct bpf_map *old_map,
> +				     struct bpf_map *expected_old_map)
> +{
> +	struct bpf_struct_ops_map *st_map, *old_st_map;
> +
> +	if (!old_map)
> +		return -ENOLINK;
> +	if (expected_old_map && old_map != expected_old_map)
> +		return -EPERM;
> +
> +	st_map = container_of(new_map, struct bpf_struct_ops_map, map);
> +	old_st_map = container_of(old_map, struct bpf_struct_ops_map, map);
> +	/* The new and old struct_ops must be the same type. */
> +	if (st_map->st_ops_desc != old_st_map->st_ops_desc)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map *new_map,
>  					  struct bpf_map *expected_old_map)
>  {
> @@ -1307,23 +1343,12 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
>  		return -EOPNOTSUPP;
>  
>  	mutex_lock(&update_mutex);
> -
>  	old_map = st_link->map;
> -	if (!old_map) {
> -		err = -ENOLINK;
> -		goto err_out;
> -	}
> -	if (expected_old_map && old_map != expected_old_map) {
> -		err = -EPERM;
> +	err = bpf_struct_ops_link_update_check(new_map, old_map, expected_old_map);
> +	if (err)
>  		goto err_out;
> -	}
>  
>  	old_st_map = container_of(old_map, struct bpf_struct_ops_map, map);
> -	/* The new and old struct_ops must be the same type. */
> -	if (st_map->st_ops_desc != old_st_map->st_ops_desc) {
> -		err = -EINVAL;
> -		goto err_out;
> -	}
>  
>  	err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data, link);
>  	if (err)


^ permalink raw reply

* Re: [PATCH RFC v2 5/9] leds: Add trigger_may_offload attribute
From: Thomas Weißschuh @ 2026-07-13 20:36 UTC (permalink / raw)
  To: Rong Zhang
  Cc: Lee Jones, Pavel Machek, Jonathan Corbet, Shuah Khan,
	Benson Leung, Guenter Roeck, Marek Behún, Mark Pearson,
	Derek J. Clark, Hans de Goede, Ilpo Järvinen, Ike Panhc,
	Andrew Lunn, Jakub Kicinski, Vishnu Sankar, Vishnu Sankar,
	linux-leds, netdev, linux-doc, linux-kernel, chrome-platform,
	platform-driver-x86
In-Reply-To: <20260618-leds-trigger-hw-changed-v2-5-c28c44053cf3@rong.moe>

On 2026-06-18 00:47:59+0800, Rong Zhang wrote:
> There are multiple triggers implementing hardware control. Only "netdev"
> provides a custom attribute to determine if it's offloaded to hardware
> (i.e., in hardware control). For other triggers, there is no obvious way
> for userspace to determine the trigger state programmatically. Moreover,
> userspace can't query if an LED device supports hardware control or
> identifies these triggers.
> 
> Add a new attribute "trigger_may_offload" to the LED core, so that
> userspace can determine:
> 
> - if the LED device supports hardware control (supported => visible)
> - which trigger is the hardware control trigger selected by the LED
>   device
> - if the trigger is selected ("<foo_trigger>")
> - if the trigger is offloaded ("[foo_trigger]")
> 
> Note: the documentation describes the attribute as "returning a list"
> despite the LED core currently only supports one hardware control
> trigger per LED device. This is intentional to make the attribute
> extensible in the future without breaking userspace.

Maybe also mention that the old 'offloaded' attribute is deprecated.
However, does it really need to be deprecated?

> Signed-off-by: Rong Zhang <i@rong.moe>
> ---
>  .../ABI/obsolete/sysfs-class-led-trigger-netdev    | 16 ++++++++
>  Documentation/ABI/testing/sysfs-class-led          | 22 +++++++++++
>  .../ABI/testing/sysfs-class-led-trigger-netdev     | 13 -------
>  Documentation/leds/leds-class.rst                  |  8 ++++
>  drivers/leds/led-class.c                           | 23 +++++++++++
>  drivers/leds/led-triggers.c                        | 45 ++++++++++++++++++++++
>  drivers/leds/leds.h                                |  2 +
>  drivers/leds/trigger/ledtrig-netdev.c              |  2 +
>  8 files changed, 118 insertions(+), 13 deletions(-)
> 
> diff --git a/Documentation/ABI/obsolete/sysfs-class-led-trigger-netdev b/Documentation/ABI/obsolete/sysfs-class-led-trigger-netdev
> new file mode 100644
> index 000000000000..8d2fbfaf50c3
> --- /dev/null
> +++ b/Documentation/ABI/obsolete/sysfs-class-led-trigger-netdev
> @@ -0,0 +1,16 @@
> +What:		/sys/class/leds/<led>/offloaded
> +Date:		June 2026
> +KernelVersion:	7.3
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Communicate whether the LED trigger modes are offloaded to
> +		hardware or whether software fallback is used.
> +
> +		If 0, the LED is using software fallback to blink.
> +
> +		If 1, the LED blinking in requested mode is offloaded to
> +		hardware.
> +
> +		/sys/class/leds/<led>/trigger_may_offload provides a generic
> +		method to query the offloaded state of supported triggers,
> +		superseding this attribute.
> diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led
> index 0313b82644f2..edd5a9a74dfd 100644
> --- a/Documentation/ABI/testing/sysfs-class-led
> +++ b/Documentation/ABI/testing/sysfs-class-led
> @@ -78,6 +78,28 @@ Description:
>  		(which would often be configured in the device tree for the
>  		hardware).
>  
> +What:		/sys/class/leds/<led>/trigger_may_offload
> +Date:		June 2026
> +KernelVersion:	7.3
> +Contact:	linux-leds@vger.kernel.org
> +Description:
> +		Names and states of triggers that may be offloaded to hardware.
> +		Such triggers are also called "hw control trigger" in some
> +		context.
> +
> +		Only exists when the LED supports trigger offload.
> +
> +		Reading this file returns a list of triggers that are capable to
> +		be offloaded. The optional brackets around the trigger name
> +		indicate the state of the current trigger:
> +
> +		- `foo_trigger`: the trigger is not selected.
> +		- `<foo_trigger>`: the trigger is selected, but falls back to
> +		  software blink for some reason (e.g., incompatible trigger
> +		  parameters)
> +		- `[foo_trigger]`: the trigger is selected and offloaded to
> +		  hardware.
> +
>  What:		/sys/class/leds/<led>/inverted
>  Date:		January 2011
>  KernelVersion:	2.6.38
> diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
> index ed46b37ab8a2..396d37a4b820 100644
> --- a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
> +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev
> @@ -62,19 +62,6 @@ Description:
>  		When offloaded is true, the blink interval is controlled by
>  		hardware and won't reflect the value set in interval.
>  
> -What:		/sys/class/leds/<led>/offloaded
> -Date:		Jun 2023
> -KernelVersion:	6.5
> -Contact:	linux-leds@vger.kernel.org
> -Description:
> -		Communicate whether the LED trigger modes are offloaded to
> -		hardware or whether software fallback is used.
> -
> -		If 0, the LED is using software fallback to blink.
> -
> -		If 1, the LED blinking in requested mode is offloaded to
> -		hardware.
> -
>  What:		/sys/class/leds/<led>/link_10
>  Date:		Jun 2023
>  KernelVersion:	6.5
> diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst
> index 84665200a88d..41342ecb5f6b 100644
> --- a/Documentation/leds/leds-class.rst
> +++ b/Documentation/leds/leds-class.rst
> @@ -179,6 +179,9 @@ ops and needs to declare specific support for the supported triggers.
>  
>  With hw control we refer to the LED driven by hardware.
>  
> +A sysfs attribute `trigger_may_offload` is provided for userspace to
> +query supported triggers and their states.
> +
>  LED driver must define the following value to support hw control:
>  
>      - hw_control_trigger:
> @@ -240,6 +243,11 @@ LED trigger must implement the following API to support hw control:
>                  return a boolean indicating if the trigger is offloaded to
>                  hardware.
>  
> +                If an LED driver specifies a hw control trigger but the
> +                latter doesn't implement this callback, a dev_err_once will
> +                be emitted and the LED trigger will be assumed to be not
> +                offloaded.

Not sure if this needs to be documented.
I would make this optional initally and enforce it after all the drivers
have been changed in the series.

> +
>  LED driver can activate additional modes by default to workaround the
>  impossibility of supporting each different mode on the supported trigger.
>  Examples are hardcoding the blink speed to a set interval, enable special
> diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
> index 9e14ae588f78..0ac80b93b8b5 100644
> --- a/drivers/leds/led-class.c
> +++ b/drivers/leds/led-class.c
> @@ -90,8 +90,31 @@ static const struct bin_attribute *const led_trigger_bin_attrs[] = {
>  	&bin_attr_trigger,
>  	NULL,
>  };
> +
> +static DEVICE_ATTR(trigger_may_offload, 0444, led_trigger_may_offload_show, NULL);

DEVICE_ATTR_RO()

> +static struct attribute *led_trigger_attrs[] = {
> +	&dev_attr_trigger_may_offload.attr,
> +	NULL,

No comma after the sentinel.

> +};
> +
> +static umode_t led_trigger_is_visible(struct kobject *kobj,
> +				      struct attribute *attr,
> +				      int idx)
> +{
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +
> +	if (attr == &dev_attr_trigger_may_offload.attr &&
> +	    !led_cdev->hw_control_trigger)

Can be a single line.

> +		return 0;
> +
> +	return attr->mode;
> +}
> +
>  static const struct attribute_group led_trigger_group = {
>  	.bin_attrs = led_trigger_bin_attrs,
> +	.attrs = led_trigger_attrs,
> +	.is_visible = led_trigger_is_visible,
>  };
>  #endif
>  
> diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
> index b1223218bda1..c43229d9c4c1 100644
> --- a/drivers/leds/led-triggers.c
> +++ b/drivers/leds/led-triggers.c
> @@ -313,6 +313,51 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
>  }
>  EXPORT_SYMBOL_GPL(led_trigger_set_default);
>  
> +/*
> + * Caller must ensure led_cdev->trigger_lock held,

Use lockdep_assert_held() to document and validate locking invariants.

> + * and led_cdev->trigger->name must match led_cdev->hw_control_trigger.
> + */
> +static bool led_trigger_get_offloaded(struct led_classdev *led_cdev)
> +{
> +	if (likely(led_cdev->trigger->offloaded))
> +		return led_cdev->trigger->offloaded(led_cdev);
> +
> +	dev_err_once(led_cdev->dev,
> +		     "hw control trigger %s doesn't implement offloaded(), this is a bug\n",
> +		     led_cdev->trigger->name);
> +	return false;
> +}
> +
> +ssize_t led_trigger_may_offload_show(struct device *dev,
> +				     struct device_attribute *attr, char *buf)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	bool hit, offloaded = false;
> +	struct led_trigger *trig;
> +	int len;
> +
> +	mutex_lock(&led_cdev->led_access);
> +	down_read(&led_cdev->trigger_lock);

guard()?

> +
> +	trig = led_cdev->trigger;
> +
> +	hit = trig && !strcmp(led_cdev->hw_control_trigger, trig->name);
> +	if (hit)
> +		offloaded = led_trigger_get_offloaded(led_cdev);
> +
> +	/* [offloaded] <active_but_not_offloaded> inactive */
> +	len = sysfs_emit(buf, "%s%s%s\n",
> +			 offloaded ? "[" : (hit ? "<" : ""),
> +			 led_cdev->hw_control_trigger,
> +			 offloaded ? "]" : (hit ? ">" : ""));
> +
> +	up_read(&led_cdev->trigger_lock);
> +	mutex_unlock(&led_cdev->led_access);
> +
> +	return len;
> +}
> +EXPORT_SYMBOL_GPL(led_trigger_may_offload_show);
> +
>  /* LED Trigger Interface */
>  
>  int led_trigger_register(struct led_trigger *trig)
> diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
> index bee46651e068..9177e098989b 100644
> --- a/drivers/leds/leds.h
> +++ b/drivers/leds/leds.h
> @@ -27,6 +27,8 @@ ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
>  ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
>  			const struct bin_attribute *bin_attr, char *buf,
>  			loff_t pos, size_t count);
> +ssize_t led_trigger_may_offload_show(struct device *dev,
> +				     struct device_attribute *attr, char *buf);
>  
>  extern struct rw_semaphore leds_list_lock;
>  extern struct list_head leds_list;
> diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
> index a26109ca4b1c..21f22eea4ab8 100644
> --- a/drivers/leds/trigger/ledtrig-netdev.c
> +++ b/drivers/leds/trigger/ledtrig-netdev.c
> @@ -487,6 +487,8 @@ static ssize_t offloaded_show(struct device *dev,
>  {
>  	struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
>  
> +	dev_warn_once(dev, "offloaded attribute has been deprecated, see trigger_may_offload.\n");
> +
>  	return sprintf(buf, "%d\n", trigger_data->hw_control);
>  }
>  
> 
> -- 
> 2.53.0
> 

^ permalink raw reply

* Re: [PATCH bpf-next v3 04/15] bpf: Remove unnecessary prog_list_prog() check
From: Emil Tsalapatis @ 2026-07-13 20:35 UTC (permalink / raw)
  To: Amery Hung, bpf
  Cc: netdev, alexei.starovoitov, andrii, daniel, eddyz87, memxor,
	martin.lau, shakeel.butt, roman.gushchin, kuniyu, kerneljasonxing,
	kernel-team
In-Reply-To: <20260706171918.317102-5-ameryhung@gmail.com>

On Mon Jul 6, 2026 at 1:19 PM EDT, Amery Hung wrote:
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> effective_prog_pos(), called from replace_effective_prog() and
> purge_effective_progs(), tests "!prog_list_prog(pl)" to skip a
> 'detaching' pl.
>
> When detaching a pl, pl->prog and pl->link are set to NULL in case
> the update_effective_progs() failed.
>
> However, replace_effective_prog() is not detaching a pl,
> so the case "!prog_list_prog()" will not happen.
>
> In purge_effective_prog(), the pl->prog and pl->link are restored
> before calling purge_effective_progs(), so the case "!prog_list_prog()"
> will not happen either.
>
> This patch removes them as a prep work for the upcoming work
> in attaching struct_ops to cgroup. When attaching a struct_ops
> to cgroup, there is a link->map case and the prog_list_prog()
> will not consider the link->map. The replace_effective_prog()
> and purge_effective_progs() will then incorrectly skip a pl
> with struct_ops map attached to it.
>
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> Signed-off-by: Amery Hung <ameryhung@gmail.com>

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

> ---
>  kernel/bpf/cgroup.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
> index 4355ccb78a9c..b64f6757096c 100644
> --- a/kernel/bpf/cgroup.c
> +++ b/kernel/bpf/cgroup.c
> @@ -965,9 +965,10 @@ static int effective_prog_pos(struct cgroup *cgrp,
>  
>  		init_bstart = bstart;
>  		hlist_for_each_entry(pl, &p->bpf.progs[atype], node) {
> -			if (!prog_list_prog(pl))
> -				continue;
> -
> +			/*
> +			 * No detaching pl (NULL prog and link) is visible to the callers,
> +			 * so skip the check compute_effective_progs() needs.
> +			 */
>  			if (pl->flags & BPF_F_PREORDER) {
>  				if (pl == target_pl)
>  					pos = bstart;


^ permalink raw reply

* Re: [PATCH 5.10.y] net: Drop the lock in skb_may_tx_timestamp()
From: Sasha Levin @ 2026-07-13 20:34 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, bigeasy, willemb, kerneljasonxing, edumazet, pabeni,
	lulie, davem, kuba, netdev, linux-kernel, dust.li, heiko.stuebner
In-Reply-To: <20260713025017.38079-1-lulie@linux.alibaba.com>

> commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
>
> skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
> not be taken in IRQ context, only softirq is okay. A few drivers receive
> the timestamp via a dedicated interrupt and complete the TX timestamp
> from that handler. This will lead to a deadlock if the lock is already
> write-locked on the same CPU.

Queued for 5.10.y, thanks.

-- 
Thanks,
Sasha

^ permalink raw reply

* Re: [PATCH 5.15.y] net: Drop the lock in skb_may_tx_timestamp()
From: Sasha Levin @ 2026-07-13 20:34 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, bigeasy, willemb, kerneljasonxing, edumazet, pabeni,
	lulie, davem, kuba, netdev, linux-kernel, dust.li, heiko.stuebner
In-Reply-To: <20260713024943.37452-1-lulie@linux.alibaba.com>

> commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
>
> skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
> not be taken in IRQ context, only softirq is okay. A few drivers receive
> the timestamp via a dedicated interrupt and complete the TX timestamp
> from that handler. This will lead to a deadlock if the lock is already
> write-locked on the same CPU.

Queued for 5.15.y, thanks.

-- 
Thanks,
Sasha

^ permalink raw reply

* Re: [PATCH 6.1.y] net: Drop the lock in skb_may_tx_timestamp()
From: Sasha Levin @ 2026-07-13 20:34 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, bigeasy, willemb, kerneljasonxing, edumazet, pabeni,
	lulie, davem, kuba, netdev, linux-kernel, dust.li, heiko.stuebner
In-Reply-To: <20260713024912.36991-1-lulie@linux.alibaba.com>

> commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
>
> skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
> not be taken in IRQ context, only softirq is okay. A few drivers receive
> the timestamp via a dedicated interrupt and complete the TX timestamp
> from that handler. This will lead to a deadlock if the lock is already
> write-locked on the same CPU.

Queued for 6.1.y, thanks.

-- 
Thanks,
Sasha

^ permalink raw reply

* Re: [PATCH 1/1] tls: device: push pending open record on splice EOF
From: Nils Juenemann @ 2026-07-13 20:29 UTC (permalink / raw)
  To: rjethwani
  Cc: netdev, john.fastabend, kuba, sd, davem, pabeni, edumazet, leon,
	nils.juenemann
In-Reply-To: <20260709224436.1608993-2-rjethwani@purestorage.com>

On Thu, Jul 9, 2026 at 4:44 PM Rishikesh Jethwani <rjethwani@purestorage.com> wrote:
>
> On kTLS device-offload sockets, sendfile() with count > EOF can reach
> ->splice_eof() with a fully assembled but still-open TLS record left
> pending.
[...]

Confirmed on ConnectX-6 Dx with TLS 1.3 device offload: with this fix,
the sendfile() count > EOF + abrupt close() case no longer drops the
final record.

Tested-by: Nils Juenemann <nils.juenemann@gmail.com>

^ permalink raw reply

* Re: [PATCH RFC v2 2/9] leds: cros_ec: Implement offloaded() callback for trigger
From: Thomas Weißschuh @ 2026-07-13 20:28 UTC (permalink / raw)
  To: Rong Zhang
  Cc: Lee Jones, Pavel Machek, Jonathan Corbet, Shuah Khan,
	Benson Leung, Guenter Roeck, Marek Behún, Mark Pearson,
	Derek J. Clark, Hans de Goede, Ilpo Järvinen, Ike Panhc,
	Andrew Lunn, Jakub Kicinski, Vishnu Sankar, Vishnu Sankar,
	linux-leds, netdev, linux-doc, linux-kernel, chrome-platform,
	platform-driver-x86
In-Reply-To: <20260618-leds-trigger-hw-changed-v2-2-c28c44053cf3@rong.moe>

On 2026-06-18 00:47:56+0800, Rong Zhang wrote:
> "chromeos-auto" is a private hardware control trigger which always stays
> in hardware control. Implement offloaded() callback with its return
> value to be always true to reflect this.
> 
> Signed-off-by: Rong Zhang <i@rong.moe>

Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>

> ---
>  drivers/leds/leds-cros_ec.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/leds/leds-cros_ec.c b/drivers/leds/leds-cros_ec.c
> index bea3cc3fbfd2..f48e3cf6ccf6 100644
> --- a/drivers/leds/leds-cros_ec.c
> +++ b/drivers/leds/leds-cros_ec.c
> @@ -86,12 +86,18 @@ static int cros_ec_led_trigger_activate(struct led_classdev *led_cdev)
>  	return cros_ec_led_send_cmd(priv->cros_ec, &arg);
>  }
>  
> +static bool cros_ec_led_trigger_offloaded(struct led_classdev *led_cdev)
> +{
> +	return true;
> +}
> +
>  static struct led_hw_trigger_type cros_ec_led_trigger_type;
>  
>  static struct led_trigger cros_ec_led_trigger = {
>  	.name = "chromeos-auto",
>  	.trigger_type = &cros_ec_led_trigger_type,
>  	.activate = cros_ec_led_trigger_activate,
> +	.offloaded = cros_ec_led_trigger_offloaded,
>  };
>  
>  static int cros_ec_led_brightness_set_blocking(struct led_classdev *led_cdev,
> 
> -- 
> 2.53.0
> 

^ permalink raw reply

* Re: [PATCH RFC v2 1/9] leds: Add callback offloaded() to query the state of hardware control trigger
From: Thomas Weißschuh @ 2026-07-13 20:27 UTC (permalink / raw)
  To: Rong Zhang
  Cc: Lee Jones, Pavel Machek, Jonathan Corbet, Shuah Khan,
	Benson Leung, Guenter Roeck, Marek Behún, Mark Pearson,
	Derek J. Clark, Hans de Goede, Ilpo Järvinen, Ike Panhc,
	Andrew Lunn, Jakub Kicinski, Vishnu Sankar, Vishnu Sankar,
	linux-leds, netdev, linux-doc, linux-kernel, chrome-platform,
	platform-driver-x86
In-Reply-To: <20260618-leds-trigger-hw-changed-v2-1-c28c44053cf3@rong.moe>

On 2026-06-18 00:47:55+0800, Rong Zhang wrote:
> There are multiple triggers implementing hardware control. However, the
> LED core doesn't really know the hardware control state since the
> coordination is done directly between the trigger and the LED device.
> 
> Add an offloaded() callback so that the LED core can query the hardware
> control state.

For review it would be easier if the code using the new callback was
introduced *before* the driver implementation.

> Signed-off-by: Rong Zhang <i@rong.moe>
> ---
>  Documentation/leds/leds-class.rst | 5 +++++
>  include/linux/leds.h              | 1 +
>  2 files changed, 6 insertions(+)

(...)

^ permalink raw reply

* Re: [PATCH net 1/3] net: dsa: tag_ocelot_8021q: don't read an unset MAC header on transmit
From: Vladimir Oltean @ 2026-07-13 20:04 UTC (permalink / raw)
  To: Doruk Tan Ozturk
  Cc: Andrew Lunn, Florian Fainelli, Woojung Huh, Nick Child,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, stable
In-Reply-To: <20260713194010.54642-2-doruk@0sec.ai>

On Mon, Jul 13, 2026 at 09:40:08PM +0200, Doruk Tan Ozturk wrote:
> ocelot_xmit() reads the Ethernet header via eth_hdr(skb) to test the
> destination address against the link-local range.
> 
> On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
> reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
> resolves to skb->head + (u16)~0 and the read is out of bounds.
> 
> On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
> done for the same class by
> commit f5089008f90c ("macsec: don't read an unset MAC header in macsec_encrypt()")
> and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()").
> 
> Fixes: 43ba33b4f143 ("net: dsa: tag_ocelot_8021q: fix inability to inject STP BPDUs into BLOCKING ports")
> Cc: stable@vger.kernel.org
> Found by 0sec automated security-research tooling (https://0sec.ai).
> Assisted-by: 0sec:claude-opus-4-8
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> ---

Reviewed-by: Vladimir Oltean <olteanv@gmail.com>

I was not aware of the bug introduced by commit d346a3fae3ff ("packet:
introduce PACKET_QDISC_BYPASS socket option"). Commits
eabb1494c9f2 ("net: dsa: tag_ocelot: do not rely on skb_mac_header() for VLAN xmit")
499b2491d550 ("net: dsa: tag_ksz: do not rely on skb_mac_header() in TX paths")
f9346f00b5af ("net: dsa: tag_sja1105: don't rely on skb_mac_header() in TX paths")
0bcf2e4aca6c ("net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX")

were made assuming that the bug to avoid would be exclusively a future
one (the revert of commit 6d1ccff62780 ("net: reset mac header in
dev_start_xmit()")) and thus they were not marked as bug fixes.

Are they true bug fixes, as in "can we reproduce these [using
CONFIG_NET_DSA_LOOP=y on virtually any network adapter]"? If so, should
all the commits above also be backported to stable?

^ permalink raw reply

* [PATCH net 3/3] ibmveth: don't read an unset MAC header on transmit
From: Doruk Tan Ozturk @ 2026-07-13 19:40 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn, Florian Fainelli, Woojung Huh,
	Nick Child, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, Doruk Tan Ozturk,
	stable
In-Reply-To: <20260713194010.54642-1-doruk@0sec.ai>

ibmveth_is_packet_unsupported(), called from ibmveth_start_xmit(), reads
the Ethernet header via eth_hdr(skb) to test the destination address.

On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
resolves to skb->head + (u16)~0 and the read is out of bounds.

On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
done for the same class by
commit f5089008f90c ("macsec: don't read an unset MAC header in macsec_encrypt()")
and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()").

Fixes: 6f2275433a2f ("ibmveth: Detect unsupported packets before sending to the hypervisor")
Cc: stable@vger.kernel.org
Found by 0sec automated security-research tooling (https://0sec.ai).
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
---
 drivers/net/ethernet/ibm/ibmveth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 73e051d26b9d..88e8bdfbcd11 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1218,7 +1218,7 @@ static int ibmveth_is_packet_unsupported(struct sk_buff *skb,
 	struct ethhdr *ether_header;
 	int ret = 0;
 
-	ether_header = eth_hdr(skb);
+	ether_header = skb_eth_hdr(skb);
 
 	if (ether_addr_equal(ether_header->h_dest, netdev->dev_addr)) {
 		netdev_dbg(netdev, "veth doesn't support loopback packets, dropping packet.\n");
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 2/3] net: dsa: tag_ksz: don't read an unset MAC header in lan937x_xmit()
From: Doruk Tan Ozturk @ 2026-07-13 19:40 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn, Florian Fainelli, Woojung Huh,
	Nick Child, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, Doruk Tan Ozturk,
	stable
In-Reply-To: <20260713194010.54642-1-doruk@0sec.ai>

lan937x_xmit() reads the Ethernet header via eth_hdr(skb) to test the
destination address. The sibling xmit paths in this file (ksz8795_xmit,
ksz9477_xmit, ksz9893_xmit) already use skb_eth_hdr(); lan937x_xmit() is
the lone hold-out.

On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
resolves to skb->head + (u16)~0 and the read is out of bounds.

On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
done for the same class by
commit f5089008f90c ("macsec: don't read an unset MAC header in macsec_encrypt()")
and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()").

Fixes: 092f875131dc ("net: dsa: tag_ksz: add tag handling for Microchip LAN937x")
Cc: stable@vger.kernel.org
Found by 0sec automated security-research tooling (https://0sec.ai).
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
---
 net/dsa/tag_ksz.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index 67fa89f102e0..4f74336ae396 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -430,7 +430,7 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
 	u16 queue_mapping = skb_get_queue_mapping(skb);
 	u8 prio = netdev_txq_to_tc(dev, queue_mapping);
 	struct dsa_port *dp = dsa_user_to_port(dev);
-	const struct ethhdr *hdr = eth_hdr(skb);
+	const struct ethhdr *hdr = skb_eth_hdr(skb);
 	__be16 *tag;
 	u16 val;
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 1/3] net: dsa: tag_ocelot_8021q: don't read an unset MAC header on transmit
From: Doruk Tan Ozturk @ 2026-07-13 19:40 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn, Florian Fainelli, Woojung Huh,
	Nick Child, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, Doruk Tan Ozturk,
	stable
In-Reply-To: <20260713194010.54642-1-doruk@0sec.ai>

ocelot_xmit() reads the Ethernet header via eth_hdr(skb) to test the
destination address against the link-local range.

On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
resolves to skb->head + (u16)~0 and the read is out of bounds.

On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
done for the same class by
commit f5089008f90c ("macsec: don't read an unset MAC header in macsec_encrypt()")
and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in macvlan_broadcast()").

Fixes: 43ba33b4f143 ("net: dsa: tag_ocelot_8021q: fix inability to inject STP BPDUs into BLOCKING ports")
Cc: stable@vger.kernel.org
Found by 0sec automated security-research tooling (https://0sec.ai).
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
---
 net/dsa/tag_ocelot_8021q.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c
index f50f1cd83f16..4514026897d1 100644
--- a/net/dsa/tag_ocelot_8021q.c
+++ b/net/dsa/tag_ocelot_8021q.c
@@ -71,7 +71,7 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
 	u16 queue_mapping = skb_get_queue_mapping(skb);
 	u8 pcp = netdev_txq_to_tc(netdev, queue_mapping);
 	u16 tx_vid = dsa_tag_8021q_standalone_vid(dp);
-	struct ethhdr *hdr = eth_hdr(skb);
+	struct ethhdr *hdr = skb_eth_hdr(skb);
 
 	if (ocelot_ptp_rew_op(skb) || is_link_local_ether_addr(hdr->h_dest))
 		return ocelot_defer_xmit(dp, skb);
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 0/3] net: don't read an unset MAC header on the raw/qdisc-bypass TX path
From: Doruk Tan Ozturk @ 2026-07-13 19:40 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn, Florian Fainelli, Woojung Huh,
	Nick Child, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: netdev, linux-kernel, linuxppc-dev, Sabrina Dubroca,
	Arun Ramadoss, UNGLinuxDriver, Michael Ellerman, Doruk Tan Ozturk

On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path, skb->mac_header
is left unset when ndo_start_xmit() runs, so eth_hdr(skb) resolves ~64KB out of
bounds. Commit f5089008f90c ("macsec: don't read an unset MAC header in
macsec_encrypt()") fixed one instance; these three are the same class in other
TX/.xmit paths, each reading eth_hdr(skb)->h_dest. On TX the L2 header is at
skb->data, so use skb_eth_hdr() (a no-op on normal TX where mac_header is set).

Found by static analysis (0sec); verified against source, not runtime-reproduced.
Confirmed by an independent cross-check that mac_header is unset on the bypass
path (__dev_direct_xmit does not reset it). More siblings exist (sja1105 shared
TX/RX helper, atlantic PTP path) and will follow separately.


Doruk Tan Ozturk (3):
  net: dsa: tag_ocelot_8021q: don't read an unset MAC header on transmit
  net: dsa: tag_ksz: don't read an unset MAC header in lan937x_xmit()
  ibmveth: don't read an unset MAC header on transmit

 drivers/net/ethernet/ibm/ibmveth.c | 2 +-
 net/dsa/tag_ksz.c                  | 2 +-
 net/dsa/tag_ocelot_8021q.c         | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH net-next] sctp: replace cb->args[4] with a local variable in sctp_diag_dump()
From: Xin Long @ 2026-07-13 19:26 UTC (permalink / raw)
  To: network dev, linux-sctp
  Cc: davem, kuba, Eric Dumazet, Paolo Abeni, Simon Horman,
	Marcelo Ricardo Leitner
In-Reply-To: <e0076ec046fbd8a70d4f3facfb701473d08c3ebb.1783632513.git.lucien.xin@gmail.com>

> diff --git a/net/sctp/diag.c b/net/sctp/diag.c
> index c2a0de2adf6f..a9bb31303613 100644
> --- a/net/sctp/diag.c
> +++ b/net/sctp/diag.c
> @@ -299,18 +299,21 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t
>  static int sctp_sock_dump(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p)
>  {
>       struct sctp_comm_param *commp = p;
> -     struct sock *sk = ep->base.sk;
> +     struct sock *sk = ep->base.sk, *nsk;
>       struct sk_buff *skb = commp->skb;
>       struct netlink_callback *cb = commp->cb;
>       const struct inet_diag_req_v2 *r = commp->r;
> +     u32 portid = NETLINK_CB(cb->skb).portid;
>       struct sctp_association *assoc;
> -     int err = 0;
> +     int err = 0, idx = 0;
> +
> +     nsk = NETLINK_CB(cb->skb).sk;
>
>       lock_sock(sk);
>       if (ep != tsp->asoc->ep)
>               goto release;
Could the peel-off exit here leave stale state in cb->args[1] across
netlink dump sessions?
Prior to this patch, sctp_diag_dump() always executed:
        cb->args[1] = cb->args[4];
        cb->args[4] = 0;
after sctp_transport_traverse_process() returned.  Because cb->args[4]
was only bumped inside the list_for_each_entry loop and was reset to 0
when the loop completed normally, that outer assignment acted as an
unconditional clear of cb->args[1] whenever no traversal was
interrupted.
After the patch, cb->args[1] is only cleared to 0 when the
list_for_each_entry loop in sctp_sock_dump() runs to completion:
>       list_for_each_entry(assoc, &ep->asocs, asocs) {
> -             if (cb->args[4] < cb->args[1])
> +             if (idx < cb->args[1])
>                       goto next;
[ ... ]
>  next:
> -             cb->args[4]++;
> +             idx++;
>       }
>       cb->args[1] = 0;
>       cb->args[3] = 0;
> -     cb->args[4] = 0;
>  release:
>       release_sock(sk);
>       return err;
If a prior session left cb->args[1] = N > 0 and every sctp_sock_dump()
call in the next session hits the early peel-off exit:
        if (ep != tsp->asoc->ep)
                goto release;
then N is never cleared, and a later invocation on an unrelated
endpoint applies "if (idx < cb->args[1]) goto next;" to its ep->asocs,
silently skipping the first N associations.
The trigger requires a previously interrupted dump plus a peel-off race
across every traversed transport in the subsequent session, so the
practical impact is narrow, but should the end-of-traversal path in
sctp_diag_dump() still guarantee cb->args[1] is reset when no
interruption occurred?
[...]

In this case, both cb->args[1] and cb->args[3] need to be cleared.

Please drop this patch, and I will prepare a new patch for net.git.

Thanks.

^ permalink raw reply

* Re: [PATCH bpf-next v3 01/15] bpf: Remove __rcu tagging in st_link->map
From: Emil Tsalapatis @ 2026-07-13 19:02 UTC (permalink / raw)
  To: Amery Hung
  Cc: bpf, netdev, alexei.starovoitov, andrii, daniel, eddyz87, memxor,
	martin.lau, shakeel.butt, roman.gushchin, kuniyu, kerneljasonxing,
	kernel-team
In-Reply-To: <20260706171918.317102-2-ameryhung@gmail.com>

On Mon, Jul 6, 2026 at 2:59 PM Amery Hung <ameryhung@gmail.com> wrote:
>
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> st_link->map is always written under update_mutex. The paths that read
> st_link->map with rcu_read_lock() are not in the fast path, so they can
> simply take update_mutex instead. Remove the __rcu annotation and replace
> all RCU accessors with direct pointer reads under update_mutex. Use
> READ_ONCE() in bpf_struct_ops_map_link_poll() which reads the pointer
> without holding update_mutex.
>
> It is a simplification change.
>
> Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> Signed-off-by: Amery Hung <ameryhung@gmail.com>
> ---


Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

>
>  kernel/bpf/bpf_struct_ops.c | 29 ++++++++++++++---------------
>  1 file changed, 14 insertions(+), 15 deletions(-)
>
> diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
> index 51b16e5f5534..d06b3d9bcc13 100644
> --- a/kernel/bpf/bpf_struct_ops.c
> +++ b/kernel/bpf/bpf_struct_ops.c
> @@ -57,7 +57,7 @@ struct bpf_struct_ops_map {
>
>  struct bpf_struct_ops_link {
>         struct bpf_link link;
> -       struct bpf_map __rcu *map;
> +       struct bpf_map *map;
>         wait_queue_head_t wait_hup;
>  };
>
> @@ -1257,8 +1257,7 @@ static void bpf_struct_ops_map_link_dealloc(struct bpf_link *link)
>         struct bpf_struct_ops_map *st_map;
>
>         st_link = container_of(link, struct bpf_struct_ops_link, link);
> -       st_map = (struct bpf_struct_ops_map *)
> -               rcu_dereference_protected(st_link->map, true);
> +       st_map = (struct bpf_struct_ops_map *)st_link->map;
>         if (st_map) {
>                 st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, link);
>                 bpf_map_put(&st_map->map);
> @@ -1273,11 +1272,11 @@ static void bpf_struct_ops_map_link_show_fdinfo(const struct bpf_link *link,
>         struct bpf_map *map;
>
>         st_link = container_of(link, struct bpf_struct_ops_link, link);
> -       rcu_read_lock();
> -       map = rcu_dereference(st_link->map);
> +       mutex_lock(&update_mutex);
> +       map = st_link->map;
>         if (map)
>                 seq_printf(seq, "map_id:\t%d\n", map->id);
> -       rcu_read_unlock();
> +       mutex_unlock(&update_mutex);
>  }
>
>  static int bpf_struct_ops_map_link_fill_link_info(const struct bpf_link *link,
> @@ -1287,11 +1286,11 @@ static int bpf_struct_ops_map_link_fill_link_info(const struct bpf_link *link,
>         struct bpf_map *map;
>
>         st_link = container_of(link, struct bpf_struct_ops_link, link);
> -       rcu_read_lock();
> -       map = rcu_dereference(st_link->map);
> +       mutex_lock(&update_mutex);
> +       map = st_link->map;
>         if (map)
>                 info->struct_ops.map_id = map->id;
> -       rcu_read_unlock();
> +       mutex_unlock(&update_mutex);
>         return 0;
>  }
>
> @@ -1314,7 +1313,7 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
>
>         mutex_lock(&update_mutex);
>
> -       old_map = rcu_dereference_protected(st_link->map, lockdep_is_held(&update_mutex));
> +       old_map = st_link->map;
>         if (!old_map) {
>                 err = -ENOLINK;
>                 goto err_out;
> @@ -1336,7 +1335,7 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
>                 goto err_out;
>
>         bpf_map_inc(new_map);
> -       rcu_assign_pointer(st_link->map, new_map);
> +       WRITE_ONCE(st_link->map, new_map);
>         bpf_map_put(old_map);
>
>  err_out:
> @@ -1353,7 +1352,7 @@ static int bpf_struct_ops_map_link_detach(struct bpf_link *link)
>
>         mutex_lock(&update_mutex);
>
> -       map = rcu_dereference_protected(st_link->map, lockdep_is_held(&update_mutex));
> +       map = st_link->map;
>         if (!map) {
>                 mutex_unlock(&update_mutex);
>                 return 0;
> @@ -1362,7 +1361,7 @@ static int bpf_struct_ops_map_link_detach(struct bpf_link *link)
>
>         st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, link);
>
> -       RCU_INIT_POINTER(st_link->map, NULL);
> +       WRITE_ONCE(st_link->map, NULL);
>         /* Pair with bpf_map_get() in bpf_struct_ops_link_create() or
>          * bpf_map_inc() in bpf_struct_ops_map_link_update().
>          */
> @@ -1382,7 +1381,7 @@ static __poll_t bpf_struct_ops_map_link_poll(struct file *file,
>
>         poll_wait(file, &st_link->wait_hup, pts);
>
> -       return rcu_access_pointer(st_link->map) ? 0 : EPOLLHUP;
> +       return READ_ONCE(st_link->map) ? 0 : EPOLLHUP;
>  }
>
>  static const struct bpf_link_ops bpf_struct_ops_map_lops = {
> @@ -1438,7 +1437,7 @@ int bpf_struct_ops_link_create(union bpf_attr *attr)
>                 link = NULL;
>                 goto err_out;
>         }
> -       RCU_INIT_POINTER(link->map, map);
> +       link->map = map;
>         mutex_unlock(&update_mutex);
>
>         return bpf_link_settle(&link_primer);
> --
> 2.52.0
>
>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox