diff options
Diffstat (limited to 'debian/patches-rt/0331-net-xfrm-fix-compress-vs-decompress-serialization.patch')
-rw-r--r-- | debian/patches-rt/0331-net-xfrm-fix-compress-vs-decompress-serialization.patch | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/debian/patches-rt/0331-net-xfrm-fix-compress-vs-decompress-serialization.patch b/debian/patches-rt/0331-net-xfrm-fix-compress-vs-decompress-serialization.patch new file mode 100644 index 000000000..7d3f711b4 --- /dev/null +++ b/debian/patches-rt/0331-net-xfrm-fix-compress-vs-decompress-serialization.patch @@ -0,0 +1,98 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Tue, 18 Aug 2020 09:20:53 -0700 +Subject: [PATCH 331/342] net: xfrm: fix compress vs decompress serialization +Origin: https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit?id=232e27733feb20a490b99f63f08c073c9ed9e9d9 + +A crash was seen in xfrm when running ltp's 'tcp4_ipsec06' stresser on v4.x +based RT kernels. + +ipcomp_compress() will serialize access to the ipcomp_scratches percpu buffer by +disabling BH and preventing a softirq from coming in and running ipcom_decompress(), +which is never called from process context. This of course won't work on RT and +the buffer can get corrupted; there have been similar issues with in the past with +such assumptions, ie: ebf255ed6c44 (net: add back the missing serialization in +ip_send_unicast_reply()). + +Similarly, this patch addresses the issue with locallocks allowing RT to have a +percpu spinlock and do the correct serialization. + +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Signed-off-by: Tom Zanussi <zanussi@kernel.org> +--- + net/xfrm/xfrm_ipcomp.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c +index a00ec715aa46..a97997385423 100644 +--- a/net/xfrm/xfrm_ipcomp.c ++++ b/net/xfrm/xfrm_ipcomp.c +@@ -20,6 +20,7 @@ + #include <linux/list.h> + #include <linux/module.h> + #include <linux/mutex.h> ++#include <linux/locallock.h> + #include <linux/percpu.h> + #include <linux/slab.h> + #include <linux/smp.h> +@@ -36,6 +37,7 @@ struct ipcomp_tfms { + + static DEFINE_MUTEX(ipcomp_resource_mutex); + static void * __percpu *ipcomp_scratches; ++static DEFINE_LOCAL_IRQ_LOCK(ipcomp_scratches_lock); + static int ipcomp_scratch_users; + static LIST_HEAD(ipcomp_tfms_list); + +@@ -45,12 +47,15 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) + const int plen = skb->len; + int dlen = IPCOMP_SCRATCH_SIZE; + const 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); +- int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen); +- int len; ++ u8 *scratch; ++ struct crypto_comp *tfm; ++ int err, len; ++ ++ local_lock(ipcomp_scratches_lock); + ++ scratch = *this_cpu_ptr(ipcomp_scratches); ++ tfm = *this_cpu_ptr(ipcd->tfms); ++ err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen); + if (err) + goto out; + +@@ -103,7 +108,7 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) + err = 0; + + out: +- put_cpu(); ++ local_unlock(ipcomp_scratches_lock); + return err; + } + +@@ -146,6 +151,8 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) + int err; + + local_bh_disable(); ++ local_lock(ipcomp_scratches_lock); ++ + scratch = *this_cpu_ptr(ipcomp_scratches); + tfm = *this_cpu_ptr(ipcd->tfms); + err = crypto_comp_compress(tfm, start, plen, scratch, &dlen); +@@ -158,12 +165,14 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) + } + + memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); ++ local_unlock(ipcomp_scratches_lock); + local_bh_enable(); + + pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr)); + return 0; + + out: ++ local_unlock(ipcomp_scratches_lock); + local_bh_enable(); + return err; + } |