From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Jakub Kicinski <kuba@kernel.org>
Cc: netfilter-devel@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org, pabeni@redhat.com, edumazet@google.com,
fw@strlen.de, horms@kernel.org
Subject: Re: [PATCH net 02/10] netfilter: ebt_nflog: pin the NFLOG backend
Date: Wed, 5 Aug 2026 19:18:01 +0200 [thread overview]
Message-ID: <anNwSVI29j5-FfwJ@chamomile> (raw)
In-Reply-To: <20260805001529.3978646-1-kuba@kernel.org>
Hi Jakub,
This refers to pre-existing issue, it seems the model is now not
indicating this for some reason, see below for details.
On Tue, Aug 04, 2026 at 05:15:29PM -0700, Jakub Kicinski wrote:
> 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: ebt_nflog: pin the NFLOG backend
>
> This adds a module reference on the ULOG logger when an ebtables nflog
> rule is validated, and drops it from a new .destroy callback, so that
> nfnetlink_log cannot be unloaded while such a rule is installed. It also
> requests the nfnetlink_log module for legacy (non nft_compat) callers.
>
> A few questions about the change and the commit message.
This patch is doing exactly the same as xt_LOG and xt_NFLOG so it is
needed.
> > nf_log_unregister() runs after the per-net teardown so its final RCU
> > grace period also drains readers that obtained the logger from a per-net
> > binding.
>
> [Severity: High]
> Is this description accurate? This isn't a bug introduced by this patch,
> but the ordering seems to be the other way around.
>
> nfnetlink_log_fini() frees the per-net state first:
>
> net/netfilter/nfnetlink_log.c:nfnetlink_log_fini() {
> ...
> unregister_pernet_subsys(&nfnl_log_net_ops);
> nf_log_unregister(&nfulnl_logger);
> ...
> }
>
> unregister_pernet_subsys() reaches ops_undo_list(), where the only
> synchronize_rcu() happens before the exit callbacks run, and the kfree
> follows immediately after them:
>
> net/core/net_namespace.c:ops_undo_list() {
> ...
> list_for_each_entry_continue_reverse(ops, ops_list, list)
> ops_exit_list(ops, net_exit_list);
>
> ops = saved_ops;
> list_for_each_entry_continue_reverse(ops, ops_list, list)
> ops_free_list(ops, net_exit_list);
> ...
> }
>
> So the grace period inside nf_log_unregister() runs after struct
> nfnl_log_net has already been freed, which would mean it protects the
> module text rather than the per-net data.
>
> Does the per-net binding path stay exposed after this patch? A logger
> bound per-net (sysctl /proc/sys/net/netfilter/nf_log/<pf>, or
> nf_log_bind_pf()) is only cleared in the pernet exit hook:
>
> net/netfilter/nfnetlink_log.c:nfnl_log_net_exit() {
> nf_log_unset(net, &nfulnl_logger);
> ...
> }
>
> and nf_log_unset() does not wait for readers, since the grace period was
> removed by the commit named in the Fixes: tag:
>
> net/netfilter/nf_log.c:nf_log_unset() {
> ...
> RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL);
> ...
> }
>
> A reader that resolved the logger through the per-net branch of
> nf_log_packet():
>
> if (loginfo != NULL)
> logger = rcu_dereference(loggers[pf][loginfo->type]);
> else
> logger = rcu_dereference(net->nf.nf_loggers[pf]);
>
> can still be inside nfulnl_log_packet() -> nfnl_log_pernet(net) ->
> instance_lookup_get_rcu() -> __instance_lookup() when ops_free_list()
> frees the blob, which is the same KASAN signature quoted above with no
> ebtables rule involved. Reachable loginfo == NULL callers today include
> nf_log_trace(), the conntrack helper log in net/netfilter/nf_conntrack_helper.c
> and net/netfilter/nfnetlink_osf.c.
>
> Would reordering nfnetlink_log_fini() so that nf_log_unregister() runs
> before unregister_pernet_subsys() close all of the frontends at once?
This sounds like a pre-existing issue.
This needs a follow up which does not belong to this patch IMO.
> > diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
> > index 61bf8f4465ab7..426f8adc912c7 100644
> > --- a/net/bridge/netfilter/ebt_nflog.c
> > +++ b/net/bridge/netfilter/ebt_nflog.c
> > @@ -41,11 +41,25 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
> > static int ebt_nflog_tg_check(const struct xt_tgchk_param *par)
> > {
> > struct ebt_nflog_info *info = par->targinfo;
> > + int ret;
> >
> > if (info->flags & ~EBT_NFLOG_MASK)
> > return -EINVAL;
> > info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
> > - return 0;
> > +
> > + ret = nf_logger_find_get(par->family, NF_LOG_TYPE_ULOG);
>
> [Severity: Medium]
> Should the commit message mention that this can reject rulesets that used
> to load? ebt_nflog_tg_check() previously returned 0 unconditionally, so an
> ebtables nflog rule installed fine and simply logged nothing when
> loggers[pf][NF_LOG_TYPE_ULOG] was NULL. Now the raw -ENOENT from
> nf_logger_find_get() is propagated out through xt_check_target(), so
> ebtables -A ... --nflog and ebtables-restore fail. This seems worth
> spelling out given the Cc: stable.
>
> Also, is the stated parity with xt_NFLOG complete? NETFILTER_XT_TARGET_NFLOG
> carries select NETFILTER_NETLINK_LOG in net/netfilter/Kconfig, while
> BRIDGE_EBT_NFLOG has no select or depends:
>
> net/bridge/netfilter/Kconfig:
> config BRIDGE_EBT_NFLOG
> tristate "ebt: nflog support"
> help
> This option enables the nflog watcher, which allows to LOG
> messages through the netfilter logging API, which can use
> either the old LOG target, the old ULOG target or nfnetlink_log
> as backend.
>
> On a kernel with CONFIG_BRIDGE_EBT_NFLOG set and
> CONFIG_NETFILTER_NETLINK_LOG=n, the request_module() fallback below can
> never succeed, so the target becomes unusable. Should a
> select NETFILTER_NETLINK_LOG be added here? The help text claiming the
> watcher can use the old LOG or ULOG targets as backend also no longer
> matches the code.
This sounds again like a pre-existing issue in ebt_nflog's Kconfig.
>
> > + if (ret != 0 && !par->nft_compat) {
> > + request_module("%s", "nfnetlink_log");
> > +
> > + ret = nf_logger_find_get(par->family, NF_LOG_TYPE_ULOG);
> > + }
> > +
> > + return ret;
>
> [Severity: Medium]
> Who loads nfnetlink_log for the nft_compat case?
This is again a pre-existing issue that should be handled in a follow
up, it affects xt_LOG and xt_NFLOG too.
> The !par->nft_compat skip is copied from xt_NFLOG, but xt_NFLOG also
> declares MODULE_SOFTDEP("pre: nfnetlink_log"), and ebt_nflog.c has
> no MODULE_SOFTDEP at all, so demand-loading ebt_nflog through
> xt_request_find_target(NFPROTO_BRIDGE, "nflog", rev) does not bring
> in the backend.
>
> The -ENOENT recovery in nft_compat only matches the uppercase names:
>
> net/netfilter/nft_compat.c:nft_target_init() {
> ...
> if (ret == -ENOENT) {
> const char *modname = NULL;
>
> if (strcmp(target->name, "LOG") == 0)
> modname = "nf_log_syslog";
> else if (strcmp(target->name, "NFLOG") == 0)
> modname = "nfnetlink_log";
>
> if (modname &&
> nft_request_module(ctx->net, "%s", modname) == -EAGAIN)
> return -EAGAIN;
> }
> ...
> }
>
> The target registered here is .name = "nflog", so modname stays NULL, no
> module is requested and there is no -EAGAIN retry. Does an nftables
> bridge-family compat rule using nflog now fail with -ENOENT unless
> nfnetlink_log is already resident, where it succeeded before? Adding
> MODULE_SOFTDEP("pre: nfnetlink_log") to ebt_nflog.c, or extending the name
> mapping in nft_target_init(), would seem to cover it.
>
> > +}
> > +
> > +static void ebt_nflog_tg_destroy(const struct xt_tgdtor_param *par)
> > +{
> > + nf_logger_put(par->family, NF_LOG_TYPE_ULOG);
> > }
> >
> > static struct xt_target ebt_nflog_tg_reg __read_mostly = {
> > @@ -54,6 +68,7 @@ static struct xt_target ebt_nflog_tg_reg __read_mostly = {
> > .family = NFPROTO_BRIDGE,
> > .target = ebt_nflog_tg,
> > .checkentry = ebt_nflog_tg_check,
> > + .destroy = ebt_nflog_tg_destroy,
> > .targetsize = sizeof(struct ebt_nflog_info),
> > .me = THIS_MODULE,
> > };
next prev parent reply other threads:[~2026-08-05 17:18 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 15:17 [PATCH net 00/10] Netfilter/IPVS fixes for net Pablo Neira Ayuso
2026-07-31 15:17 ` [PATCH net 01/10] ipvs: stop estimator after disabled calc phase Pablo Neira Ayuso
2026-08-05 23:50 ` patchwork-bot+netdevbpf
2026-07-31 15:17 ` [PATCH net 02/10] netfilter: ebt_nflog: pin the NFLOG backend Pablo Neira Ayuso
2026-08-05 0:15 ` Jakub Kicinski
2026-08-05 7:11 ` Florian Westphal
2026-08-05 7:25 ` Paolo Abeni
2026-08-05 17:18 ` Pablo Neira Ayuso [this message]
2026-08-05 19:12 ` Florian Westphal
2026-07-31 15:17 ` [PATCH net 03/10] netfilter: ipset: rework cidr bookkeeping Pablo Neira Ayuso
2026-08-05 0:15 ` Jakub Kicinski
2026-08-05 7:33 ` Florian Westphal
2026-08-05 17:19 ` Pablo Neira Ayuso
2026-08-05 19:17 ` Florian Westphal
2026-07-31 15:18 ` [PATCH net 04/10] netfilter: ipset: switch ext_size to atomic64_t Pablo Neira Ayuso
2026-07-31 15:18 ` [PATCH net 05/10] netfilter: ipset: add small wrappers for hash and bucket sizes Pablo Neira Ayuso
2026-07-31 15:18 ` [PATCH net 06/10] netfilter: ipset: add and use mtype_del_cidr_all helper Pablo Neira Ayuso
2026-08-05 0:15 ` Jakub Kicinski
2026-07-31 15:18 ` [PATCH net 07/10] netfilter: ipset: switch to rcu work Pablo Neira Ayuso
2026-07-31 15:18 ` [PATCH net 08/10] ipvs: avoid out-of-bounds write in ip_vs_nat_icmp Pablo Neira Ayuso
2026-08-05 0:15 ` Jakub Kicinski
2026-08-05 4:18 ` Julian Anastasov
2026-08-05 17:20 ` Pablo Neira Ayuso
2026-07-31 15:18 ` [PATCH net 09/10] ipvs: return the csum validation for forward hook Pablo Neira Ayuso
2026-07-31 15:18 ` [PATCH net 10/10] netfilter: nft_ct: move custom expectation support to helper Pablo Neira Ayuso
2026-08-05 0:15 ` Jakub Kicinski
2026-08-05 17:38 ` Pablo Neira Ayuso
2026-08-05 7:42 ` [PATCH net 00/10] Netfilter/IPVS fixes for net Florian Westphal
2026-08-05 17:39 ` Pablo Neira Ayuso
2026-08-05 23:21 ` Jakub Kicinski
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=anNwSVI29j5-FfwJ@chamomile \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.