diff options
author | Florian Westphal <fw@strlen.de> | 2016-08-11 09:17:55 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2016-08-12 02:07:11 -0400 |
commit | e37cc8ade5afaf082f804c6d18eb23377146bec4 (patch) | |
tree | c9e1bf67bfedc04fb6e0b6840bd280198c300549 /net/xfrm | |
parent | 30846090a746edfdb230deadd638cfa96f7b8c91 (diff) |
xfrm: policy: use atomic_inc_not_zero in rcu section
If we don't hold the policy lock anymore the refcnt might
already be 0, i.e. policy struct is about to be free'd.
Switch to atomic_inc_not_zero to avoid this.
On removal policies are already unlinked from the tables (lists)
before the last _put occurs so we are not supposed to find the same
'dead' entry on the next loop, so its safe to just repeat the lookup.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 576d90321068..09f2e2b38246 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -60,6 +60,11 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir); | |||
60 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | 60 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, |
61 | int dir); | 61 | int dir); |
62 | 62 | ||
63 | static inline bool xfrm_pol_hold_rcu(struct xfrm_policy *policy) | ||
64 | { | ||
65 | return atomic_inc_not_zero(&policy->refcnt); | ||
66 | } | ||
67 | |||
63 | static inline bool | 68 | static inline bool |
64 | __xfrm4_selector_match(const struct xfrm_selector *sel, const struct flowi *fl) | 69 | __xfrm4_selector_match(const struct xfrm_selector *sel, const struct flowi *fl) |
65 | { | 70 | { |
@@ -1164,7 +1169,8 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, | |||
1164 | if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) | 1169 | if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) |
1165 | goto retry; | 1170 | goto retry; |
1166 | 1171 | ||
1167 | xfrm_pol_hold(ret); | 1172 | if (ret && !xfrm_pol_hold_rcu(ret)) |
1173 | goto retry; | ||
1168 | fail: | 1174 | fail: |
1169 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); | 1175 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1170 | 1176 | ||