diff options
Diffstat (limited to '0001-netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch')
-rw-r--r-- | 0001-netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/0001-netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch b/0001-netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch new file mode 100644 index 000000000..a5af1a3e9 --- /dev/null +++ b/0001-netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch @@ -0,0 +1,69 @@ +From 9b57da0630c9fd36ed7a20fc0f98dc82cc0777fa Mon Sep 17 00:00:00 2001 +From: Florian Westphal <fw@strlen.de> +Date: Tue, 29 Nov 2016 02:17:34 +0100 +Subject: [PATCH] netfilter: ipv6: nf_defrag: drop mangled skb on ream error + +Dmitry Vyukov reported GPF in network stack that Andrey traced down to +negative nh offset in nf_ct_frag6_queue(). + +Problem is that all network headers before fragment header are pulled. +Normal ipv6 reassembly will drop the skb when errors occur further down +the line. + +netfilter doesn't do this, and instead passed the original fragment +along. That was also fine back when netfilter ipv6 defrag worked with +cloned fragments, as the original, pristine fragment was passed on. + +So we either have to undo the pull op, or discard such fragments. +Since they're malformed after all (e.g. overlapping fragment) it seems +preferrable to just drop them. + +Same for temporary errors -- it doesn't make sense to accept (and +perhaps forward!) only some fragments of same datagram. + +Fixes: 029f7f3b8701cc7ac ("netfilter: ipv6: nf_defrag: avoid/free clone operations") +Reported-by: Dmitry Vyukov <dvyukov@google.com> +Debugged-by: Andrey Konovalov <andreyknvl@google.com> +Diagnosed-by: Eric Dumazet <Eric Dumazet <edumazet@google.com> +Signed-off-by: Florian Westphal <fw@strlen.de> +Acked-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + net/ipv6/netfilter/nf_conntrack_reasm.c | 4 ++-- + net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index e4347ae..9948b5c 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -576,11 +576,11 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) + /* Jumbo payload inhibits frag. header */ + if (ipv6_hdr(skb)->payload_len == 0) { + pr_debug("payload len = 0\n"); +- return -EINVAL; ++ return 0; + } + + if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0) +- return -EINVAL; ++ return 0; + + if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr))) + return -ENOMEM; +diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +index f7aab5a..f06b047 100644 +--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c ++++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +@@ -69,7 +69,7 @@ static unsigned int ipv6_defrag(void *priv, + if (err == -EINPROGRESS) + return NF_STOLEN; + +- return NF_ACCEPT; ++ return err == 0 ? NF_ACCEPT : NF_DROP; + } + + static struct nf_hook_ops ipv6_defrag_ops[] = { +-- +2.9.3 + |