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.c67
1 files changed, 36 insertions, 31 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 934492bad8e0..8d1a898d0ba5 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -680,16 +680,6 @@ static void xfrm_hash_resize(struct work_struct *work)
680 mutex_unlock(&hash_resize_mutex); 680 mutex_unlock(&hash_resize_mutex);
681} 681}
682 682
683static void xfrm_hash_reset_inexact_table(struct net *net)
684{
685 struct xfrm_pol_inexact_bin *b;
686
687 lockdep_assert_held(&net->xfrm.xfrm_policy_lock);
688
689 list_for_each_entry(b, &net->xfrm.inexact_bins, inexact_bins)
690 INIT_HLIST_HEAD(&b->hhead);
691}
692
693/* Make sure *pol can be inserted into fastbin. 683/* Make sure *pol can be inserted into fastbin.
694 * Useful to check that later insert requests will be sucessful 684 * Useful to check that later insert requests will be sucessful
695 * (provided xfrm_policy_lock is held throughout). 685 * (provided xfrm_policy_lock is held throughout).
@@ -833,13 +823,13 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
833 u16 family) 823 u16 family)
834{ 824{
835 unsigned int matched_s, matched_d; 825 unsigned int matched_s, matched_d;
836 struct hlist_node *newpos = NULL;
837 struct xfrm_policy *policy, *p; 826 struct xfrm_policy *policy, *p;
838 827
839 matched_s = 0; 828 matched_s = 0;
840 matched_d = 0; 829 matched_d = 0;
841 830
842 list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) { 831 list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
832 struct hlist_node *newpos = NULL;
843 bool matches_s, matches_d; 833 bool matches_s, matches_d;
844 834
845 if (!policy->bydst_reinsert) 835 if (!policy->bydst_reinsert)
@@ -849,16 +839,19 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
849 839
850 policy->bydst_reinsert = false; 840 policy->bydst_reinsert = false;
851 hlist_for_each_entry(p, &n->hhead, bydst) { 841 hlist_for_each_entry(p, &n->hhead, bydst) {
852 if (policy->priority >= p->priority) 842 if (policy->priority > p->priority)
843 newpos = &p->bydst;
844 else if (policy->priority == p->priority &&
845 policy->pos > p->pos)
853 newpos = &p->bydst; 846 newpos = &p->bydst;
854 else 847 else
855 break; 848 break;
856 } 849 }
857 850
858 if (newpos) 851 if (newpos)
859 hlist_add_behind(&policy->bydst, newpos); 852 hlist_add_behind_rcu(&policy->bydst, newpos);
860 else 853 else
861 hlist_add_head(&policy->bydst, &n->hhead); 854 hlist_add_head_rcu(&policy->bydst, &n->hhead);
862 855
863 /* paranoia checks follow. 856 /* paranoia checks follow.
864 * Check that the reinserted policy matches at least 857 * Check that the reinserted policy matches at least
@@ -893,12 +886,13 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
893 struct rb_root *new, 886 struct rb_root *new,
894 u16 family) 887 u16 family)
895{ 888{
896 struct rb_node **p, *parent = NULL;
897 struct xfrm_pol_inexact_node *node; 889 struct xfrm_pol_inexact_node *node;
890 struct rb_node **p, *parent;
898 891
899 /* we should not have another subtree here */ 892 /* we should not have another subtree here */
900 WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root)); 893 WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root));
901 894restart:
895 parent = NULL;
902 p = &new->rb_node; 896 p = &new->rb_node;
903 while (*p) { 897 while (*p) {
904 u8 prefixlen; 898 u8 prefixlen;
@@ -918,12 +912,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
918 } else { 912 } else {
919 struct xfrm_policy *tmp; 913 struct xfrm_policy *tmp;
920 914
921 hlist_for_each_entry(tmp, &node->hhead, bydst) 915 hlist_for_each_entry(tmp, &n->hhead, bydst) {
922 tmp->bydst_reinsert = true;
923 hlist_for_each_entry(tmp, &n->hhead, bydst)
924 tmp->bydst_reinsert = true; 916 tmp->bydst_reinsert = true;
917 hlist_del_rcu(&tmp->bydst);
918 }
925 919
926 INIT_HLIST_HEAD(&node->hhead);
927 xfrm_policy_inexact_list_reinsert(net, node, family); 920 xfrm_policy_inexact_list_reinsert(net, node, family);
928 921
929 if (node->prefixlen == n->prefixlen) { 922 if (node->prefixlen == n->prefixlen) {
@@ -935,8 +928,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
935 kfree_rcu(n, rcu); 928 kfree_rcu(n, rcu);
936 n = node; 929 n = node;
937 n->prefixlen = prefixlen; 930 n->prefixlen = prefixlen;
938 *p = new->rb_node; 931 goto restart;
939 parent = NULL;
940 } 932 }
941 } 933 }
942 934
@@ -965,12 +957,11 @@ static void xfrm_policy_inexact_node_merge(struct net *net,
965 family); 957 family);
966 } 958 }
967 959
968 hlist_for_each_entry(tmp, &v->hhead, bydst) 960 hlist_for_each_entry(tmp, &v->hhead, bydst) {
969 tmp->bydst_reinsert = true;
970 hlist_for_each_entry(tmp, &n->hhead, bydst)
971 tmp->bydst_reinsert = true; 961 tmp->bydst_reinsert = true;
962 hlist_del_rcu(&tmp->bydst);
963 }
972 964
973 INIT_HLIST_HEAD(&n->hhead);
974 xfrm_policy_inexact_list_reinsert(net, n, family); 965 xfrm_policy_inexact_list_reinsert(net, n, family);
975} 966}
976 967
@@ -1235,6 +1226,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1235 } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq)); 1226 } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
1236 1227
1237 spin_lock_bh(&net->xfrm.xfrm_policy_lock); 1228 spin_lock_bh(&net->xfrm.xfrm_policy_lock);
1229 write_seqcount_begin(&xfrm_policy_hash_generation);
1238 1230
1239 /* make sure that we can insert the indirect policies again before 1231 /* make sure that we can insert the indirect policies again before
1240 * we start with destructive action. 1232 * we start with destructive action.
@@ -1278,10 +1270,14 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1278 } 1270 }
1279 1271
1280 /* reset the bydst and inexact table in all directions */ 1272 /* reset the bydst and inexact table in all directions */
1281 xfrm_hash_reset_inexact_table(net);
1282
1283 for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { 1273 for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
1284 INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); 1274 struct hlist_node *n;
1275
1276 hlist_for_each_entry_safe(policy, n,
1277 &net->xfrm.policy_inexact[dir],
1278 bydst_inexact_list)
1279 hlist_del_init(&policy->bydst_inexact_list);
1280
1285 hmask = net->xfrm.policy_bydst[dir].hmask; 1281 hmask = net->xfrm.policy_bydst[dir].hmask;
1286 odst = net->xfrm.policy_bydst[dir].table; 1282 odst = net->xfrm.policy_bydst[dir].table;
1287 for (i = hmask; i >= 0; i--) 1283 for (i = hmask; i >= 0; i--)
@@ -1313,6 +1309,9 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1313 newpos = NULL; 1309 newpos = NULL;
1314 chain = policy_hash_bysel(net, &policy->selector, 1310 chain = policy_hash_bysel(net, &policy->selector,
1315 policy->family, dir); 1311 policy->family, dir);
1312
1313 hlist_del_rcu(&policy->bydst);
1314
1316 if (!chain) { 1315 if (!chain) {
1317 void *p = xfrm_policy_inexact_insert(policy, dir, 0); 1316 void *p = xfrm_policy_inexact_insert(policy, dir, 0);
1318 1317
@@ -1334,6 +1333,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1334 1333
1335out_unlock: 1334out_unlock:
1336 __xfrm_policy_inexact_flush(net); 1335 __xfrm_policy_inexact_flush(net);
1336 write_seqcount_end(&xfrm_policy_hash_generation);
1337 spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 1337 spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
1338 1338
1339 mutex_unlock(&hash_resize_mutex); 1339 mutex_unlock(&hash_resize_mutex);
@@ -2600,7 +2600,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
2600 dst_copy_metrics(dst1, dst); 2600 dst_copy_metrics(dst1, dst);
2601 2601
2602 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 2602 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
2603 __u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]); 2603 __u32 mark = 0;
2604
2605 if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m)
2606 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
2604 2607
2605 family = xfrm[i]->props.family; 2608 family = xfrm[i]->props.family;
2606 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, 2609 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
@@ -3311,8 +3314,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
3311 3314
3312 if (ifcb) { 3315 if (ifcb) {
3313 xi = ifcb->decode_session(skb); 3316 xi = ifcb->decode_session(skb);
3314 if (xi) 3317 if (xi) {
3315 if_id = xi->p.if_id; 3318 if_id = xi->p.if_id;
3319 net = xi->net;
3320 }
3316 } 3321 }
3317 rcu_read_unlock(); 3322 rcu_read_unlock();
3318 3323