diff options
-rw-r--r-- | include/net/net_namespace.h | 37 | ||||
-rw-r--r-- | include/net/netns/ipv4.h | 1 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 1 | ||||
-rw-r--r-- | net/ipv4/route.c | 16 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 1 | ||||
-rw-r--r-- | net/ipv6/route.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 8 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 7 |
8 files changed, 58 insertions, 17 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 84e37b1ca9e1..1313456a0994 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -119,7 +119,6 @@ struct net { | |||
119 | struct netns_ipvs *ipvs; | 119 | struct netns_ipvs *ipvs; |
120 | #endif | 120 | #endif |
121 | struct sock *diag_nlsk; | 121 | struct sock *diag_nlsk; |
122 | atomic_t rt_genid; | ||
123 | atomic_t fnhe_genid; | 122 | atomic_t fnhe_genid; |
124 | }; | 123 | }; |
125 | 124 | ||
@@ -333,14 +332,42 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header) | |||
333 | } | 332 | } |
334 | #endif | 333 | #endif |
335 | 334 | ||
336 | static inline int rt_genid(struct net *net) | 335 | static inline int rt_genid_ipv4(struct net *net) |
337 | { | 336 | { |
338 | return atomic_read(&net->rt_genid); | 337 | return atomic_read(&net->ipv4.rt_genid); |
339 | } | 338 | } |
340 | 339 | ||
341 | static inline void rt_genid_bump(struct net *net) | 340 | static inline void rt_genid_bump_ipv4(struct net *net) |
342 | { | 341 | { |
343 | atomic_inc(&net->rt_genid); | 342 | atomic_inc(&net->ipv4.rt_genid); |
343 | } | ||
344 | |||
345 | #if IS_ENABLED(CONFIG_IPV6) | ||
346 | static inline int rt_genid_ipv6(struct net *net) | ||
347 | { | ||
348 | return atomic_read(&net->ipv6.rt_genid); | ||
349 | } | ||
350 | |||
351 | static inline void rt_genid_bump_ipv6(struct net *net) | ||
352 | { | ||
353 | atomic_inc(&net->ipv6.rt_genid); | ||
354 | } | ||
355 | #else | ||
356 | static inline int rt_genid_ipv6(struct net *net) | ||
357 | { | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static inline void rt_genid_bump_ipv6(struct net *net) | ||
362 | { | ||
363 | } | ||
364 | #endif | ||
365 | |||
366 | /* For callers who don't really care about whether it's IPv4 or IPv6 */ | ||
367 | static inline void rt_genid_bump_all(struct net *net) | ||
368 | { | ||
369 | rt_genid_bump_ipv4(net); | ||
370 | rt_genid_bump_ipv6(net); | ||
344 | } | 371 | } |
345 | 372 | ||
346 | static inline int fnhe_genid(struct net *net) | 373 | static inline int fnhe_genid(struct net *net) |
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2ba9de89e8ec..bf2ec2202c56 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h | |||
@@ -77,5 +77,6 @@ struct netns_ipv4 { | |||
77 | struct fib_rules_ops *mr_rules_ops; | 77 | struct fib_rules_ops *mr_rules_ops; |
78 | #endif | 78 | #endif |
79 | #endif | 79 | #endif |
80 | atomic_t rt_genid; | ||
80 | }; | 81 | }; |
81 | #endif | 82 | #endif |
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 005e2c2e39a9..0fb2401197c5 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -72,6 +72,7 @@ struct netns_ipv6 { | |||
72 | #endif | 72 | #endif |
73 | #endif | 73 | #endif |
74 | atomic_t dev_addr_genid; | 74 | atomic_t dev_addr_genid; |
75 | atomic_t rt_genid; | ||
75 | }; | 76 | }; |
76 | 77 | ||
77 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) | 78 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index a9a54a236832..e805481eff72 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -435,12 +435,12 @@ static inline int ip_rt_proc_init(void) | |||
435 | 435 | ||
436 | static inline bool rt_is_expired(const struct rtable *rth) | 436 | static inline bool rt_is_expired(const struct rtable *rth) |
437 | { | 437 | { |
438 | return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); | 438 | return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev)); |
439 | } | 439 | } |
440 | 440 | ||
441 | void rt_cache_flush(struct net *net) | 441 | void rt_cache_flush(struct net *net) |
442 | { | 442 | { |
443 | rt_genid_bump(net); | 443 | rt_genid_bump_ipv4(net); |
444 | } | 444 | } |
445 | 445 | ||
446 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, | 446 | static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, |
@@ -1458,7 +1458,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1458 | #endif | 1458 | #endif |
1459 | rth->dst.output = ip_rt_bug; | 1459 | rth->dst.output = ip_rt_bug; |
1460 | 1460 | ||
1461 | rth->rt_genid = rt_genid(dev_net(dev)); | 1461 | rth->rt_genid = rt_genid_ipv4(dev_net(dev)); |
1462 | rth->rt_flags = RTCF_MULTICAST; | 1462 | rth->rt_flags = RTCF_MULTICAST; |
1463 | rth->rt_type = RTN_MULTICAST; | 1463 | rth->rt_type = RTN_MULTICAST; |
1464 | rth->rt_is_input= 1; | 1464 | rth->rt_is_input= 1; |
@@ -1589,7 +1589,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1589 | goto cleanup; | 1589 | goto cleanup; |
1590 | } | 1590 | } |
1591 | 1591 | ||
1592 | rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); | 1592 | rth->rt_genid = rt_genid_ipv4(dev_net(rth->dst.dev)); |
1593 | rth->rt_flags = flags; | 1593 | rth->rt_flags = flags; |
1594 | rth->rt_type = res->type; | 1594 | rth->rt_type = res->type; |
1595 | rth->rt_is_input = 1; | 1595 | rth->rt_is_input = 1; |
@@ -1760,7 +1760,7 @@ local_input: | |||
1760 | rth->dst.tclassid = itag; | 1760 | rth->dst.tclassid = itag; |
1761 | #endif | 1761 | #endif |
1762 | 1762 | ||
1763 | rth->rt_genid = rt_genid(net); | 1763 | rth->rt_genid = rt_genid_ipv4(net); |
1764 | rth->rt_flags = flags|RTCF_LOCAL; | 1764 | rth->rt_flags = flags|RTCF_LOCAL; |
1765 | rth->rt_type = res.type; | 1765 | rth->rt_type = res.type; |
1766 | rth->rt_is_input = 1; | 1766 | rth->rt_is_input = 1; |
@@ -1945,7 +1945,7 @@ add: | |||
1945 | 1945 | ||
1946 | rth->dst.output = ip_output; | 1946 | rth->dst.output = ip_output; |
1947 | 1947 | ||
1948 | rth->rt_genid = rt_genid(dev_net(dev_out)); | 1948 | rth->rt_genid = rt_genid_ipv4(dev_net(dev_out)); |
1949 | rth->rt_flags = flags; | 1949 | rth->rt_flags = flags; |
1950 | rth->rt_type = type; | 1950 | rth->rt_type = type; |
1951 | rth->rt_is_input = 0; | 1951 | rth->rt_is_input = 0; |
@@ -2227,7 +2227,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2227 | rt->rt_iif = ort->rt_iif; | 2227 | rt->rt_iif = ort->rt_iif; |
2228 | rt->rt_pmtu = ort->rt_pmtu; | 2228 | rt->rt_pmtu = ort->rt_pmtu; |
2229 | 2229 | ||
2230 | rt->rt_genid = rt_genid(net); | 2230 | rt->rt_genid = rt_genid_ipv4(net); |
2231 | rt->rt_flags = ort->rt_flags; | 2231 | rt->rt_flags = ort->rt_flags; |
2232 | rt->rt_type = ort->rt_type; | 2232 | rt->rt_type = ort->rt_type; |
2233 | rt->rt_gateway = ort->rt_gateway; | 2233 | rt->rt_gateway = ort->rt_gateway; |
@@ -2665,7 +2665,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { | |||
2665 | 2665 | ||
2666 | static __net_init int rt_genid_init(struct net *net) | 2666 | static __net_init int rt_genid_init(struct net *net) |
2667 | { | 2667 | { |
2668 | atomic_set(&net->rt_genid, 0); | 2668 | atomic_set(&net->ipv4.rt_genid, 0); |
2669 | atomic_set(&net->fnhe_genid, 0); | 2669 | atomic_set(&net->fnhe_genid, 0); |
2670 | get_random_bytes(&net->ipv4.dev_addr_genid, | 2670 | get_random_bytes(&net->ipv4.dev_addr_genid, |
2671 | sizeof(net->ipv4.dev_addr_genid)); | 2671 | sizeof(net->ipv4.dev_addr_genid)); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index a5ac969aeefe..0d1a9b153fbb 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -766,6 +766,7 @@ static int __net_init inet6_net_init(struct net *net) | |||
766 | 766 | ||
767 | net->ipv6.sysctl.bindv6only = 0; | 767 | net->ipv6.sysctl.bindv6only = 0; |
768 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 768 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
769 | atomic_set(&net->ipv6.rt_genid, 0); | ||
769 | 770 | ||
770 | err = ipv6_init_mibs(net); | 771 | err = ipv6_init_mibs(net); |
771 | if (err) | 772 | if (err) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 74ab1f74abcd..ce9616304521 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -283,7 +283,7 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, | |||
283 | 283 | ||
284 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); | 284 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); |
285 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); | 285 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); |
286 | rt->rt6i_genid = rt_genid(net); | 286 | rt->rt6i_genid = rt_genid_ipv6(net); |
287 | INIT_LIST_HEAD(&rt->rt6i_siblings); | 287 | INIT_LIST_HEAD(&rt->rt6i_siblings); |
288 | } | 288 | } |
289 | return rt; | 289 | return rt; |
@@ -1061,7 +1061,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
1061 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | 1061 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down |
1062 | * into this function always. | 1062 | * into this function always. |
1063 | */ | 1063 | */ |
1064 | if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) | 1064 | if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) |
1065 | return NULL; | 1065 | return NULL; |
1066 | 1066 | ||
1067 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 1067 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index e52cab3591dd..d8da6b8c6ba8 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -660,7 +660,13 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
660 | xfrm_pol_hold(policy); | 660 | xfrm_pol_hold(policy); |
661 | net->xfrm.policy_count[dir]++; | 661 | net->xfrm.policy_count[dir]++; |
662 | atomic_inc(&flow_cache_genid); | 662 | atomic_inc(&flow_cache_genid); |
663 | rt_genid_bump(net); | 663 | |
664 | /* After previous checking, family can either be AF_INET or AF_INET6 */ | ||
665 | if (policy->family == AF_INET) | ||
666 | rt_genid_bump_ipv4(net); | ||
667 | else | ||
668 | rt_genid_bump_ipv6(net); | ||
669 | |||
664 | if (delpol) { | 670 | if (delpol) { |
665 | xfrm_policy_requeue(delpol, policy); | 671 | xfrm_policy_requeue(delpol, policy); |
666 | __xfrm_policy_unlink(delpol, dir); | 672 | __xfrm_policy_unlink(delpol, dir); |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 65f67cb0aefb..6713f04e30ba 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -50,8 +50,13 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | |||
50 | 50 | ||
51 | static inline void selinux_xfrm_notify_policyload(void) | 51 | static inline void selinux_xfrm_notify_policyload(void) |
52 | { | 52 | { |
53 | struct net *net; | ||
54 | |||
53 | atomic_inc(&flow_cache_genid); | 55 | atomic_inc(&flow_cache_genid); |
54 | rt_genid_bump(&init_net); | 56 | rtnl_lock(); |
57 | for_each_net(net) | ||
58 | rt_genid_bump_all(net); | ||
59 | rtnl_unlock(); | ||
55 | } | 60 | } |
56 | #else | 61 | #else |
57 | static inline int selinux_xfrm_enabled(void) | 62 | static inline int selinux_xfrm_enabled(void) |