Netdev List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: pablo@netfilter.org
Cc: Jakub Kicinski <kuba@kernel.org>,
	netfilter-devel@vger.kernel.org, davem@davemloft.net,
	netdev@vger.kernel.org, pabeni@redhat.com, edumazet@google.com,
	horms@kernel.org, fw@strlen.de, ja@ssi.bg
Subject: Re: [PATCH net 02/10] netfilter: nfnetlink_queue: hold nfnl mutex in event notifier
Date: Thu, 17 Sep 2026 19:04:08 -0700	[thread overview]
Message-ID: <20260918020409.3513342-1-kuba@kernel.org> (raw)
In-Reply-To: <20260916231652.127456-3-pablo@netfilter.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
netfilter: nfnetlink_queue: hold nfnl mutex in event notifier

This takes the NFNL_SUBSYS_QUEUE mutex around the instance destroy loop in
nfqnl_rcv_nl_event() so that the NETLINK_URELEASE notifier can no longer run
in parallel with nfqnl_recv_config().  The stale comment in nfqnl_recv_config()
is updated to describe the new serialization.

> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
> index c727668b0c5be..a3bc002800510 100644
> --- a/net/netfilter/nfnetlink_queue.c
> +++ b/net/netfilter/nfnetlink_queue.c
> @@ -1593,6 +1593,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
>  	if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
>  		int i;
>  
> +		nfnl_lock(NFNL_SUBSYS_QUEUE);
>  		/* destroy all instances for this portid */
>  		spin_lock(&q->instances_lock);
>  		for (i = 0; i < INSTANCE_BUCKETS; i++) {

[Severity: Medium]
This is a pre-existing issue, not something introduced here, but does waiting
on the nfnl queue mutex here make it easier to destroy an instance that belongs
to a different socket?

The destroy loop in nfqnl_rcv_nl_event() picks victims by portid only:

	hlist_for_each_entry_safe(inst, t2, head, hlist) {
		if (n->portid == inst->peer_portid)
			__instance_destroy(inst);
	}

and net/netlink/af_netlink.c:netlink_release() makes the portid reusable well
before the notifier runs:

netlink_release()
	netlink_remove(sk);		/* portid is free for reuse here */
	sock_orphan(sk);
	...
	blocking_notifier_call_chain(&netlink_chain,
				     NETLINK_URELEASE, &n);

With the new nfnl_lock(NFNL_SUBSYS_QUEUE), the notifier now blocks for the
whole duration of any NFQNL_MSG_CONFIG handling (including instance_create()
and its sleeping rhashtable_init()), in any netns, since
net/netfilter/nfnetlink.c:nfnl_lock() takes the single global
table[NFNL_SUBSYS_QUEUE].mutex.  So this sequence looks possible:

thread 1: close() of a NETLINK_NETFILTER socket with portid X
	  netlink_remove() releases X, notifier is pending

thread 2: binds portid X, sends NFQNL_CFG_CMD_BIND
	  nfnetlink_rcv_msg() -> nfqnl_recv_config() under the queue mutex
	  instance_create() links a fresh instance with peer_portid == X

thread 1: notifier finally acquires the mutex, matches
	  inst->peer_portid == X and calls __instance_destroy() on the
	  brand new instance

Can the ownership check that the new comment relies on detect this?

	queue = instance_lookup(q, queue_num);
	if (queue && queue->peer_portid != NETLINK_CB(skb).portid) {

peer_portid matches in the recycled-portid case, so the check passes and the
instance is still torn down by the older socket's notification.

There is no memory safety problem, the instance is unlinked once and freed via
queue_rcu_work().  The visible effect is that a live socket's queue silently
disappears, its queued packets are flushed, packets hitting the NFQUEUE rule
then fail with -ESRCH (dropped unless fail-open or bypass is set), and later
CONFIG messages for that queue number return -ENODEV.  It requires
CAP_NET_ADMIN in the netns and a concurrent close/bind, and no later commit in
this series touches net/netfilter/nfnetlink_queue.c.

>  			}
>  		}
>  		spin_unlock(&q->instances_lock);
> +		nfnl_unlock(NFNL_SUBSYS_QUEUE);
>  	}
>  	return NOTIFY_DONE;
>  }
> @@ -1925,9 +1927,9 @@ static int nfqnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info,
>  
>  	/* Lookup queue under RCU. After peer_portid check (or for new queue
>  	 * in BIND case), the queue is owned by the socket sending this message.
> -	 * A socket cannot simultaneously send a message and close, so while
> -	 * processing this CONFIG message, nfqnl_rcv_nl_event() (triggered by
> -	 * socket close) cannot destroy this queue. Safe to use without RCU.
> +	 * nfqnl_rcv_nl_event() will block on the nfnl subsys mutex that is
> +	 * held by the caller, so the queue cannot be destroyed in parallel,
> +	 * even after we drop the RCU read lock.
>  	 */

[ ... ]

  reply	other threads:[~2026-09-18  2:04 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16 23:16 [PATCH net 00/10] Netfilter/IPVS fixes for net Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 01/10] netfilter: flowtable: publish HW_DEAD after worker is done Pablo Neira Ayuso
2026-09-17  0:40   ` patchwork-bot+netdevbpf
2026-09-18  2:04   ` Jakub Kicinski
2026-09-18  8:38     ` Pablo Neira Ayuso
2026-09-18  8:56       ` my summary of LLM judgement in this PR [was Re: [PATCH net 01/10] netfilter: flowtable: publish HW_DEAD after worker is done] Pablo Neira Ayuso
2026-09-21 20:56         ` Jakub Kicinski
2026-09-16 23:16 ` [PATCH net 02/10] netfilter: nfnetlink_queue: hold nfnl mutex in event notifier Pablo Neira Ayuso
2026-09-18  2:04   ` Jakub Kicinski [this message]
2026-09-18  8:39     ` Pablo Neira Ayuso
2026-09-18  9:51     ` Florian Westphal
2026-09-16 23:16 ` [PATCH net 03/10] netfilter: ip6t_rpfilter: reject routes without inet6_dev Pablo Neira Ayuso
2026-09-18  2:04   ` Jakub Kicinski
2026-09-18  8:39     ` Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 04/10] netfilter: ip6t_rt: fix zero-address non-strict match out-of-bounds read Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 05/10] netfilter: nft_synproxy: use the family-aware checksum helper Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 06/10] ipvs: revalidate ihl before icmp_send Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 07/10] ipvs: filter some flags received in the backup server Pablo Neira Ayuso
2026-09-18  2:04   ` Jakub Kicinski
2026-09-18  8:39     ` Pablo Neira Ayuso
2026-09-18 10:23     ` Julian Anastasov
2026-09-16 23:16 ` [PATCH net 08/10] netfilter: ctnetlink: fix suspicious RCU usage in expect_iter_name Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 09/10] net: remove WARN_ON_ONCE() from the dev_fill_forward_path() loop check Pablo Neira Ayuso
2026-09-16 23:16 ` [PATCH net 10/10] netfilter: nf_tables: skip expired catchall elements on insert and delete Pablo Neira Ayuso
2026-09-18  2:04   ` Jakub Kicinski
2026-09-18  8:41     ` Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260918020409.3513342-1-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=ja@ssi.bg \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox