Netdev List
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: kuniyu@google.com
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, dsahern@kernel.org,
	idosch@nvidia.com, horms@kernel.org, kuni1840@gmail.com,
	netdev@vger.kernel.org, razor@blackwall.org
Subject: Re: [PATCH v6 net-next 06/15] neighbour: Store arp_tbl and nd_tbl in net->neigh_tables[].
Date: Fri, 04 Sep 2026 03:09:56 +0000	[thread overview]
Message-ID: <178849139693.4131868.6063380912219450302@kernel.org> (raw)
In-Reply-To: <20260902203722.926528-7-kuniyu@google.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 0 (1) · Medium: 0 · Low: 1

- [Low] Commit message rationale for the new `#ifdef CONFIG_PROC_FS`
  guard in arp_net_init() is factually wrong.

Pre-existing issues:
- [High] Concern (verified RESOLVED later in this series): at this
  commit, ndisc_init() (net/ipv6/ndisc.c:2015-2041) calls…

--

neighbour: Store arp_tbl and nd_tbl in net->neigh_tables[].

This adds a per-netns neigh_tables[] array to struct net along with
neigh_table_register()/neigh_table_unregister() helpers, and stores
&arp_tbl and &nd_tbl there from arp_net_init() and ndisc_net_init() as
preparation for making neigh_table per-netns.  New arp_table(net) and
nd_table(net) accessors are added.

The commit message says:

    proc_create_net() is guarded with CONFIG_PROC_FS because it
    returns NULL when =n and setup_net() fails and panic()s.

[Severity: Low]
Is the panic() part of this description accurate?

arp_net_ops is registered from arp_init():

net/ipv4/arp.c:arp_init() {
	neigh_table_init(NEIGH_ARP_TABLE, &arp_tbl);

	dev_add_pack(&arp_packet_type);
	register_pernet_subsys(&arp_net_ops);
	...
}

arp_init() runs from inet_init() (fs_initcall), while the only setup_net()
call that panics is setup_net(&init_net) in net_ns_init(), which is a
pure_initcall and has already completed by then.  For an ops registered
later, a failing ->init is handled in __register_pernet_operations():

	error = ops_init(ops, net); /* on failure the ops are undone and the error returned */

and arp_init() is void, so that -ENOMEM is silently discarded.

Wouldn't the actual consequence on CONFIG_PROC_FS=n be that arp_net_ops
never gets registered, so net->neigh_tables[NEIGH_ARP_TABLE] stays NULL in
every netns, which would then break arp_table(net) once the follow-up
patches convert the ARP users over?  Could the changelog describe that
instead?

> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index caa52bf64a2d..286acb7cd504 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -1899,6 +1899,18 @@ int neigh_table_clear(int index, struct neigh_table *tbl)
>  	return 0;
>  }
>  
> +int neigh_table_register(struct net *net, struct neigh_table *tbl, int index)
> +{
> +	net->neigh_tables[index] = tbl;
> +
> +	return 0;
> +}
> +
> +void neigh_table_unregister(struct net *net, int index)
> +{
> +	net->neigh_tables[index] = NULL;
> +}
> +
>  static struct neigh_table *neigh_find_table(int family)
>  {
>  	struct neigh_table *tbl = NULL;
> diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
> index d409f606aec0..bad17d5aeafc 100644
> --- a/net/ipv4/arp.c
> +++ b/net/ipv4/arp.c
> @@ -1495,15 +1495,34 @@ static const struct seq_operations arp_seq_ops = {
>  
>  static int __net_init arp_net_init(struct net *net)
>  {
> +	int err;
> +
> +	err = neigh_table_register(net, &arp_tbl, NEIGH_ARP_TABLE);
> +	if (err)
> +		goto err;
> +
> +#ifdef CONFIG_PROC_FS
>  	if (!proc_create_net("arp", 0444, net->proc_net, &arp_seq_ops,
> -			sizeof(struct neigh_seq_state)))
> -		return -ENOMEM;
> +			     sizeof(struct neigh_seq_state))) {
> +		err = -ENOMEM;
> +		goto err_proc_create;
> +	}
> +#endif
> +
>  	return 0;
> +
> +#ifdef CONFIG_PROC_FS
> +err_proc_create:
> +	neigh_table_unregister(net, NEIGH_ARP_TABLE);
> +#endif
> +err:
> +	return err;
>  }

[ ... ]

> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 75515fd99383..dc4c083fe27a 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -1974,12 +1974,16 @@ static int __net_init ndisc_net_init(struct net *net)
>  	struct sock *sk;
>  	int err;
>  
> +	err = neigh_table_register(net, &nd_tbl, NEIGH_ND_TABLE);
> +	if (err)
> +		goto err;
> +
>  	err = inet_ctl_sock_create(&sk, PF_INET6,
>  				   SOCK_RAW, IPPROTO_ICMPV6, net);
>  	if (err < 0) {
>  		net_err_ratelimited("NDISC: Failed to initialize the control socket (err %d)\n",
>  				    err);
> -		return err;
> +		goto err_sock_create;
>  	}

[Severity: High]
This isn't a bug introduced by this patch, but while unwinding is being
added here, does the neighbour table in ndisc_init() still leak on the
sysctl failure path?

net/ipv6/ndisc.c:ndisc_init() {
	neigh_table_init(NEIGH_ND_TABLE, &nd_tbl);

#ifdef CONFIG_SYSCTL
	err = neigh_sysctl_register(NULL, &nd_tbl.parms,
				    ndisc_ifinfo_sysctl_change);
	if (err)
		goto out_unregister_pernet;
out:
#endif
	return err;

#ifdef CONFIG_SYSCTL
out_unregister_pernet:
	unregister_pernet_subsys(&ndisc_net_ops);
	goto out;
#endif
}

If neigh_sysctl_register() returns -ENOBUFS (kmemdup or
register_net_sysctl_sz() failure), only the pernet ops are unregistered and
neigh_table_clear(NEIGH_ND_TABLE, &nd_tbl) is never called, so nd_tbl->stats,
nd_tbl->nht, nd_tbl->phash_buckets and the /proc/net/stat/ndisc_cache entry
stay around.

neigh_table_init() also leaves work queued and the proxy timer armed on the
abandoned table:

net/core/neighbour.c:neigh_table_init() {
	INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
	queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
			tbl->parms.reachable_time);
	INIT_DEFERRABLE_WORK(&tbl->managed_work, neigh_managed_work);
	queue_delayed_work(system_power_efficient_wq, &tbl->managed_work, 0);
	...
}

inet6_init() jumps to ndisc_fail on ndisc_init() failure and never calls
ndisc_cleanup(), so nothing balances the initialised table.

This does get resolved later in the same series: after "neighbour:
Namespacify neigh_tables." ndisc_init() becomes just
register_pernet_subsys(&ndisc_net_ops), and both neigh_table_register() and
neigh_sysctl_register() move into ndisc_net_init() with full unwinding
through neigh_sysctl_unregister() and neigh_table_unregister().  Noting it
here only for completeness.

>  	net->ipv6.ndisc_sk = sk;
> @@ -1990,11 +1994,17 @@ static int __net_init ndisc_net_init(struct net *net)
>  	inet6_clear_bit(MC6_LOOP, sk);
>  
>  	return 0;
> +
> +err_sock_create:
> +	neigh_table_unregister(net, NEIGH_ND_TABLE);
> +err:
> +	return err;
>  }

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260902203722.926528-1-kuniyu%40google.com

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

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 20:36 [PATCH v6 net-next 00/15] neighbour: Namespacify arp_tbl and nd_tbl Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 01/15] selftest: net: Deflake Periodic GC test in test_neigh.sh Kuniyuki Iwashima
2026-09-04  3:09   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 02/15] neighbour: Remove __neigh_for_each_release() Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 03/15] neighbour: Remove lock dance for neigh_update_{gc,managed}_list() Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 04/15] neighbour: Remove unnecessary EXPORT_SYMBOL() Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 05/15] neighbour: Remove __rcu from neigh_tables[] Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 06/15] neighbour: Store arp_tbl and nd_tbl in net->neigh_tables[] Kuniyuki Iwashima
2026-09-04  3:09   ` netdev-bot+sashiko [this message]
2026-09-02 20:36 ` [PATCH v6 net-next 07/15] neighbour: Remove neigh_tables[] Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 08/15] ipv4: Replace &arp_tbl with arp_table(net) Kuniyuki Iwashima
2026-09-04  3:09   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 09/15] ipv6: Replace &nd_tbl with nd_table(net) Kuniyuki Iwashima
2026-09-04  3:09   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 10/15] neighbour: Clean up neigh_table_init() and neigh_table_clear() Kuniyuki Iwashima
2026-09-04  3:10   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 11/15] neighbour: Convert neigh_table.entries to refcount_t Kuniyuki Iwashima
2026-09-04  3:10   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 12/15] neighbour: Namespacify neigh_tables Kuniyuki Iwashima
2026-09-04  3:10   ` netdev-bot+sashiko
2026-09-02 20:36 ` [PATCH v6 net-next 13/15] neighbour: Don't store net in struct pneigh_entry Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 14/15] neighbour: Remove unnecessary net_eq() Kuniyuki Iwashima
2026-09-02 20:36 ` [PATCH v6 net-next 15/15] selftest: net: Specify netns for ip ntable in test_neigh.sh Kuniyuki Iwashima
2026-09-04  3:10   ` netdev-bot+sashiko
2026-09-03 12:46 ` [PATCH v6 net-next 00/15] neighbour: Namespacify arp_tbl and nd_tbl Ido Schimmel

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=178849139693.4131868.6063380912219450302@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=kuni1840@gmail.com \
    --cc=kuniyu@google.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=razor@blackwall.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