Skip to content

Commit 11b78f9

Browse files
committed
Merge: [RHEL10.0 P2] IPv6: backport stable commits from upstream
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/180 JIRA: https://issues.redhat.com/browse/RHEL-74037 * 4a0ec2a ipv6: switch inet6_addr_hash() to less predictable hash * 4daf4dc ipv6: switch inet6_acaddr_hash() to less predictable hash * eb02688 ipv6: release nexthop on device removal * 52ed077 selftests: net: really check for bg process completion * d9ccb18 ipv6: Fix soft lockups in fib6_select_path under high next hop churn * f6e1dcd selftests/rtnetlink.sh: add mngtempaddr test * 11b6e70 ipmr: add debug check for mr table cleanup * f1553c9 ip6mr: fix tables suspicious RCU usage * fc9c273 ipmr: fix tables suspicious RCU usage * a747e02 ipv6: avoid possible NULL deref in modify_prefix_route() * 3301ab7 net/ipv6: release expired exception dst cached in socket * f6d7695 ipmr: fix build with clang and DEBUG_NET disabled. * 50b9420 ipmr: tune the ipmr_can_free_table() checks. Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> --- <small>Created 2025-01-15 09:09 UTC by backporter - [KWF FAQ](https://red.ht/kernel_workflow_doc) - [Slack #team-kernel-workflow](https://redhat-internal.slack.com/archives/C04LRUPMJQ5) - [Source](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/webhook/utils/backporter.py) - [Documentation](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/docs/README.backporter.md) - [Report an issue](https://gitlab.com/cki-project/kernel-workflow/-/issues/new?issue%5Btitle%5D=backporter%20webhook%20issue)</small> Approved-by: Hangbin Liu <haliu@redhat.com> Approved-by: Florian Westphal <fwestpha@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Jan Stancek <jstancek@redhat.com>
2 parents 60ae9b8 + 8ef26dd commit 11b78f9

File tree

11 files changed

+499
-59
lines changed

11 files changed

+499
-59
lines changed

include/net/net_namespace.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ static inline int check_net(const struct net *net)
322322
#define net_drop_ns NULL
323323
#endif
324324

325+
/* Returns true if the netns initialization is completed successfully */
326+
static inline bool net_initialized(const struct net *net)
327+
{
328+
return READ_ONCE(net->list.next);
329+
}
325330

