Skip to content

Commit c46286f

Browse files
Paolo Abenikuba-moo
Paolo Abeni
authored andcommitted
mr: consolidate the ipmr_can_free_table() checks.
Guoyu Yin reported a splat in the ipmr netns cleanup path: WARNING: CPU: 2 PID: 14564 at net/ipv4/ipmr.c:440 ipmr_free_table net/ipv4/ipmr.c:440 [inline] WARNING: CPU: 2 PID: 14564 at net/ipv4/ipmr.c:440 ipmr_rules_exit+0x135/0x1c0 net/ipv4/ipmr.c:361 Modules linked in: CPU: 2 UID: 0 PID: 14564 Comm: syz.4.838 Not tainted 6.14.0 kernel-patches#1 Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:ipmr_free_table net/ipv4/ipmr.c:440 [inline] RIP: 0010:ipmr_rules_exit+0x135/0x1c0 net/ipv4/ipmr.c:361 Code: ff df 48 c1 ea 03 80 3c 02 00 75 7d 48 c7 83 60 05 00 00 00 00 00 00 5b 5d 41 5c 41 5d 41 5e e9 71 67 7f 00 e8 4c 2d 8a fd 90 <0f> 0b 90 eb 93 e8 41 2d 8a fd 0f b6 2d 80 54 ea 01 31 ff 89 ee e8 RSP: 0018:ffff888109547c58 EFLAGS: 00010293 RAX: 0000000000000000 RBX: ffff888108c12dc0 RCX: ffffffff83e09868 RDX: ffff8881022b3300 RSI: ffffffff83e098d4 RDI: 0000000000000005 RBP: ffff888104288000 R08: 0000000000000000 R09: ffffed10211825c9 R10: 0000000000000001 R11: ffff88801816c4a0 R12: 0000000000000001 R13: ffff888108c13320 R14: ffff888108c12dc0 R15: fffffbfff0b74058 FS: 00007f84f39316c0(0000) GS:ffff88811b100000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f84f3930f98 CR3: 0000000113b56000 CR4: 0000000000350ef0 Call Trace: <TASK> ipmr_net_exit_batch+0x50/0x90 net/ipv4/ipmr.c:3160 ops_exit_list+0x10c/0x160 net/core/net_namespace.c:177 setup_net+0x47d/0x8e0 net/core/net_namespace.c:394 copy_net_ns+0x25d/0x410 net/core/net_namespace.c:516 create_new_namespaces+0x3f6/0xaf0 kernel/nsproxy.c:110 unshare_nsproxy_namespaces+0xc3/0x180 kernel/nsproxy.c:228 ksys_unshare+0x78d/0x9a0 kernel/fork.c:3342 __do_sys_unshare kernel/fork.c:3413 [inline] __se_sys_unshare kernel/fork.c:3411 [inline] __x64_sys_unshare+0x31/0x40 kernel/fork.c:3411 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xa6/0x1a0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f84f532cc29 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f84f3931038 EFLAGS: 00000246 ORIG_RAX: 0000000000000110 RAX: ffffffffffffffda RBX: 00007f84f5615fa0 RCX: 00007f84f532cc29 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000040000400 RBP: 00007f84f53fba18 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f84f5615fa0 R15: 00007fff51c5f328 </TASK> The running kernel has CONFIG_IP_MROUTE_MULTIPLE_TABLES disabled, and the sanity check for such build is still too loose. Address the issue consolidating the relevant sanity check in a single helper regardless of the kernel configuration. Also share it between the ipv4 and ipv6 code. Reported-by: Guoyu Yin <[email protected]> Fixes: 50b9420 ("ipmr: tune the ipmr_can_free_table() checks.") Signed-off-by: Paolo Abeni <[email protected]> Link: https://patch.msgid.link/372dc261e1bf12742276e1b984fc5a071b7fc5a8.1747321903.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d6d2b0e commit c46286f

File tree

3 files changed

+7
-22
lines changed

3 files changed

+7
-22
lines changed

include/linux/mroute_base.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ struct mr_table {
262262
int mroute_reg_vif_num;
263263
};
264264

265+
static inline bool mr_can_free_table(struct net *net)
266+
{
267+
return !check_net(net) || !net_initialized(net);
268+
}
269+
265270
#ifdef CONFIG_IP_MROUTE_COMMON
266271
void vif_device_init(struct vif_device *v,
267272
struct net_device *dev,

net/ipv4/ipmr.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ static void ipmr_expire_process(struct timer_list *t);
120120
lockdep_rtnl_is_held() || \
121121
list_empty(&net->ipv4.mr_tables))
122122

123-
static bool ipmr_can_free_table(struct net *net)
124-
{
125-
return !check_net(net) || !net_initialized(net);
126-
}
127-
128123
static struct mr_table *ipmr_mr_table_iter(struct net *net,
129124
struct mr_table *mrt)
130125
{
@@ -317,11 +312,6 @@ EXPORT_SYMBOL(ipmr_rule_default);
317312
#define ipmr_for_each_table(mrt, net) \
318313
for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
319314

320-
static bool ipmr_can_free_table(struct net *net)
321-
{
322-
return !check_net(net);
323-
}
324-
325315
static struct mr_table *ipmr_mr_table_iter(struct net *net,
326316
struct mr_table *mrt)
327317
{
@@ -437,7 +427,7 @@ static void ipmr_free_table(struct mr_table *mrt)
437427
{
438428
struct net *net = read_pnet(&mrt->net);
439429

440-
WARN_ON_ONCE(!ipmr_can_free_table(net));
430+
WARN_ON_ONCE(!mr_can_free_table(net));
441431

442432
timer_shutdown_sync(&mrt->ipmr_expire_timer);
443433
mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |

net/ipv6/ip6mr.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,6 @@ static void ipmr_expire_process(struct timer_list *t);
108108
lockdep_rtnl_is_held() || \
109109
list_empty(&net->ipv6.mr6_tables))
110110

111-
static bool ip6mr_can_free_table(struct net *net)
112-
{
113-
return !check_net(net) || !net_initialized(net);
114-
}
115-
116111
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
117112
struct mr_table *mrt)
118113
{
@@ -306,11 +301,6 @@ EXPORT_SYMBOL(ip6mr_rule_default);
306301
#define ip6mr_for_each_table(mrt, net) \
307302
for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
308303

309-
static bool ip6mr_can_free_table(struct net *net)
310-
{
311-
return !check_net(net);
312-
}
313-
314304
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
315305
struct mr_table *mrt)
316306
{
@@ -416,7 +406,7 @@ static void ip6mr_free_table(struct mr_table *mrt)
416406
{
417407
struct net *net = read_pnet(&mrt->net);
418408

419-
WARN_ON_ONCE(!ip6mr_can_free_table(net));
409+
WARN_ON_ONCE(!mr_can_free_table(net));
420410

421411
timer_shutdown_sync(&mrt->ipmr_expire_timer);
422412
mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |

0 commit comments

Comments
 (0)