CVE-2013-4387 ipv6: panic when UFO=On for an interface (rhbz 1011927 1015166)
This commit is contained in:
parent
59fe9957e4
commit
84bd6b090b
|
@ -0,0 +1,123 @@
|
|||
From 2811ebac2521ceac84f2bdae402455baa6a7fb47 Mon Sep 17 00:00:00 2001
|
||||
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
||||
Date: Sat, 21 Sep 2013 06:27:00 +0200
|
||||
Subject: [PATCH] ipv6: udp packets following an UFO enqueued packet need also
|
||||
be handled by UFO
|
||||
|
||||
In the following scenario the socket is corked:
|
||||
If the first UDP packet is larger then the mtu we try to append it to the
|
||||
write queue via ip6_ufo_append_data. A following packet, which is smaller
|
||||
than the mtu would be appended to the already queued up gso-skb via
|
||||
plain ip6_append_data. This causes random memory corruptions.
|
||||
|
||||
In ip6_ufo_append_data we also have to be careful to not queue up the
|
||||
same skb multiple times. So setup the gso frame only when no first skb
|
||||
is available.
|
||||
|
||||
This also fixes a shortcoming where we add the current packet's length to
|
||||
cork->length but return early because of a packet > mtu with dontfrag set
|
||||
(instead of sutracting it again).
|
||||
|
||||
Found with trinity.
|
||||
|
||||
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
||||
Reported-by: Dmitry Vyukov <dvyukov@google.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/ipv6/ip6_output.c | 53 +++++++++++++++++++++------------------------------
|
||||
1 file changed, 22 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
||||
index 3a692d5..a54c45c 100644
|
||||
--- a/net/ipv6/ip6_output.c
|
||||
+++ b/net/ipv6/ip6_output.c
|
||||
@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
||||
* udp datagram
|
||||
*/
|
||||
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
|
||||
+ struct frag_hdr fhdr;
|
||||
+
|
||||
skb = sock_alloc_send_skb(sk,
|
||||
hh_len + fragheaderlen + transhdrlen + 20,
|
||||
(flags & MSG_DONTWAIT), &err);
|
||||
@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->csum = 0;
|
||||
- }
|
||||
-
|
||||
- err = skb_append_datato_frags(sk,skb, getfrag, from,
|
||||
- (length - transhdrlen));
|
||||
- if (!err) {
|
||||
- struct frag_hdr fhdr;
|
||||
|
||||
/* Specify the length of each IPv6 datagram fragment.
|
||||
* It has to be a multiple of 8.
|
||||
@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
||||
ipv6_select_ident(&fhdr, rt);
|
||||
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
|
||||
__skb_queue_tail(&sk->sk_write_queue, skb);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
- /* There is not enough support do UPD LSO,
|
||||
- * so follow normal path
|
||||
- */
|
||||
- kfree_skb(skb);
|
||||
|
||||
- return err;
|
||||
+ return skb_append_datato_frags(sk, skb, getfrag, from,
|
||||
+ (length - transhdrlen));
|
||||
}
|
||||
|
||||
static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
|
||||
@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
||||
* --yoshfuji
|
||||
*/
|
||||
|
||||
- cork->length += length;
|
||||
- if (length > mtu) {
|
||||
- int proto = sk->sk_protocol;
|
||||
- if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
|
||||
- ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
|
||||
- return -EMSGSIZE;
|
||||
- }
|
||||
-
|
||||
- if (proto == IPPROTO_UDP &&
|
||||
- (rt->dst.dev->features & NETIF_F_UFO)) {
|
||||
+ if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
|
||||
+ sk->sk_protocol == IPPROTO_RAW)) {
|
||||
+ ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
|
||||
+ return -EMSGSIZE;
|
||||
+ }
|
||||
|
||||
- err = ip6_ufo_append_data(sk, getfrag, from, length,
|
||||
- hh_len, fragheaderlen,
|
||||
- transhdrlen, mtu, flags, rt);
|
||||
- if (err)
|
||||
- goto error;
|
||||
- return 0;
|
||||
- }
|
||||
+ skb = skb_peek_tail(&sk->sk_write_queue);
|
||||
+ cork->length += length;
|
||||
+ if (((length > mtu) ||
|
||||
+ (skb && skb_is_gso(skb))) &&
|
||||
+ (sk->sk_protocol == IPPROTO_UDP) &&
|
||||
+ (rt->dst.dev->features & NETIF_F_UFO)) {
|
||||
+ err = ip6_ufo_append_data(sk, getfrag, from, length,
|
||||
+ hh_len, fragheaderlen,
|
||||
+ transhdrlen, mtu, flags, rt);
|
||||
+ if (err)
|
||||
+ goto error;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
- if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
|
||||
+ if (!skb)
|
||||
goto alloc_new_skb;
|
||||
|
||||
while (length > 0) {
|
||||
--
|
||||
1.8.3.1
|
||||
|
|
@ -803,6 +803,9 @@ Patch25118: bonding-driver-promisc.patch
|
|||
#rhbz 1013814
|
||||
Patch25119: drm-radeon-dont-set-default-clocks-for-SI-when-DPM-is-disabled.patch
|
||||
|
||||
#CVE-2013-4387 rhbz 1011927 1015166
|
||||
Patch25121: ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
%endif
|
||||
|
@ -1564,6 +1567,9 @@ ApplyPatch bonding-driver-promisc.patch
|
|||
#rhbz 1013814
|
||||
ApplyPatch drm-radeon-dont-set-default-clocks-for-SI-when-DPM-is-disabled.patch
|
||||
|
||||
#CVE-2013-4387 rhbz 1011927 1015166
|
||||
ApplyPatch ipv6-udp-packets-following-an-UFO-enqueued-packet-ne.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
%endif
|
||||
|
@ -2366,6 +2372,9 @@ fi
|
|||
# ||----w |
|
||||
# || ||
|
||||
%changelog
|
||||
* Thu Oct 3 2013 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- CVE-2013-4387 ipv6: panic when UFO=On for an interface (rhbz 1011927 1015166)
|
||||
|
||||
* Wed Oct 2 2013 Justin M. Forbes <jforbes@fedoraproject.org>
|
||||
- drm/radeon: don't set default clocks for SI when DPM is disabled (rhbz 1013814)
|
||||
|
||||
|
|
Loading…
Reference in New Issue