diff options
author | Steffen Klassert <steffen.klassert@secunet.com> | 2018-01-10 12:14:28 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-01-31 14:03:41 +0100 |
commit | ceab06885c09f685910779a8685b7659d66de4b5 (patch) | |
tree | 5bf04521c572a53012746989390077c95fd0c902 /net | |
parent | 19848ca7b7dad5153860239c893c1eadd603217e (diff) | |
download | linux-stable-ceab06885c09f685910779a8685b7659d66de4b5.tar.gz linux-stable-ceab06885c09f685910779a8685b7659d66de4b5.tar.bz2 linux-stable-ceab06885c09f685910779a8685b7659d66de4b5.zip |
xfrm: Fix a race in the xdst pcpu cache.
commit 76a4201191814a0061cb5c861fafb9ecaa764846 upstream.
We need to run xfrm_resolve_and_create_bundle() with
bottom halves off. Otherwise we may reuse an already
released dst_enty when the xfrm lookup functions are
called from process context.
Fixes: c30d78c14a813db39a647b6a348b428 ("xfrm: add xdst pcpu cache")
Reported-by: Darius Ski <darius.ski@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: David Miller <davem@davemloft.net>,
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-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 6bc16bb61b55..688ed34f0671 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2056,8 +2056,11 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, if (num_xfrms <= 0) goto make_dummy_bundle; + local_bh_disable(); xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, - xflo->dst_orig); + xflo->dst_orig); + local_bh_enable(); + if (IS_ERR(xdst)) { err = PTR_ERR(xdst); if (err != -EAGAIN) @@ -2144,9 +2147,12 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, goto no_transform; } + local_bh_disable(); xdst = xfrm_resolve_and_create_bundle( pols, num_pols, fl, family, dst_orig); + local_bh_enable(); + if (IS_ERR(xdst)) { xfrm_pols_put(pols, num_pols); err = PTR_ERR(xdst); |