From 6b3e73774815910a39d8ca75b9ad7df963f61d50 Mon Sep 17 00:00:00 2001 From: Zixuan Chai Date: Sat, 10 Oct 2026 14:25:31 +0800 Subject: [PATCH] devlink: fix reload error on netns teardown During network namespace teardown, devlink_pernet_pre_exit() reloads devlink instances into init_net. If reload_down() fails, devlink_reload() returns before changing the namespace, leaving the registered devlink with a pointer to the namespace being destroyed. Move the fallback transition to devlink_pernet_pre_exit(), where the teardown context is explicit. Do it only when the devlink still belongs to the exiting namespace, since reload_up() can fail after the regular reload path has already moved the instance. Keep the original reload error. Cc: stable+noautosel@kernel.org # unlikely driver error paths Fixes: 070c63f20f6c ("net: devlink: allow to change namespaces during reload") Reported-by: Vega Closes: https://bugtracker.nebusec.ai/f/11365 Signed-off-by: Zixuan Chai Signed-off-by: Ren Wei Link: https://patch.msgid.link/c43794aa549424b79a0da624e73bbb5215c0e9f5.1791555658.git.petalzu987@gmail.com Signed-off-by: Jakub Kicinski --- net/devlink/core.c | 2 ++ net/devlink/dev.c | 6 +++--- net/devlink/devl_internal.h | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/net/devlink/core.c b/net/devlink/core.c index bddbbbf000fe..9b844e0c1bd2 100644 --- a/net/devlink/core.c +++ b/net/devlink/core.c @@ -585,6 +585,8 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net) DEVLINK_RELOAD_ACTION_DRIVER_REINIT, DEVLINK_RELOAD_LIMIT_UNSPEC, &actions_performed, NULL); + if (err && net_eq(devlink_net(devlink), net)) + devlink_reload_netns_change(devlink, net, &init_net); devl_dev_unlock(devlink, true); devlink_put(devlink); if (err && err != -EOPNOTSUPP) diff --git a/net/devlink/dev.c b/net/devlink/dev.c index b85bb02a9e80..b7e5aebf13be 100644 --- a/net/devlink/dev.c +++ b/net/devlink/dev.c @@ -412,9 +412,9 @@ static struct net *devlink_netns_get(struct sk_buff *skb, return net; } -static void devlink_reload_netns_change(struct devlink *devlink, - struct net *curr_net, - struct net *dest_net) +void devlink_reload_netns_change(struct devlink *devlink, + struct net *curr_net, + struct net *dest_net) { /* Userspace needs to be notified about devlink objects * removed from original and entering new network namespace. diff --git a/net/devlink/devl_internal.h b/net/devlink/devl_internal.h index cdf894ba5a9d..798e707002b9 100644 --- a/net/devlink/devl_internal.h +++ b/net/devlink/devl_internal.h @@ -324,6 +324,9 @@ struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, /* Reload */ bool devlink_reload_actions_valid(const struct devlink_ops *ops); +void devlink_reload_netns_change(struct devlink *devlink, + struct net *curr_net, + struct net *dest_net); int devlink_reload(struct devlink *devlink, struct net *dest_net, enum devlink_reload_action action, enum devlink_reload_limit limit,