* [PATCH net v2] netlabel: check register_netdevice_notifier() error in netlbl_unlabel_init()
@ 2026-07-29 9:07 Minhong He
2026-08-03 23:32 ` Jakub Kicinski
0 siblings, 1 reply; 2+ messages in thread
From: Minhong He @ 2026-07-29 9:07 UTC (permalink / raw)
To: Paul Moore, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, netdev
Cc: linux-security-module, linux-kernel
netlbl_unlabel_init() installs the unlabeled connection hash table and
registers a netdevice notifier, but ignores notifier registration errors
and always returns success.
Check the error and unwind the hash table allocation on failure.
Signed-off-by: Minhong He <heminhong@kylinos.cn>
Acked-by: Paul Moore <paul@paul-moore.com>
---
v2:
- Use rcu_assign_pointer() instead of RCU_INIT_POINTER() when clearing
netlbl_unlhsh on notifier registration failure, as suggested by Paul Moore
v1: https://lore.kernel.org/all/20260728031043.76586-1-heminhong@kylinos.cn/
net/netlabel/netlabel_unlabeled.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 47bae5e48db6..fe1be424601f 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1397,6 +1397,7 @@ static struct notifier_block netlbl_unlhsh_netdev_notifier = {
*/
int __init netlbl_unlabel_init(u32 size)
{
+ int err;
u32 iter;
struct netlbl_unlhsh_tbl *hsh_tbl;
@@ -1419,7 +1420,16 @@ int __init netlbl_unlabel_init(u32 size)
rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
spin_unlock(&netlbl_unlhsh_lock);
- register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
+ err = register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
+ if (err) {
+ spin_lock(&netlbl_unlhsh_lock);
+ rcu_assign_pointer(netlbl_unlhsh, NULL);
+ spin_unlock(&netlbl_unlhsh_lock);
+ synchronize_rcu();
+ kfree(hsh_tbl->tbl);
+ kfree(hsh_tbl);
+ return err;
+ }
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net v2] netlabel: check register_netdevice_notifier() error in netlbl_unlabel_init()
2026-07-29 9:07 [PATCH net v2] netlabel: check register_netdevice_notifier() error in netlbl_unlabel_init() Minhong He
@ 2026-08-03 23:32 ` Jakub Kicinski
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2026-08-03 23:32 UTC (permalink / raw)
To: heminhong
Cc: Jakub Kicinski, paul, davem, edumazet, pabeni, horms, netdev,
linux-security-module, linux-kernel
AI says that this can never fail in practice. Please make that clear
in the commit message. Take a look at the other comment too, and if
it's incorrect explain in the commit msg why.
---
This is an AI-generated review of your patch.
netlabel: check register_netdevice_notifier() error in netlbl_unlabel_init()
This makes netlbl_unlabel_init() check the return value of
register_netdevice_notifier() instead of ignoring it, and on failure it
clears the netlbl_unlhsh global, waits for a grace period and frees the
hash table before returning the error.
No Link: tags present in the commit header.
> diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
> index 47bae5e48db6c..fe1be424601f6 100644
> --- a/net/netlabel/netlabel_unlabeled.c
> +++ b/net/netlabel/netlabel_unlabeled.c
[ ... ]
> @@ -1419,7 +1420,16 @@ int __init netlbl_unlabel_init(u32 size)
> rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
> spin_unlock(&netlbl_unlhsh_lock);
>
> - register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
> + err = register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
> + if (err) {
[Severity: Low]
[Finding: main-1-0]
[Sources: opus-5]
Can this branch ever be taken, and can its cleanup ever be observed?
register_netdevice_notifier() in net/core/dev.c only returns the result of
raw_notifier_chain_register() (-EEXIST for an already registered
notifier_block, which cannot happen for the single static
netlbl_unlhsh_netdev_notifier) or an error returned by the per-net
NETDEV_REGISTER replay. The replay calls
netlbl_unlhsh_netdev_handler(), which always ends with:
net/netlabel/netlabel_unlabeled.c:netlbl_unlhsh_netdev_handler() {
...
return NOTIFY_DONE;
}
so the replay cannot fail either.
Even if it did, the sole caller turns the new return value into a
noreturn panic():
net/netlabel/netlabel_kapi.c:netlbl_init() {
...
ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
if (ret_val != 0)
goto init_failure;
...
init_failure:
panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
}
which means clearing the global, the synchronize_rcu() wait and both
kfree() calls can never have any observable effect. The remaining
behaviour change is that a previously ignored condition now reaches
panic() during subsys_initcall, which the changelog does not mention.
Would it be simpler to keep the call unchecked here, or to document the
panic-on-failure behaviour in the changelog?
> + spin_lock(&netlbl_unlhsh_lock);
> + rcu_assign_pointer(netlbl_unlhsh, NULL);
> + spin_unlock(&netlbl_unlhsh_lock);
> + synchronize_rcu();
[Severity: Low]
[Finding: main-2-2]
[Sources: opus-5]
Is it safe to publish NULL into netlbl_unlhsh here?
Up to now netlbl_unlhsh is assigned exactly once during __init and is
never NULL, and every reader in this file dereferences it without a NULL
check:
net/netlabel/netlabel_unlabeled.c:netlbl_unlhsh_hash() {
return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1);
}
net/netlabel/netlabel_unlabeled.c:netlbl_unlhsh_search_iface() {
...
bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
...
}
net/netlabel/netlabel_unlabeled.c:netlbl_unlabel_staticlist() {
...
for (iter_bkt = skip_bkt;
iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
iter_bkt++) {
iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
...
}
netlbl_unlhsh_search_iface() is reached both from the receive path
netlbl_unlabel_getattr() and from netlbl_unlhsh_netdev_handler(), and
the synchronize_rcu() above is a blocking point executed while the
global is already NULL, so the NULL window is not instantaneous.
Nothing oopses today because netlbl_init() panics right away and the
netlabel generic netlink families are only registered later by
netlbl_netlink_init(), so no reader is expected in that window. If the
panic is ever relaxed into a graceful failure, which is the direction
this patch points at, would every unlabeled lookup and netlink dump then
become a NULL dereference? Leaving the (empty) table installed on the
failure path would avoid creating the NULL state at all.
> + kfree(hsh_tbl->tbl);
> + kfree(hsh_tbl);
> + return err;
> + }
>
> return 0;
> }
--
pw-bot: cr
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-03 23:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 9:07 [PATCH net v2] netlabel: check register_netdevice_notifier() error in netlbl_unlabel_init() Minhong He
2026-08-03 23:32 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox