Skip to content

Commit 3a5ca85

Browse files
martinwillimarckleinebudde
authored andcommitted
can: dev: Move device back to init netns on owning netns delete
When a non-initial netns is destroyed, the usual policy is to delete all virtual network interfaces contained, but move physical interfaces back to the initial netns. This keeps the physical interface visible on the system. CAN devices are somewhat special, as they define rtnl_link_ops even if they are physical devices. If a CAN interface is moved into a non-initial netns, destroying that netns lets the interface vanish instead of moving it back to the initial netns. default_device_exit() skips CAN interfaces due to having rtnl_link_ops set. Reproducer: ip netns add foo ip link set can0 netns foo ip netns delete foo WARNING: CPU: 1 PID: 84 at net/core/dev.c:11030 ops_exit_list+0x38/0x60 CPU: 1 PID: 84 Comm: kworker/u4:2 Not tainted 5.10.19 rib#1 Workqueue: netns cleanup_net [<c010e700>] (unwind_backtrace) from [<c010a1d8>] (show_stack+0x10/0x14) [<c010a1d8>] (show_stack) from [<c086dc10>] (dump_stack+0x94/0xa8) [<c086dc10>] (dump_stack) from [<c086b938>] (__warn+0xb8/0x114) [<c086b938>] (__warn) from [<c086ba10>] (warn_slowpath_fmt+0x7c/0xac) [<c086ba10>] (warn_slowpath_fmt) from [<c0629f20>] (ops_exit_list+0x38/0x60) [<c0629f20>] (ops_exit_list) from [<c062a5c4>] (cleanup_net+0x230/0x380) [<c062a5c4>] (cleanup_net) from [<c0142c20>] (process_one_work+0x1d8/0x438) [<c0142c20>] (process_one_work) from [<c0142ee4>] (worker_thread+0x64/0x5a8) [<c0142ee4>] (worker_thread) from [<c0148a98>] (kthread+0x148/0x14c) [<c0148a98>] (kthread) from [<c0100148>] (ret_from_fork+0x14/0x2c) To properly restore physical CAN devices to the initial netns on owning netns exit, introduce a flag on rtnl_link_ops that can be set by drivers. For CAN devices setting this flag, default_device_exit() considers them non-virtual, applying the usual namespace move. The issue was introduced in the commit mentioned below, as at that time CAN devices did not have a dellink() operation. Fixes: e008b5f ("net: Simplfy default_device_exit and improve batching.") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin Willi <[email protected]> Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 13832ae commit 3a5ca85

File tree

3 files changed

+4
-1
lines changed

3 files changed

+4
-1
lines changed

drivers/net/can/dev/netlink.c

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ static void can_dellink(struct net_device *dev, struct list_head *head)
355355

356356
struct rtnl_link_ops can_link_ops __read_mostly = {
357357
.kind = "can",
358+
.netns_refund = true,
358359
.maxtype = IFLA_CAN_MAX,
359360
.policy = can_policy,
360361
.setup = can_setup,

include/net/rtnetlink.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
3333
*
3434
* @list: Used internally
3535
* @kind: Identifier
36+
* @netns_refund: Physical device, move to init_net on netns exit
3637
* @maxtype: Highest device specific netlink attribute number
3738
* @policy: Netlink policy for device specific attribute validation
3839
* @validate: Optional validation function for netlink/changelink parameters
@@ -64,6 +65,7 @@ struct rtnl_link_ops {
6465
size_t priv_size;
6566
void (*setup)(struct net_device *dev);
6667

68+
bool netns_refund;
6769
unsigned int maxtype;
6870
const struct nla_policy *policy;
6971
int (*validate)(struct nlattr *tb[],

net/core/dev.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -11346,7 +11346,7 @@ static void __net_exit default_device_exit(struct net *net)
1134611346
continue;
1134711347

1134811348
/* Leave virtual devices for the generic cleanup */
11349-
if (dev->rtnl_link_ops)
11349+
if (dev->rtnl_link_ops && !dev->rtnl_link_ops->netns_refund)
1135011350
continue;
1135111351

1135211352
/* Push remaining network devices to init_net */

0 commit comments

Comments
 (0)