[kernel] r8428 - in dists/etch-security/linux-2.6/debian: . patches/bugfix patches/series

Dann Frazier dannf at alioth.debian.org
Fri Apr 6 20:55:43 UTC 2007


Author: dannf
Date: Fri Apr  6 20:55:42 2007
New Revision: 8428

Added:
   dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-endianness-annotations.patch
   dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-length-mismatch.patch
Modified:
   dists/etch-security/linux-2.6/debian/changelog
   dists/etch-security/linux-2.6/debian/patches/series/12etch1
Log:
* bugfix/appletalk-length-mismatch.patch
  [SECURITY] Fix a remote DoS (crash) in appletalk
  Depends upon bugfix/appletalk-endianness-annotations.patch
  See CVE-2007-1357

Modified: dists/etch-security/linux-2.6/debian/changelog
==============================================================================
--- dists/etch-security/linux-2.6/debian/changelog	(original)
+++ dists/etch-security/linux-2.6/debian/changelog	Fri Apr  6 20:55:42 2007
@@ -4,8 +4,12 @@
     [SECURITY] Fix a vulnerability that allows local users to read
     otherwise unreadable (but executable) files by triggering a core dump.
     See CVE-2007-0958
+  * bugfix/appletalk-length-mismatch.patch
+    [SECURITY] Fix a remote DoS (crash) in appletalk
+    Depends upon bugfix/appletalk-endianness-annotations.patch
+    See CVE-2007-1357
 
- -- dann frazier <dannf at debian.org>  Wed, 04 Apr 2007 01:38:23 -0600
+ -- dann frazier <dannf at debian.org>  Fri, 06 Apr 2007 14:33:49 -0600
 
 linux-2.6 (2.6.18.dfsg.1-12) unstable; urgency=low
 

Added: dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-endianness-annotations.patch
==============================================================================
--- (empty file)
+++ dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-endianness-annotations.patch	Fri Apr  6 20:55:42 2007
@@ -0,0 +1,285 @@
+From: Al Viro <viro at zeniv.linux.org.uk>
+Date: Wed, 27 Sep 2006 04:22:08 +0000 (-0700)
+Subject: [ATALK]: endianness annotations
+X-Git-Tag: v2.6.19~1799^2~155
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=2a50f28c326d20ab4556be1b867ecddf6aefbb88
+
+[ATALK]: endianness annotations
+
+Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
+index 7f7dd45..b98592a 100644
+--- a/drivers/net/appletalk/ipddp.c
++++ b/drivers/net/appletalk/ipddp.c
+@@ -145,9 +145,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	/* Create the Extended DDP header */
+ 	ddp = (struct ddpehdr *)skb->data;
+-        ddp->deh_len = skb->len;
+-        ddp->deh_hops = 1;
+-        ddp->deh_pad = 0;
++        ddp->deh_len_hops = htons(skb->len + (1<<10));
+         ddp->deh_sum = 0;
+ 
+ 	/*
+@@ -170,7 +168,6 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
+         ddp->deh_sport = 72;
+ 
+         *((__u8 *)(ddp+1)) = 22;        	/* ddp type = IP */
+-        *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));	/* fix up length field */
+ 
+         skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */
+ 
+diff --git a/include/linux/atalk.h b/include/linux/atalk.h
+index 6ba3aa8..75b8bac 100644
+--- a/include/linux/atalk.h
++++ b/include/linux/atalk.h
+@@ -88,15 +88,7 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
+ #include <asm/byteorder.h>
+ 
+ struct ddpehdr {
+-#ifdef __LITTLE_ENDIAN_BITFIELD
+-	__u16	deh_len:10,
+-		deh_hops:4,
+-		deh_pad:2;
+-#else
+-	__u16	deh_pad:2,
+-		deh_hops:4,
+-		deh_len:10;
+-#endif
++	__be16	deh_len_hops;	/* lower 10 bits are length, next 4 - hops */
+ 	__be16	deh_sum;
+ 	__be16	deh_dnet;
+ 	__be16	deh_snet;
+@@ -112,36 +104,6 @@ static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb)
+ 	return (struct ddpehdr *)skb->h.raw;
+ }
+ 
+-/*
+- *	Don't drop the struct into the struct above.  You'll get some
+- *	surprise padding.
+- */
+-struct ddpebits {
+-#ifdef __LITTLE_ENDIAN_BITFIELD
+-	__u16	deh_len:10,
+-		deh_hops:4,
+-		deh_pad:2;
+-#else
+-	__u16	deh_pad:2,
+-		deh_hops:4,
+-		deh_len:10;
+-#endif
+-};
+-
+-/* Short form header */
+-struct ddpshdr {
+-#ifdef __LITTLE_ENDIAN_BITFIELD
+-	__u16	dsh_len:10,
+-		dsh_pad:6;
+-#else
+-	__u16	dsh_pad:6,
+-		dsh_len:10;
+-#endif
+-	__u8	dsh_dport;
+-	__u8	dsh_sport;
+-	/* And netatalk apps expect to stick the type in themselves */
+-};
+-
+ /* AppleTalk AARP headers */
+ struct elapaarp {
+ 	__be16	hw_type;
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index 96dc6bb..708e2e0 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -1002,7 +1002,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
+ 	return sum;
+ }
+ 
+-static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
++static __be16 atalk_checksum(const struct sk_buff *skb, int len)
+ {
+ 	unsigned long sum;
+ 
+@@ -1010,7 +1010,7 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
+ 	sum = atalk_sum_skb(skb, 4, len-4, 0);
+ 
+ 	/* Use 0xFFFF for 0. 0 itself means none */
+-	return sum ? htons((unsigned short)sum) : 0xFFFF;
++	return sum ? htons((unsigned short)sum) : htons(0xFFFF);
+ }
+ 
+ static struct proto ddp_proto = {
+@@ -1289,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
+ #endif
+ 
+ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+-			       struct ddpehdr *ddp, struct ddpebits *ddphv,
++			       struct ddpehdr *ddp, __u16 len_hops,
+ 			       int origlen)
+ {
+ 	struct atalk_route *rt;
+@@ -1317,10 +1317,12 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+ 
+ 	/* Route the packet */
+ 	rt = atrtr_find(&ta);
+-	if (!rt || ddphv->deh_hops == DDP_MAXHOPS)
++	/* increment hops count */
++	len_hops += 1 << 10;
++	if (!rt || !(len_hops & (15 << 10)))
+ 		goto free_it;
++
+ 	/* FIXME: use skb->cb to be able to use shared skbs */
+-	ddphv->deh_hops++;
+ 
+ 	/*
+ 	 * Route goes through another gateway, so set the target to the
+@@ -1335,11 +1337,10 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+         /* Fix up skb->len field */
+         skb_trim(skb, min_t(unsigned int, origlen,
+ 			    (rt->dev->hard_header_len +
+-			     ddp_dl->header_length + ddphv->deh_len)));
++			     ddp_dl->header_length + (len_hops & 1023))));
+ 
+-	/* Mend the byte order */
+ 	/* FIXME: use skb->cb to be able to use shared skbs */
+-	*((__u16 *)ddp) = ntohs(*((__u16 *)ddphv));
++	ddp->deh_len_hops = htons(len_hops);
+ 
+ 	/*
+ 	 * Send the buffer onwards
+@@ -1394,7 +1395,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	struct atalk_iface *atif;
+ 	struct sockaddr_at tosat;
+         int origlen;
+-        struct ddpebits ddphv;
++	__u16 len_hops;
+ 
+ 	/* Don't mangle buffer if shared */
+ 	if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
+@@ -1406,16 +1407,11 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 
+ 	ddp = ddp_hdr(skb);
+ 
+-	/*
+-	 *	Fix up the length field	[Ok this is horrible but otherwise
+-	 *	I end up with unions of bit fields and messy bit field order
+-	 *	compiler/endian dependencies..]
+-	 */
+-	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
++	len_hops = ntohs(ddp->deh_len_hops);
+ 
+ 	/* Trim buffer in case of stray trailing data */
+ 	origlen = skb->len;
+-	skb_trim(skb, min_t(unsigned int, skb->len, ddphv.deh_len));
++	skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023));
+ 
+ 	/*
+ 	 * Size check to see if ddp->deh_len was crap
+@@ -1430,7 +1426,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	 * valid for net byte orders all over the networking code...
+ 	 */
+ 	if (ddp->deh_sum &&
+-	    atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum)
++	    atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
+ 		/* Not a valid AppleTalk frame - dustbin time */
+ 		goto freeit;
+ 
+@@ -1444,7 +1440,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 		/* Not ours, so we route the packet via the correct
+ 		 * AppleTalk iface
+ 		 */
+-		atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
++		atalk_route_packet(skb, dev, ddp, len_hops, origlen);
+ 		goto out;
+ 	}
+ 
+@@ -1489,7 +1485,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 		/* Find our address */
+ 		struct atalk_addr *ap = atalk_find_dev_addr(dev);
+ 
+-		if (!ap || skb->len < sizeof(struct ddpshdr))
++		if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
+ 			goto freeit;
+ 
+ 		/* Don't mangle buffer if shared */
+@@ -1519,11 +1515,8 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 		/*
+ 		 * Not sure about this bit...
+ 		 */
+-		ddp->deh_len   = skb->len;
+-		ddp->deh_hops  = DDP_MAXHOPS;	/* Non routable, so force a drop
+-						   if we slip up later */
+-		/* Mend the byte order */
+-		*((__u16 *)ddp) = htons(*((__u16 *)ddp));
++		/* Non routable, so force a drop if we slip up later */
++		ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
+ 	}
+ 	skb->h.raw = skb->data;
+ 
+@@ -1622,16 +1615,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
+ 
+ 	ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
+-	ddp->deh_pad  = 0;
+-	ddp->deh_hops = 0;
+-	ddp->deh_len  = len + sizeof(*ddp);
+-	/*
+-	 * Fix up the length field [Ok this is horrible but otherwise
+-	 * I end up with unions of bit fields and messy bit field order
+-	 * compiler/endian dependencies..
+-	 */
+-	*((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
+-
++	ddp->deh_len_hops  = htons(len + sizeof(*ddp));
+ 	ddp->deh_dnet  = usat->sat_addr.s_net;
+ 	ddp->deh_snet  = at->src_net;
+ 	ddp->deh_dnode = usat->sat_addr.s_node;
+@@ -1712,8 +1696,8 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
+ 	struct ddpehdr *ddp;
+ 	int copied = 0;
++	int offset = 0;
+ 	int err = 0;
+-        struct ddpebits ddphv;
+ 	struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ 						flags & MSG_DONTWAIT, &err);
+ 	if (!skb)
+@@ -1721,25 +1705,18 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 
+ 	/* FIXME: use skb->cb to be able to use shared skbs */
+ 	ddp = ddp_hdr(skb);
+-	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
++	copied = ntohs(ddp->deh_len_hops) & 1023;
+ 
+-	if (sk->sk_type == SOCK_RAW) {
+-		copied = ddphv.deh_len;
+-		if (copied > size) {
+-			copied = size;
+-			msg->msg_flags |= MSG_TRUNC;
+-		}
++	if (sk->sk_type != SOCK_RAW) {
++		offset = sizeof(*ddp);
++		copied -= offset;
++	}
+ 
+-		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+-	} else {
+-		copied = ddphv.deh_len - sizeof(*ddp);
+-		if (copied > size) {
+-			copied = size;
+-			msg->msg_flags |= MSG_TRUNC;
+-		}
+-		err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
+-					      msg->msg_iov, copied);
++	if (copied > size) {
++		copied = size;
++		msg->msg_flags |= MSG_TRUNC;
+ 	}
++	err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
+ 
+ 	if (!err) {
+ 		if (sat) {

Added: dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-length-mismatch.patch
==============================================================================
--- (empty file)
+++ dists/etch-security/linux-2.6/debian/patches/bugfix/appletalk-length-mismatch.patch	Fri Apr  6 20:55:42 2007
@@ -0,0 +1,93 @@
+From: Jean Delvare <jdelvare at suse.de>
+Date: Thu, 5 Apr 2007 06:52:46 +0000 (-0700)
+Subject: [APPLETALK]: Fix a remotely triggerable crash
+X-Git-Tag: v2.6.21-rc6~3
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=75559c167bddc1254db5bcff032ad5eed8bd6f4a
+
+[APPLETALK]: Fix a remotely triggerable crash
+
+When we receive an AppleTalk frame shorter than what its header says,
+we still attempt to verify its checksum, and trip on the BUG_ON() at
+the end of function atalk_sum_skb() because of the length mismatch.
+
+This has security implications because this can be triggered by simply
+sending a specially crafted ethernet frame to a target victim,
+effectively crashing that host. Thus this qualifies, I think, as a
+remote DoS. Here is the frame I used to trigger the crash, in npg
+format:
+
+<Appletalk Killer>
+{
+# Ethernet header -----
+
+  XX XX XX XX XX XX  # Destination MAC
+  00 00 00 00 00 00  # Source MAC
+  00 1D              # Length
+
+# LLC header -----
+
+  AA AA 03
+  08 00 07 80 9B  # Appletalk
+
+# Appletalk header -----
+
+  00 1B        # Packet length (invalid)
+  00 01        # Fake checksum
+  00 00 00 00  # Destination and source networks
+  00 00 00 00  # Destination and source nodes and ports
+
+# Payload -----
+
+  0C 0D 0E 0F 10 11 12 13
+  14
+}
+
+The destination MAC address must be set to those of the victim.
+
+The severity is mitigated by two requirements:
+* The target host must have the appletalk kernel module loaded. I
+  suspect this isn't so frequent.
+* AppleTalk frames are non-IP, thus I guess they can only travel on
+  local networks. I am no network expert though, maybe it is possible
+  to somehow encapsulate AppleTalk packets over IP.
+
+The bug has been reported back in June 2004:
+  http://bugzilla.kernel.org/show_bug.cgi?id=2979
+But it wasn't investigated, and was closed in July 2006 as both
+reporters had vanished meanwhile.
+
+This code was new in kernel 2.6.0-test5:
+  http://git.kernel.org/?p=linux/kernel/git/tglx/history.git;a=commitdiff;h=7ab442d7e0a76402c12553ee256f756097cae2d2
+And not modified since then, so we can assume that vanilla kernels
+2.6.0-test5 and later, and distribution kernels based thereon, are
+affected.
+
+Note that I still do not know for sure what triggered the bug in the
+real-world cases. The frame could have been corrupted by the kernel if
+we have a bug hiding somewhere. But more likely, we are receiving the
+faulty frame from the network.
+
+Signed-off-by: Jean Delvare <jdelvare at suse.de>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index 113c175..c8b7dc2 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -1417,10 +1417,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	/*
+ 	 * Size check to see if ddp->deh_len was crap
+ 	 * (Otherwise we'll detonate most spectacularly
+-	 * in the middle of recvmsg()).
++	 * in the middle of atalk_checksum() or recvmsg()).
+ 	 */
+-	if (skb->len < sizeof(*ddp))
++	if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) {
++		pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, "
++			 "skb->len=%u)\n", len_hops & 1023, skb->len);
+ 		goto freeit;
++	}
+ 
+ 	/*
+ 	 * Any checksums. Note we don't do htons() on this == is assumed to be

Modified: dists/etch-security/linux-2.6/debian/patches/series/12etch1
==============================================================================
--- dists/etch-security/linux-2.6/debian/patches/series/12etch1	(original)
+++ dists/etch-security/linux-2.6/debian/patches/series/12etch1	Fri Apr  6 20:55:42 2007
@@ -1 +1,3 @@
 + bugfix/core-dump-unreadable-PT_INTERP.patch
++ bugfix/appletalk-endianness-annotations.patch
++ bugfix/appletalk-length-mismatch.patch



More information about the Kernel-svn-changes mailing list