summaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-01-04 14:17:01 +0100
committerSteffen Klassert <steffen.klassert@secunet.com>2019-01-09 13:58:23 +0100
commit7a474c36586f4277f930ab7e6865c97e44dfc3bc (patch)
tree5495f12516af3b388932004c7ee9dd1eaa179e44 /net/xfrm/xfrm_policy.c
parent355b00d1e14051c13aea48c1c5430c486fed2d7a (diff)
downloadlinux-7a474c36586f4277f930ab7e6865c97e44dfc3bc.tar.gz
linux-7a474c36586f4277f930ab7e6865c97e44dfc3bc.tar.bz2
linux-7a474c36586f4277f930ab7e6865c97e44dfc3bc.zip
xfrm: policy: increment xfrm_hash_generation on hash rebuild
Hash rebuild will re-set all the inexact entries, then re-insert them. Lookups that can occur in parallel will therefore not find any policies. This was safe when lookups were still guarded by rwlock. After rcu-ification, lookups check the hash_generation seqcount to detect when a hash resize takes place. Hash rebuild missed the needed increment. Hash resizes and hash rebuilds cannot occur in parallel (both acquire hash_resize_mutex), so just increment xfrm_hash_generation, like resize. Fixes: a7c44247f704e3 ("xfrm: policy: make xfrm_policy_lookup_bytype lockless") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 628b389af2ba..d8fba27a4bfb 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1235,6 +1235,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
} while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
+ write_seqcount_begin(&xfrm_policy_hash_generation);
/* make sure that we can insert the indirect policies again before
* we start with destructive action.
@@ -1334,6 +1335,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
out_unlock:
__xfrm_policy_inexact_flush(net);
+ write_seqcount_end(&xfrm_policy_hash_generation);
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
mutex_unlock(&hash_resize_mutex);