Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv6: Protect fib6_link_table() with spinlock.

We will get rid of RTNL from RTM_NEWROUTE and SIOCADDRT.

If the request specifies a new table ID, fib6_new_table() is
called to create a new routing table.

Two concurrent requests could specify the same table ID, so we
need a lock to protect net->ipv6.fib_table_hash[h].

Let's add a spinlock to protect the hash bucket linkage.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/20250418000443.43734-13-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Kuniyuki Iwashima and committed by
Paolo Abeni
834d9784 71c0efb6

+22 -5
+1
include/net/netns/ipv6.h
··· 72 72 struct rt6_statistics *rt6_stats; 73 73 struct timer_list ip6_fib_timer; 74 74 struct hlist_head *fib_table_hash; 75 + spinlock_t fib_table_hash_lock; 75 76 struct fib6_table *fib6_main_tbl; 76 77 struct list_head fib6_walkers; 77 78 rwlock_t fib6_walker_lock;
+21 -5
net/ipv6/ip6_fib.c
··· 249 249 250 250 struct fib6_table *fib6_new_table(struct net *net, u32 id) 251 251 { 252 - struct fib6_table *tb; 252 + struct fib6_table *tb, *new_tb; 253 253 254 254 if (id == 0) 255 255 id = RT6_TABLE_MAIN; 256 + 256 257 tb = fib6_get_table(net, id); 257 258 if (tb) 258 259 return tb; 259 260 260 - tb = fib6_alloc_table(net, id); 261 - if (tb) 262 - fib6_link_table(net, tb); 261 + new_tb = fib6_alloc_table(net, id); 262 + if (!new_tb) 263 + return NULL; 263 264 264 - return tb; 265 + spin_lock_bh(&net->ipv6.fib_table_hash_lock); 266 + 267 + tb = fib6_get_table(net, id); 268 + if (unlikely(tb)) { 269 + spin_unlock_bh(&net->ipv6.fib_table_hash_lock); 270 + kfree(new_tb); 271 + return tb; 272 + } 273 + 274 + fib6_link_table(net, new_tb); 275 + 276 + spin_unlock_bh(&net->ipv6.fib_table_hash_lock); 277 + 278 + return new_tb; 265 279 } 266 280 EXPORT_SYMBOL_GPL(fib6_new_table); 267 281 ··· 2436 2422 net->ipv6.fib_table_hash = kzalloc(size, GFP_KERNEL); 2437 2423 if (!net->ipv6.fib_table_hash) 2438 2424 goto out_rt6_stats; 2425 + 2426 + spin_lock_init(&net->ipv6.fib_table_hash_lock); 2439 2427 2440 2428 net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl), 2441 2429 GFP_KERNEL);