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 09/12] netfilter: nfnetlink_queue: hold nfnl mutex in event notifier
Date: Thu, 3 Sep 2026 19:01:49 -0700 [thread overview]
Message-ID: <20260904020149.3549947-1-kuba@kernel.org> (raw)
In-Reply-To: <20260903004149.1037028-10-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
The NETLINK_URELEASE notifier now takes the NFNL_SUBSYS_QUEUE mutex around
the instance teardown loop, so it can no longer run concurrently with
nfqnl_recv_config(). The comment in nfqnl_recv_config() is updated to
explain that the notifier blocks on the subsystem mutex held by the caller.
> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
> index c727668b0c5b..a3bc00280051 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]
The new mutex gives mutual exclusion, but does it give any ordering
against the socket unhash? In netlink_release() the socket is removed
from the hash table before the notifier chain is invoked:
net/netlink/af_netlink.c:netlink_release() {
...
netlink_remove(sk);
sock_orphan(sk);
...
if (nlk->portid && nlk->bound) {
struct netlink_notify n = {
...
.portid = nlk->portid,
};
blocking_notifier_call_chain(&netlink_chain,
NETLINK_URELEASE, &n);
}
}
Once netlink_remove(sk) has run, the portid is free for anyone else to
claim:
net/netlink/af_netlink.c:netlink_bind() {
...
err = nladdr->nl_pid ?
netlink_insert(sk, nladdr->nl_pid) :
netlink_autobind(sock);
}
So the sequence below looks possible:
thread A: close() -> netlink_remove(sk) unhashes portid P
thread B: bind(P) succeeds
thread B: NFQNL_MSG_CONFIG / NFQNL_CFG_CMD_BIND
-> instance_create(q, queue_num, NETLINK_CB(skb).portid)
stamps inst->peer_portid = P
thread A: blocking_notifier_call_chain(NETLINK_URELEASE) finally runs
Since the loop here keys ownership only on the numeric portid:
hlist_for_each_entry_safe(inst, t2, head, hlist) {
if (n->portid == inst->peer_portid)
__instance_destroy(inst);
}
does thread A's notifier then destroy the instance that thread B just
created? __instance_destroy() does hlist_del_rcu() plus
queue_rcu_work(), and instance_destroy_work() -> nfqnl_flush() drops all
queued packets, after which thread B's NFQNL_MSG_VERDICT calls fail with
-ENODEV from verdict_instance_lookup(), leaving the NFQUEUE rule to drop
or bypass traffic depending on the queue-bypass setting.
The portid-based ownership test itself predates this patch, but does the
new mutex widen the window rather than narrow it? Before, the notifier
only contended on q->instances_lock and could easily win the race and
find nothing to destroy. Now, if the notifier arrives at any point while
the re-binding socket is inside nfqnl_recv_config() holding the QUEUE
mutex (which sleeps in kzalloc_obj(GFP_KERNEL_ACCOUNT) and
rhashtable_init()), the notifier is parked until that CONFIG operation
completes, so it is guaranteed to run after the new instance is linked
and will match it.
Would keying ownership on the socket identity, or refcounting instances
as the commit message notes is currently missing, avoid this rather than
relying on the subsystem mutex?
> @@ -1606,6 +1607,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
> }
> }
> 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.
> */
> rcu_read_lock();
> queue = instance_lookup(q, queue_num);
This finding was flagged as requiring validation, so please double check
whether the portid reuse window described above is reachable in practice
on your side.
next prev parent reply other threads:[~2026-09-04 2:01 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 0:41 [PATCH net 00/12] Netfilter/IPVS fixes for net Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 01/12] ipvs: reject invalid states in connection template sync records Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 02/12] ipvs: fix reversed sequence option serialization Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 03/12] netfilter: nf_conntrack_sip: fix OOB read in sip_skip_whitespace() Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 04/12] netfilter: cttimeout: prevent UAF during module unload Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 05/12] netfilter: nf_log: unregister loggers before per-net teardown Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 06/12] ipvs: bound LBLCR and LBLC cache growth Pablo Neira Ayuso
2026-09-04 2:01 ` Jakub Kicinski
2026-09-04 4:20 ` Julian Anastasov
2026-09-03 0:41 ` [PATCH net 07/12] netfilter: nft_payload: restrict checksum offsets to known values Pablo Neira Ayuso
2026-09-04 2:01 ` Jakub Kicinski
2026-09-04 5:56 ` Florian Westphal
2026-09-03 0:41 ` [PATCH net 08/12] netfilter: nfnetlink_log: cope with concurrent instance destruction Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 09/12] netfilter: nfnetlink_queue: hold nfnl mutex in event notifier Pablo Neira Ayuso
2026-09-04 2:01 ` Jakub Kicinski [this message]
2026-09-04 5:56 ` Florian Westphal
2026-09-03 0:41 ` [PATCH net 10/12] netfilter: arp_tables: remove the 32bit compat interface Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 11/12] netfilter: ip6_tables: set F_PROTO when proto value is nonzero Pablo Neira Ayuso
2026-09-03 0:41 ` [PATCH net 12/12] netfilter: report NLM_F_DUMP_FILTERED when all is filtered out Pablo Neira Ayuso
2026-09-04 2:04 ` [PATCH net 00/12] Netfilter/IPVS fixes for net Jakub Kicinski
2026-09-04 5:57 ` Florian Westphal
2026-09-04 10:55 ` Pablo Neira Ayuso
2026-09-04 10:59 ` Florian Westphal
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=20260904020149.3549947-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