aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2016-08-11 09:17:57 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2016-08-12 02:07:12 -0400
commitae33786f73a7ce5b15ce29e8f342e43606385cef (patch)
tree93f389908cdcf2be4bce5ef90e322f7a4f19c394 /net/xfrm
parenta7c44247f704e385c77579d65c6ee6d002832529 (diff)
xfrm: policy: only use rcu in xfrm_sk_policy_lookup
Don't acquire the readlock anymore and rely on rcu alone. In case writer on other CPU changed policy at the wrong moment (after we obtained sk policy pointer but before we could obtain the reference) 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.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 9302647f20a0..3d27b9a2fbac 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1249,10 +1249,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
1249 const struct flowi *fl) 1249 const struct flowi *fl)
1250{ 1250{
1251 struct xfrm_policy *pol; 1251 struct xfrm_policy *pol;
1252 struct net *net = sock_net(sk);
1253 1252
1254 rcu_read_lock(); 1253 rcu_read_lock();
1255 read_lock_bh(&net->xfrm.xfrm_policy_lock); 1254 again:
1256 pol = rcu_dereference(sk->sk_policy[dir]); 1255 pol = rcu_dereference(sk->sk_policy[dir]);
1257 if (pol != NULL) { 1256 if (pol != NULL) {
1258 bool match = xfrm_selector_match(&pol->selector, fl, 1257 bool match = xfrm_selector_match(&pol->selector, fl,
@@ -1267,8 +1266,8 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
1267 err = security_xfrm_policy_lookup(pol->security, 1266 err = security_xfrm_policy_lookup(pol->security,
1268 fl->flowi_secid, 1267 fl->flowi_secid,
1269 policy_to_flow_dir(dir)); 1268 policy_to_flow_dir(dir));
1270 if (!err) 1269 if (!err && !xfrm_pol_hold_rcu(pol))
1271 xfrm_pol_hold(pol); 1270 goto again;
1272 else if (err == -ESRCH) 1271 else if (err == -ESRCH)
1273 pol = NULL; 1272 pol = NULL;
1274 else 1273 else
@@ -1277,7 +1276,6 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
1277 pol = NULL; 1276 pol = NULL;
1278 } 1277 }
1279out: 1278out:
1280 read_unlock_bh(&net->xfrm.xfrm_policy_lock);
1281 rcu_read_unlock(); 1279 rcu_read_unlock();
1282 return pol; 1280 return pol;
1283} 1281}