Merge tag 'locking-urgent-2020-08-10' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / net / xfrm / xfrm_policy.c
index 19c5e0fa3f44d89fa7767bbaa6be0a579dd5f26e..d5280fd6f9c127b6099f07108a74f76005923e98 100644 (file)
@@ -122,7 +122,7 @@ struct xfrm_pol_inexact_bin {
        /* list containing '*:*' policies */
        struct hlist_head hhead;
 
-       seqcount_t count;
+       seqcount_spinlock_t count;
        /* tree sorted by daddr/prefix */
        struct rb_root root_d;
 
@@ -155,7 +155,7 @@ static struct xfrm_policy_afinfo const __rcu *xfrm_policy_afinfo[AF_INET6 + 1]
                                                __read_mostly;
 
 static struct kmem_cache *xfrm_dst_cache __ro_after_init;
-static __read_mostly seqcount_t xfrm_policy_hash_generation;
+static __read_mostly seqcount_mutex_t xfrm_policy_hash_generation;
 
 static struct rhashtable xfrm_policy_inexact_table;
 static const struct rhashtable_params xfrm_pol_inexact_params;
@@ -719,7 +719,7 @@ xfrm_policy_inexact_alloc_bin(const struct xfrm_policy *pol, u8 dir)
        INIT_HLIST_HEAD(&bin->hhead);
        bin->root_d = RB_ROOT;
        bin->root_s = RB_ROOT;
-       seqcount_init(&bin->count);
+       seqcount_spinlock_init(&bin->count, &net->xfrm.xfrm_policy_lock);
 
        prev = rhashtable_lookup_get_insert_key(&xfrm_policy_inexact_table,
                                                &bin->k, &bin->head,
@@ -1899,7 +1899,7 @@ static int xfrm_policy_match(const struct xfrm_policy *pol,
 
 static struct xfrm_pol_inexact_node *
 xfrm_policy_lookup_inexact_addr(const struct rb_root *r,
-                               seqcount_t *count,
+                               seqcount_spinlock_t *count,
                                const xfrm_address_t *addr, u16 family)
 {
        const struct rb_node *parent;
@@ -2751,6 +2751,7 @@ static void xfrm_policy_queue_process(struct timer_list *t)
        struct xfrm_policy_queue *pq = &pol->polq;
        struct flowi fl;
        struct sk_buff_head list;
+       __u32 skb_mark;
 
        spin_lock(&pq->hold_queue.lock);
        skb = skb_peek(&pq->hold_queue);
@@ -2760,7 +2761,12 @@ static void xfrm_policy_queue_process(struct timer_list *t)
        }
        dst = skb_dst(skb);
        sk = skb->sk;
+
+       /* Fixup the mark to support VTI. */
+       skb_mark = skb->mark;
+       skb->mark = pol->mark.v;
        xfrm_decode_session(skb, &fl, dst->ops->family);
+       skb->mark = skb_mark;
        spin_unlock(&pq->hold_queue.lock);
 
        dst_hold(xfrm_dst_path(dst));
@@ -2792,7 +2798,12 @@ static void xfrm_policy_queue_process(struct timer_list *t)
        while (!skb_queue_empty(&list)) {
                skb = __skb_dequeue(&list);
 
+               /* Fixup the mark to support VTI. */
+               skb_mark = skb->mark;
+               skb->mark = pol->mark.v;
                xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family);
+               skb->mark = skb_mark;
+
                dst_hold(xfrm_dst_path(skb_dst(skb)));
                dst = xfrm_lookup(net, xfrm_dst_path(skb_dst(skb)), &fl, skb->sk, 0);
                if (IS_ERR(dst)) {
@@ -4146,7 +4157,7 @@ void __init xfrm_init(void)
 {
        register_pernet_subsys(&xfrm_net_ops);
        xfrm_dev_init();
-       seqcount_init(&xfrm_policy_hash_generation);
+       seqcount_mutex_init(&xfrm_policy_hash_generation, &hash_resize_mutex);
        xfrm_input_init();
 
 #ifdef CONFIG_XFRM_ESPINTCP