aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c96
1 files changed, 52 insertions, 44 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index c5a5165a592..41eabc46f11 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -42,13 +42,12 @@ static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock);
42static struct dst_entry *xfrm_policy_sk_bundles; 42static struct dst_entry *xfrm_policy_sk_bundles;
43static DEFINE_RWLOCK(xfrm_policy_lock); 43static DEFINE_RWLOCK(xfrm_policy_lock);
44 44
45static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); 45static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
46static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; 46static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
47 __read_mostly;
47 48
48static struct kmem_cache *xfrm_dst_cache __read_mostly; 49static struct kmem_cache *xfrm_dst_cache __read_mostly;
49 50
50static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
51static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
52static void xfrm_init_pmtu(struct dst_entry *dst); 51static void xfrm_init_pmtu(struct dst_entry *dst);
53static int stale_bundle(struct dst_entry *dst); 52static int stale_bundle(struct dst_entry *dst);
54static int xfrm_bundle_ok(struct xfrm_dst *xdst); 53static int xfrm_bundle_ok(struct xfrm_dst *xdst);
@@ -95,6 +94,24 @@ bool xfrm_selector_match(const struct xfrm_selector *sel, const struct flowi *fl
95 return false; 94 return false;
96} 95}
97 96
97static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
98{
99 struct xfrm_policy_afinfo *afinfo;
100
101 if (unlikely(family >= NPROTO))
102 return NULL;
103 rcu_read_lock();
104 afinfo = rcu_dereference(xfrm_policy_afinfo[family]);
105 if (unlikely(!afinfo))
106 rcu_read_unlock();
107 return afinfo;
108}
109
110static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
111{
112 rcu_read_unlock();
113}
114
98static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, 115static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
99 const xfrm_address_t *saddr, 116 const xfrm_address_t *saddr,
100 const xfrm_address_t *daddr, 117 const xfrm_address_t *daddr,
@@ -585,6 +602,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
585 xfrm_pol_hold(policy); 602 xfrm_pol_hold(policy);
586 net->xfrm.policy_count[dir]++; 603 net->xfrm.policy_count[dir]++;
587 atomic_inc(&flow_cache_genid); 604 atomic_inc(&flow_cache_genid);
605 rt_genid_bump(net);
588 if (delpol) 606 if (delpol)
589 __xfrm_policy_unlink(delpol, dir); 607 __xfrm_policy_unlink(delpol, dir);
590 policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); 608 policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
@@ -1357,6 +1375,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
1357 1375
1358 memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); 1376 memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst));
1359 xdst->flo.ops = &xfrm_bundle_fc_ops; 1377 xdst->flo.ops = &xfrm_bundle_fc_ops;
1378 if (afinfo->init_dst)
1379 afinfo->init_dst(net, xdst);
1360 } else 1380 } else
1361 xdst = ERR_PTR(-ENOBUFS); 1381 xdst = ERR_PTR(-ENOBUFS);
1362 1382
@@ -1761,7 +1781,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,
1761 1781
1762 if (!afinfo) { 1782 if (!afinfo) {
1763 dst_release(dst_orig); 1783 dst_release(dst_orig);
1764 ret = ERR_PTR(-EINVAL); 1784 return ERR_PTR(-EINVAL);
1765 } else { 1785 } else {
1766 ret = afinfo->blackhole_route(net, dst_orig); 1786 ret = afinfo->blackhole_route(net, dst_orig);
1767 } 1787 }
@@ -2418,7 +2438,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2418 return -EINVAL; 2438 return -EINVAL;
2419 if (unlikely(afinfo->family >= NPROTO)) 2439 if (unlikely(afinfo->family >= NPROTO))
2420 return -EAFNOSUPPORT; 2440 return -EAFNOSUPPORT;
2421 write_lock_bh(&xfrm_policy_afinfo_lock); 2441 spin_lock(&xfrm_policy_afinfo_lock);
2422 if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) 2442 if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
2423 err = -ENOBUFS; 2443 err = -ENOBUFS;
2424 else { 2444 else {
@@ -2439,9 +2459,9 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2439 dst_ops->neigh_lookup = xfrm_neigh_lookup; 2459 dst_ops->neigh_lookup = xfrm_neigh_lookup;
2440 if (likely(afinfo->garbage_collect == NULL)) 2460 if (likely(afinfo->garbage_collect == NULL))
2441 afinfo->garbage_collect = xfrm_garbage_collect_deferred; 2461 afinfo->garbage_collect = xfrm_garbage_collect_deferred;
2442 xfrm_policy_afinfo[afinfo->family] = afinfo; 2462 rcu_assign_pointer(xfrm_policy_afinfo[afinfo->family], afinfo);
2443 } 2463 }
2444 write_unlock_bh(&xfrm_policy_afinfo_lock); 2464 spin_unlock(&xfrm_policy_afinfo_lock);
2445 2465
2446 rtnl_lock(); 2466 rtnl_lock();
2447 for_each_net(net) { 2467 for_each_net(net) {
@@ -2474,21 +2494,26 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
2474 return -EINVAL; 2494 return -EINVAL;
2475 if (unlikely(afinfo->family >= NPROTO)) 2495 if (unlikely(afinfo->family >= NPROTO))
2476 return -EAFNOSUPPORT; 2496 return -EAFNOSUPPORT;
2477 write_lock_bh(&xfrm_policy_afinfo_lock); 2497 spin_lock(&xfrm_policy_afinfo_lock);
2478 if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { 2498 if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) {
2479 if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) 2499 if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo))
2480 err = -EINVAL; 2500 err = -EINVAL;
2481 else { 2501 else
2482 struct dst_ops *dst_ops = afinfo->dst_ops; 2502 RCU_INIT_POINTER(xfrm_policy_afinfo[afinfo->family],
2483 xfrm_policy_afinfo[afinfo->family] = NULL; 2503 NULL);
2484 dst_ops->kmem_cachep = NULL; 2504 }
2485 dst_ops->check = NULL; 2505 spin_unlock(&xfrm_policy_afinfo_lock);
2486 dst_ops->negative_advice = NULL; 2506 if (!err) {
2487 dst_ops->link_failure = NULL; 2507 struct dst_ops *dst_ops = afinfo->dst_ops;
2488 afinfo->garbage_collect = NULL; 2508
2489 } 2509 synchronize_rcu();
2510
2511 dst_ops->kmem_cachep = NULL;
2512 dst_ops->check = NULL;
2513 dst_ops->negative_advice = NULL;
2514 dst_ops->link_failure = NULL;
2515 afinfo->garbage_collect = NULL;
2490 } 2516 }
2491 write_unlock_bh(&xfrm_policy_afinfo_lock);
2492 return err; 2517 return err;
2493} 2518}
2494EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); 2519EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
@@ -2497,33 +2522,16 @@ static void __net_init xfrm_dst_ops_init(struct net *net)
2497{ 2522{
2498 struct xfrm_policy_afinfo *afinfo; 2523 struct xfrm_policy_afinfo *afinfo;
2499 2524
2500 read_lock_bh(&xfrm_policy_afinfo_lock); 2525 rcu_read_lock();
2501 afinfo = xfrm_policy_afinfo[AF_INET]; 2526 afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]);
2502 if (afinfo) 2527 if (afinfo)
2503 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; 2528 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
2504#if IS_ENABLED(CONFIG_IPV6) 2529#if IS_ENABLED(CONFIG_IPV6)
2505 afinfo = xfrm_policy_afinfo[AF_INET6]; 2530 afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]);
2506 if (afinfo) 2531 if (afinfo)
2507 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; 2532 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
2508#endif 2533#endif
2509 read_unlock_bh(&xfrm_policy_afinfo_lock); 2534 rcu_read_unlock();
2510}
2511
2512static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
2513{
2514 struct xfrm_policy_afinfo *afinfo;
2515 if (unlikely(family >= NPROTO))
2516 return NULL;
2517 read_lock(&xfrm_policy_afinfo_lock);
2518 afinfo = xfrm_policy_afinfo[family];
2519 if (unlikely(!afinfo))
2520 read_unlock(&xfrm_policy_afinfo_lock);
2521 return afinfo;
2522}
2523
2524static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
2525{
2526 read_unlock(&xfrm_policy_afinfo_lock);
2527} 2535}
2528 2536
2529static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 2537static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
@@ -2630,12 +2638,12 @@ static void xfrm_policy_fini(struct net *net)
2630 2638
2631 flush_work(&net->xfrm.policy_hash_work); 2639 flush_work(&net->xfrm.policy_hash_work);
2632#ifdef CONFIG_XFRM_SUB_POLICY 2640#ifdef CONFIG_XFRM_SUB_POLICY
2633 audit_info.loginuid = -1; 2641 audit_info.loginuid = INVALID_UID;
2634 audit_info.sessionid = -1; 2642 audit_info.sessionid = -1;
2635 audit_info.secid = 0; 2643 audit_info.secid = 0;
2636 xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info); 2644 xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info);
2637#endif 2645#endif
2638 audit_info.loginuid = -1; 2646 audit_info.loginuid = INVALID_UID;
2639 audit_info.sessionid = -1; 2647 audit_info.sessionid = -1;
2640 audit_info.secid = 0; 2648 audit_info.secid = 0;
2641 xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); 2649 xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info);
@@ -2742,7 +2750,7 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp,
2742} 2750}
2743 2751
2744void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, 2752void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
2745 uid_t auid, u32 sessionid, u32 secid) 2753 kuid_t auid, u32 sessionid, u32 secid)
2746{ 2754{
2747 struct audit_buffer *audit_buf; 2755 struct audit_buffer *audit_buf;
2748 2756
@@ -2757,7 +2765,7 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
2757EXPORT_SYMBOL_GPL(xfrm_audit_policy_add); 2765EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
2758 2766
2759void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, 2767void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
2760 uid_t auid, u32 sessionid, u32 secid) 2768 kuid_t auid, u32 sessionid, u32 secid)
2761{ 2769{
2762 struct audit_buffer *audit_buf; 2770 struct audit_buffer *audit_buf;
2763 2771