aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_ipcomp.c
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2013-10-17 15:07:40 +0200
committerSteffen Klassert <steffen.klassert@secunet.com>2013-10-18 10:00:00 +0200
commit12e3594698f6c3ab6ebacc79f2fb2ad2bb5952b5 (patch)
tree17915102ba31fd52f0096f77cbb38f587f16b6ec /net/xfrm/xfrm_ipcomp.c
parentnet: smc91x: dont't use SMC_outw for fixing up halfword-aligned data (diff)
downloadlinux-dev-12e3594698f6c3ab6ebacc79f2fb2ad2bb5952b5.tar.xz
linux-dev-12e3594698f6c3ab6ebacc79f2fb2ad2bb5952b5.zip
xfrm: prevent ipcomp scratch buffer race condition
In ipcomp_compress(), sortirq is enabled too early, allowing the per-cpu scratch buffer to be rewritten by ipcomp_decompress() (called on the same CPU in softirq context) between populating the buffer and copying the compressed data to the skb. v2: as pointed out by Steffen Klassert, if we also move the local_bh_disable() before reading the per-cpu pointers, we can get rid of get_cpu()/put_cpu(). v3: removed ipcomp_decompress part (as explained by Herbert Xu, it cannot be called from process context), get rid of cpu variable (thanks to Eric Dumazet) Signed-off-by: Michal Kubecek <mkubecek@suse.cz> Reviewed-by: Eric Dumazet <edumazet@google.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_ipcomp.c')
-rw-r--r--net/xfrm/xfrm_ipcomp.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index 2906d520eea7..3be02b680268 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -141,14 +141,14 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
const int plen = skb->len;
int dlen = IPCOMP_SCRATCH_SIZE;
u8 *start = skb->data;
- const int cpu = get_cpu();
- u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
- struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+ struct crypto_comp *tfm;
+ u8 *scratch;
int err;
local_bh_disable();
+ scratch = *this_cpu_ptr(ipcomp_scratches);
+ tfm = *this_cpu_ptr(ipcd->tfms);
err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
- local_bh_enable();
if (err)
goto out;
@@ -158,13 +158,13 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
}
memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
- put_cpu();
+ local_bh_enable();
pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
return 0;
out:
- put_cpu();
+ local_bh_enable();
return err;
}