326331
static inline void __netns_tracker_alloc(struct net *net,
327332
netns_tracker *tracker,

net/ipv4/ipmr.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ 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+
123128
static struct mr_table *ipmr_mr_table_iter(struct net *net,
124129
struct mr_table *mrt)
125130
{
@@ -137,7 +142,7 @@ static struct mr_table *ipmr_mr_table_iter(struct net *net,
137142
return ret;
138143
}
139144

140-
static struct mr_table *ipmr_get_table(struct net *net, u32 id)
145+
static struct mr_table *__ipmr_get_table(struct net *net, u32 id)
141146
{
142147
struct mr_table *mrt;
143148

@@ -148,6 +153,16 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
148153
return NULL;
149154
}
150155

156+
static struct mr_table *ipmr_get_table(struct net *net, u32 id)
157+
{
158+
struct mr_table *mrt;
159+
160+
rcu_read_lock();
161+
mrt = __ipmr_get_table(net, id);
162+
rcu_read_unlock();
163+
return mrt;
164+
}
165+
151166
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
152167
struct mr_table **mrt)
153168
{
@@ -189,7 +204,7 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
189204

190205
arg->table = fib_rule_get_table(rule, arg);
191206

192-
mrt = ipmr_get_table(rule->fr_net, arg->table);
207+
mrt = __ipmr_get_table(rule->fr_net, arg->table);
193208
if (!mrt)
194209
return -EAGAIN;
195210
res->mrt = mrt;
@@ -302,6 +317,11 @@ EXPORT_SYMBOL(ipmr_rule_default);
302317
#define ipmr_for_each_table(mrt, net) \
303318
for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
304319

320+
static bool ipmr_can_free_table(struct net *net)
321+
{
322+
return !check_net(net);
323+
}
324+
305325
static struct mr_table *ipmr_mr_table_iter(struct net *net,
306326
struct mr_table *mrt)
307327
{
@@ -315,6 +335,8 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
315335
return net->ipv4.mrt;
316336
}
317337

338+
#define __ipmr_get_table ipmr_get_table
339+
318340
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
319341
struct mr_table **mrt)
320342
{
@@ -403,7 +425,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
403425
if (id != RT_TABLE_DEFAULT && id >= 1000000000)
404426
return ERR_PTR(-EINVAL);
405427

406-
mrt = ipmr_get_table(net, id);
428+
mrt = __ipmr_get_table(net, id);
407429
if (mrt)
408430
return mrt;
409431

@@ -413,6 +435,10 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
413435

414436
static void ipmr_free_table(struct mr_table *mrt)
415437
{
438+
struct net *net = read_pnet(&mrt->net);
439+
440+
WARN_ON_ONCE(!ipmr_can_free_table(net));
441+
416442
timer_shutdown_sync(&mrt->ipmr_expire_timer);
417443
mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |
418444
MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC);
@@ -1374,7 +1400,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
13741400
goto out_unlock;
13751401
}
13761402

1377-
mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
1403+
mrt = __ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
13781404
if (!mrt) {
13791405
ret = -ENOENT;
13801406
goto out_unlock;
@@ -2262,11 +2288,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
22622288
struct mr_table *mrt;
22632289
int err;
22642290

2265-
mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
2266-
if (!mrt)
2291+
rcu_read_lock();
2292+
mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT);
2293+
if (!mrt) {
2294+
rcu_read_unlock();
22672295
return -ENOENT;
2296+
}
22682297

2269-
rcu_read_lock();
22702298
cache = ipmr_cache_find(mrt, saddr, daddr);
22712299
if (!cache && skb->dev) {
22722300
int vif = ipmr_find_vif(mrt, skb->dev);
@@ -2550,7 +2578,7 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
25502578
grp = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
25512579
tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0;
25522580

2553-
mrt = ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT);
2581+
mrt = __ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT);
25542582
if (!mrt) {
25552583
err = -ENOENT;
25562584
goto errout_free;
@@ -2604,7 +2632,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
26042632
if (filter.table_id) {
26052633
struct mr_table *mrt;
26062634

2607-
mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id);
2635+
mrt = __ipmr_get_table(sock_net(skb->sk), filter.table_id);
26082636
if (!mrt) {
26092637
if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR)
26102638
return skb->len;
@@ -2712,7 +2740,7 @@ static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh,
27122740
break;
27132741
}
27142742
}
2715-
mrt = ipmr_get_table(net, tblid);
2743+
mrt = __ipmr_get_table(net, tblid);
27162744
if (!mrt) {
27172745
ret = -ENOENT;
27182746
goto out;
@@ -2920,13 +2948,15 @@ static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
29202948
struct net *net = seq_file_net(seq);
29212949
struct mr_table *mrt;
29222950

2923-
mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
2924-
if (!mrt)
2951+
rcu_read_lock();
2952+
mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT);
2953+
if (!mrt) {
2954+
rcu_read_unlock();
29252955
return ERR_PTR(-ENOENT);
2956+
}
29262957

29272958
iter->mrt = mrt;
29282959

2929-
rcu_read_lock();
29302960
return mr_vif_seq_start(seq, pos);
29312961
}
29322962

net/ipv6/addrconf.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
10161016

