Fix NULL dereference in udp6_ufo_fragment(), caused by fix for CVE-2011-2699.

This commit is contained in:
Chuck Ebbert 2011-10-25 10:22:06 -04:00
parent c8c0a79ec2
commit 4d20e68f2c
2 changed files with 110 additions and 0 deletions

View File

@ -0,0 +1,103 @@
From jasowang@redhat.com Sat Oct 8 20:56:54 2011
Subject: ipv6: fix NULL dereference in udp6_ufo_fragment()
To: gregkh@suse.de, stable@kernel.org
From: Jason Wang <jasowang@redhat.com>
Cc: davem@davemloft.net, eric.dumazet@gmail.com
Date: Sun, 09 Oct 2011 10:56:44 +0800
Message-ID: <20111009025644.9437.53281.stgit@dhcp-8-146.nay.redhat.com>
From: Jason Wang <jasowang@redhat.com>
This patch fixes the issue caused by ef81bb40bf15f350fe865f31fa42f1082772a576
which is a backport of upstream 87c48fa3b4630905f98268dde838ee43626a060c. The
problem does not exist in upstream.
We do not check whether route is attached before trying to assign ip
identification through route dest which lead NULL pointer dereference. This
happens when host bridge transmit a packet from guest.
This patch changes ipv6_select_ident() to accept in6_addr as its paramter and
fix the issue by using the destination address in ipv6 header when no route is
attached.
Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
include/net/ipv6.h | 2 +-
net/ipv6/ip6_output.c | 10 +++++-----
net/ipv6/udp.c | 4 +++-
3 files changed, 9 insertions(+), 7 deletions(-)
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -463,7 +463,7 @@ static inline int ipv6_addr_diff(const s
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
}
-extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr);
/*
* Prototypes exported by ipv6
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -620,9 +620,9 @@ static u32 __ipv6_select_ident(const str
return hash + newid;
}
-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr)
{
- fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
+ fhdr->identification = htonl(__ipv6_select_ident(addr));
}
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
@@ -709,7 +709,7 @@ int ip6_fragment(struct sk_buff *skb, in
skb_reset_network_header(skb);
memcpy(skb_network_header(skb), tmp_hdr, hlen);
- ipv6_select_ident(fh, rt);
+ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
fh->nexthdr = nexthdr;
fh->reserved = 0;
fh->frag_off = htons(IP6_MF);
@@ -855,7 +855,7 @@ slow_path:
fh->nexthdr = nexthdr;
fh->reserved = 0;
if (!frag_id) {
- ipv6_select_ident(fh, rt);
+ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
frag_id = fh->identification;
} else
fh->identification = frag_id;
@@ -1146,7 +1146,7 @@ static inline int ip6_ufo_append_data(st
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
sizeof(struct frag_hdr)) & ~7;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
- ipv6_select_ident(&fhdr, rt);
+ ipv6_select_ident(&fhdr, &rt->rt6i_dst.addr);
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
__skb_queue_tail(&sk->sk_write_queue, skb);
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1309,6 +1309,7 @@ static struct sk_buff *udp6_ufo_fragment
u8 frag_hdr_sz = sizeof(struct frag_hdr);
int offset;
__wsum csum;
+ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
mss = skb_shinfo(skb)->gso_size;
if (unlikely(skb->len <= mss))
@@ -1359,7 +1360,8 @@ static struct sk_buff *udp6_ufo_fragment
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
fptr->nexthdr = nexthdr;
fptr->reserved = 0;
- ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+ ipv6_select_ident(fptr,
+ rt ? &rt->rt6i_dst.addr : &ipv6_hdr(skb)->daddr);
/* Fragment the skb. ipv6 header and the remaining fields of the
* fragment header are updated in ipv6_gso_segment()

View File

@ -852,6 +852,8 @@ Patch14012: bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch
Patch14013: nl80211-fix-overflow-in-ssid_len.patch.patch
# CVE-2011-2699
Patch14014: ipv6-make-fragment-identifications-less-predictable.patch
# fix possible null dereference in above fix
Patch14015: ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
# RHBZ #699684
Patch14020: x86-mm-fix-pgd_lock-deadlock.patch
@ -1657,6 +1659,7 @@ ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch
ApplyPatch nl80211-fix-overflow-in-ssid_len.patch.patch
# CVE-2011-2699
ApplyPatch ipv6-make-fragment-identifications-less-predictable.patch
ApplyPatch ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
# RHBZ #699684
ApplyPatch x86-mm-fix-pgd_lock-deadlock.patch
@ -2292,6 +2295,10 @@ fi
# and build.
%changelog
* Tue Oct 25 2011 Chuck Ebbert <cebbert@redhat.com>
- Fix NULL dereference in udp6_ufo_fragment(), caused by
fix for CVE-2011-2699.
* Fri Oct 21 2011 Dave Jones <davej@redhat.com> 2.6.35.14-100
- Lower severity of Radeon lockup messages.