netfilter: ipv6: nf_defrag: drop mangled skb on ream error (CVE-2016-9755)

This commit is contained in:
Salvatore Bonaccorso 2016-12-14 17:11:29 +01:00
parent 7a3d9312d0
commit 966cf13de0
3 changed files with 71 additions and 0 deletions

1
debian/changelog vendored
View File

@ -131,6 +131,7 @@ linux (4.8.14-1) UNRELEASED; urgency=medium
* net: handle no dst on skb in icmp6_send (CVE-2016-9919)
* [rt] Update to 4.8.11-rt7
* [rt] Update to 4.8.14-rt9
* netfilter: ipv6: nf_defrag: drop mangled skb on ream error (CVE-2016-9755)
[ Ben Hutchings ]
* [amd64] Re-enable LEGACY_VSYSCALL_EMULATE instead of LEGACY_VSYSCALL_NONE.

View File

@ -0,0 +1,69 @@
From: Florian Westphal <fw@strlen.de>
Date: Tue, 29 Nov 2016 02:17:34 +0100
Subject: netfilter: ipv6: nf_defrag: drop mangled skb on ream error
Origin: https://git.kernel.org/linus/9b57da0630c9fd36ed7a20fc0f98dc82cc0777fa
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.1.4

View File

@ -103,6 +103,7 @@ bugfix/all/fs-Avoid-premature-clearing-of-capabilities.patch
bugfix/all/vfio-pci-Fix-integer-overflows-bitmask-check.patch
bugfix/all/mnt-Add-a-per-mount-namespace-limit-on-the-number-of.patch
bugfix/all/net-handle-no-dst-on-skb-in-icmp6_send.patch
bugfix/all/netfilter-ipv6-nf_defrag-drop-mangled-skb-on-ream-er.patch
# ABI maintenance