10171017
static u32 inet6_addr_hash(const struct net *net, const struct in6_addr *addr)
10181018
{
1019-
u32 val = ipv6_addr_hash(addr) ^ net_hash_mix(net);
1019+
u32 val = __ipv6_addr_jhash(addr, net_hash_mix(net));
10201020

10211021
return hash_32(val, IN6_ADDR_HSIZE_SHIFT);
10221022
}
@@ -4821,7 +4821,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
48214821
ifm->ifa_prefixlen, extack);
48224822
}
48234823

4824-
static int modify_prefix_route(struct inet6_ifaddr *ifp,
4824+
static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
48254825
unsigned long expires, u32 flags,
48264826
bool modify_peer)
48274827
{
@@ -4845,7 +4845,9 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
48454845
ifp->prefix_len,
48464846
ifp->rt_priority, ifp->idev->dev,
48474847
expires, flags, GFP_KERNEL);
4848-
} else {
4848+
return 0;
4849+
}
4850+
if (f6i != net->ipv6.fib6_null_entry) {
48494851
table = f6i->fib6_table;
48504852
spin_lock_bh(&table->tb6_lock);
48514853

@@ -4858,9 +4860,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
48584860
}
48594861

48604862
spin_unlock_bh(&table->tb6_lock);
4861-
4862-
fib6_info_release(f6i);
48634863
}
4864+
fib6_info_release(f6i);
48644865

48654866
return 0;
48664867
}
@@ -4939,7 +4940,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
49394940
int rc = -ENOENT;
49404941

49414942
if (had_prefixroute)
4942-
rc = modify_prefix_route(ifp, expires, flags, false);
4943+
rc = modify_prefix_route(net, ifp, expires, flags, false);
49434944

49444945
/* prefix route could have been deleted; if so restore it */
49454946
if (rc == -ENOENT) {
@@ -4949,7 +4950,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
49494950
}
49504951

49514952
if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
4952-
rc = modify_prefix_route(ifp, expires, flags, true);
4953+
rc = modify_prefix_route(net, ifp, expires, flags, true);
49534954

49544955
if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
49554956
addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,

net/ipv6/anycast.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ static DEFINE_SPINLOCK(acaddr_hash_lock);
4949

5050
static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr);
5151

52-
static u32 inet6_acaddr_hash(struct net *net, const struct in6_addr *addr)
52+
static u32 inet6_acaddr_hash(const struct net *net,
53+
const struct in6_addr *addr)
5354
{
54-
u32 val = ipv6_addr_hash(addr) ^ net_hash_mix(net);
55+
u32 val = __ipv6_addr_jhash(addr, net_hash_mix(net));
5556

5657
return hash_32(val, IN6_ADDR_HSIZE_SHIFT);
5758
}

net/ipv6/ip6_fib.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,8 +1190,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
11901190
while (sibling) {
11911191
if (sibling->fib6_metric == rt->fib6_metric &&
11921192
rt6_qualify_for_ecmp(sibling)) {
1193-
list_add_tail(&rt->fib6_siblings,
1194-
&sibling->fib6_siblings);
1193+
list_add_tail_rcu(&rt->fib6_siblings,
1194+
&sibling->fib6_siblings);
11951195
break;
11961196
}
11971197
sibling = rcu_dereference_protected(sibling->fib6_next,
@@ -1252,7 +1252,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
12521252
fib6_siblings)
12531253
sibling->fib6_nsiblings--;
12541254
rt->fib6_nsiblings = 0;
1255-
list_del_init(&rt->fib6_siblings);
1255+
list_del_rcu(&rt->fib6_siblings);
12561256
rt6_multipath_rebalance(next_sibling);
12571257
return err;
12581258
}
@@ -1970,7 +1970,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
19701970
&rt->fib6_siblings, fib6_siblings)
19711971
sibling->fib6_nsiblings--;
19721972
rt->fib6_nsiblings = 0;
1973-
list_del_init(&rt->fib6_siblings);
1973+
list_del_rcu(&rt->fib6_siblings);
19741974
rt6_multipath_rebalance(next_sibling);
19751975
}
19761976

0 commit comments

Comments
 (0)