[kernel/f19] CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887)

Josh Boyer jwboyer at fedoraproject.org
Sat Nov 30 19:12:57 UTC 2013


commit 0273faa5e460494f9722e59e8b81f324f1010966
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date:   Sat Nov 30 13:35:27 2013 -0500

    CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887)

 ...gnment-in-recv_error-and-rxpmtu-functions.patch |  253 +++++++++++++++++++
 ...t-leakage-of-uninitialized-memory-to-user.patch |  256 ++++++++++++++++++++
 kernel.spec                                        |   11 +
 3 files changed, 520 insertions(+), 0 deletions(-)
---
diff --git a/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch b/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch
new file mode 100644
index 0000000..b76fd2a
--- /dev/null
+++ b/inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch
@@ -0,0 +1,253 @@
+Bugzilla: 1035887
+Upstream-status: 3.13
+
+From 4be402ba6158068d53ab0268f1affa9d82dae2ec Mon Sep 17 00:00:00 2001
+From: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Date: Fri, 22 Nov 2013 23:46:12 +0000
+Subject: [PATCH] inet: fix addr_len/msg->msg_namelen assignment in recv_error
+ and rxpmtu functions
+
+Commit bceaa90240b6019ed73b49965eac7d167610be69 ("inet: prevent leakage
+of uninitialized memory to user in recv syscalls") conditionally updated
+addr_len if the msg_name is written to. The recv_error and rxpmtu
+functions relied on the recvmsg functions to set up addr_len before.
+
+As this does not happen any more we have to pass addr_len to those
+functions as well and set it to the size of the corresponding sockaddr
+length.
+
+This broke traceroute and such.
+
+Fixes: bceaa90240b6 ("inet: prevent leakage of uninitialized memory to user in recv syscalls")
+Reported-by: Brad Spengler <spender at grsecurity.net>
+Reported-by: Tom Labanowski
+Cc: mpb <mpb.mail at gmail.com>
+Cc: David S. Miller <davem at davemloft.net>
+Cc: Eric Dumazet <eric.dumazet at gmail.com>
+Signed-off-by: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/net/ip.h       | 2 +-
+ include/net/ipv6.h     | 4 ++--
+ include/net/ping.h     | 3 ++-
+ net/ipv4/ip_sockglue.c | 3 ++-
+ net/ipv4/ping.c        | 5 +++--
+ net/ipv4/raw.c         | 2 +-
+ net/ipv4/udp.c         | 2 +-
+ net/ipv6/datagram.c    | 7 +++++--
+ net/ipv6/ping.c        | 3 ++-
+ net/ipv6/raw.c         | 4 ++--
+ net/ipv6/udp.c         | 4 ++--
+ net/l2tp/l2tp_ip6.c    | 2 +-
+ 12 files changed, 24 insertions(+), 17 deletions(-)
+
+diff --git a/include/net/ip.h b/include/net/ip.h
+index 5e52688..301f10c 100644
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -464,7 +464,7 @@ extern int	compat_ip_getsockopt(struct sock *sk, int level,
+ 			int optname, char __user *optval, int __user *optlen);
+ extern int	ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
+ 
+-extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
++extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
+ extern void	ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+ 			      __be16 port, u32 info, u8 *payload);
+ extern void	ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index bbf1c8f..5529d79 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -802,8 +802,8 @@ extern int			compat_ipv6_getsockopt(struct sock *sk,
+ extern int			ip6_datagram_connect(struct sock *sk, 
+ 						     struct sockaddr *addr, int addr_len);
+ 
+-extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+-extern int 			ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
++extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
++extern int 			ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
+ extern void			ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
+ 						u32 info, u8 *payload);
+ extern void			ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
+diff --git a/include/net/ping.h b/include/net/ping.h
+index 5db0224..2b496e9 100644
+--- a/include/net/ping.h
++++ b/include/net/ping.h
+@@ -31,7 +31,8 @@
+ 
+ /* Compatibility glue so we can support IPv6 when it's compiled as a module */
+ struct pingv6_ops {
+-	int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
++	int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len,
++			       int *addr_len);
+ 	int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
+ 				     struct sk_buff *skb);
+ 	int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index d9c4f11..23e6ab0 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
+ /*
+  *	Handle MSG_ERRQUEUE
+  */
+-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
++int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
+ {
+ 	struct sock_exterr_skb *serr;
+ 	struct sk_buff *skb, *skb2;
+@@ -405,6 +405,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+ 						   serr->addr_offset);
+ 		sin->sin_port = serr->port;
+ 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
++		*addr_len = sizeof(*sin);
+ 	}
+ 
+ 	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
+index 92fb6ff..ac31877 100644
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -838,10 +838,11 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 
+ 	if (flags & MSG_ERRQUEUE) {
+ 		if (family == AF_INET) {
+-			return ip_recv_error(sk, msg, len);
++			return ip_recv_error(sk, msg, len, addr_len);
+ #if IS_ENABLED(CONFIG_IPV6)
+ 		} else if (family == AF_INET6) {
+-			return pingv6_ops.ipv6_recv_error(sk, msg, len);
++			return pingv6_ops.ipv6_recv_error(sk, msg, len,
++							  addr_len);
+ #endif
+ 		}
+ 	}
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index ca4c3f1..7d3db78 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -695,7 +695,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 		goto out;
+ 
+ 	if (flags & MSG_ERRQUEUE) {
+-		err = ip_recv_error(sk, msg, len);
++		err = ip_recv_error(sk, msg, len, addr_len);
+ 		goto out;
+ 	}
+ 
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index a7003de..1ef8794 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1210,7 +1210,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	bool slow;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+-		return ip_recv_error(sk, msg, len);
++		return ip_recv_error(sk, msg, len, addr_len);
+ 
+ try_again:
+ 	skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
+diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
+index 48b6bd2..7a0fd80 100644
+--- a/net/ipv6/datagram.c
++++ b/net/ipv6/datagram.c
+@@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
+ /*
+  *	Handle MSG_ERRQUEUE
+  */
+-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
++int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct sock_exterr_skb *serr;
+@@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+ 					       &sin->sin6_addr);
+ 			sin->sin6_scope_id = 0;
+ 		}
++		*addr_len = sizeof(*sin);
+ 	}
+ 
+ 	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
+@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
+ /*
+  *	Handle IPV6_RECVPATHMTU
+  */
+-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
++int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
++		     int *addr_len)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct sk_buff *skb;
+@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
+ 		sin->sin6_port = 0;
+ 		sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
+ 		sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
++		*addr_len = sizeof(*sin);
+ 	}
+ 
+ 	put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
+diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
+index 18f19df..7856e96 100644
+--- a/net/ipv6/ping.c
++++ b/net/ipv6/ping.c
+@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = {
+ 
+ 
+ /* Compatibility glue so we can support IPv6 when it's compiled as a module */
+-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
++static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
++				 int *addr_len)
+ {
+ 	return -EAFNOSUPPORT;
+ }
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index 2f303bf..430067c 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -467,10 +467,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 		return -EOPNOTSUPP;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+-		return ipv6_recv_error(sk, msg, len);
++		return ipv6_recv_error(sk, msg, len, addr_len);
+ 
+ 	if (np->rxpmtu && np->rxopt.bits.rxpmtu)
+-		return ipv6_recv_rxpmtu(sk, msg, len);
++		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
+ 
+ 	skb = skb_recv_datagram(sk, flags, noblock, &err);
+ 	if (!skb)
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index a59beed..3d2758d 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -375,10 +375,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 	bool slow;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+-		return ipv6_recv_error(sk, msg, len);
++		return ipv6_recv_error(sk, msg, len, addr_len);
+ 
+ 	if (np->rxpmtu && np->rxopt.bits.rxpmtu)
+-		return ipv6_recv_rxpmtu(sk, msg, len);
++		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
+ 
+ try_again:
+ 	skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
+index b8a6039..e6e8408 100644
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -665,7 +665,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 		*addr_len = sizeof(*lsa);
+ 
+ 	if (flags & MSG_ERRQUEUE)
+-		return ipv6_recv_error(sk, msg, len);
++		return ipv6_recv_error(sk, msg, len, addr_len);
+ 
+ 	skb = skb_recv_datagram(sk, flags, noblock, &err);
+ 	if (!skb)
+-- 
+1.8.3.1
+
diff --git a/inet-prevent-leakage-of-uninitialized-memory-to-user.patch b/inet-prevent-leakage-of-uninitialized-memory-to-user.patch
new file mode 100644
index 0000000..c5b9411
--- /dev/null
+++ b/inet-prevent-leakage-of-uninitialized-memory-to-user.patch
@@ -0,0 +1,256 @@
+Bugzilla: 1035887
+Upstream-status: 3.13
+
+From bceaa90240b6019ed73b49965eac7d167610be69 Mon Sep 17 00:00:00 2001
+From: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Date: Mon, 18 Nov 2013 04:20:45 +0100
+Subject: [PATCH] inet: prevent leakage of uninitialized memory to user in recv
+ syscalls
+
+Only update *addr_len when we actually fill in sockaddr, otherwise we
+can return uninitialized memory from the stack to the caller in the
+recvfrom, recvmmsg and recvmsg syscalls. Drop the the (addr_len == NULL)
+checks because we only get called with a valid addr_len pointer either
+from sock_common_recvmsg or inet_recvmsg.
+
+If a blocking read waits on a socket which is concurrently shut down we
+now return zero and set msg_msgnamelen to 0.
+
+Reported-by: mpb <mpb.mail at gmail.com>
+Suggested-by: Eric Dumazet <eric.dumazet at gmail.com>
+Signed-off-by: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/ieee802154/dgram.c |  3 +--
+ net/ipv4/ping.c        | 19 +++++++------------
+ net/ipv4/raw.c         |  4 +---
+ net/ipv4/udp.c         |  7 +------
+ net/ipv6/raw.c         |  4 +---
+ net/ipv6/udp.c         |  5 +----
+ net/l2tp/l2tp_ip.c     |  4 +---
+ net/phonet/datagram.c  |  9 ++++-----
+ 8 files changed, 17 insertions(+), 38 deletions(-)
+
+diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
+index 581a595..1865fdf 100644
+--- a/net/ieee802154/dgram.c
++++ b/net/ieee802154/dgram.c
+@@ -315,9 +315,8 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 	if (saddr) {
+ 		saddr->family = AF_IEEE802154;
+ 		saddr->addr = mac_cb(skb)->sa;
+-	}
+-	if (addr_len)
+ 		*addr_len = sizeof(*saddr);
++	}
+ 
+ 	if (flags & MSG_TRUNC)
+ 		copied = skb->len;
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
+index 9afbdb1..aacefa0 100644
+--- a/net/ipv4/ping.c
++++ b/net/ipv4/ping.c
+@@ -830,8 +830,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ {
+ 	struct inet_sock *isk = inet_sk(sk);
+ 	int family = sk->sk_family;
+-	struct sockaddr_in *sin;
+-	struct sockaddr_in6 *sin6;
+ 	struct sk_buff *skb;
+ 	int copied, err;
+ 
+@@ -841,13 +839,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	if (flags & MSG_OOB)
+ 		goto out;
+ 
+-	if (addr_len) {
+-		if (family == AF_INET)
+-			*addr_len = sizeof(*sin);
+-		else if (family == AF_INET6 && addr_len)
+-			*addr_len = sizeof(*sin6);
+-	}
+-
+ 	if (flags & MSG_ERRQUEUE) {
+ 		if (family == AF_INET) {
+ 			return ip_recv_error(sk, msg, len);
+@@ -877,11 +868,13 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 
+ 	/* Copy the address and add cmsg data. */
+ 	if (family == AF_INET) {
+-		sin = (struct sockaddr_in *) msg->msg_name;
++		struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
++
+ 		sin->sin_family = AF_INET;
+ 		sin->sin_port = 0 /* skb->h.uh->source */;
+ 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
+ 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
++		*addr_len = sizeof(*sin);
+ 
+ 		if (isk->cmsg_flags)
+ 			ip_cmsg_recv(msg, skb);
+@@ -890,17 +883,19 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	} else if (family == AF_INET6) {
+ 		struct ipv6_pinfo *np = inet6_sk(sk);
+ 		struct ipv6hdr *ip6 = ipv6_hdr(skb);
+-		sin6 = (struct sockaddr_in6 *) msg->msg_name;
++		struct sockaddr_in6 *sin6 =
++			(struct sockaddr_in6 *)msg->msg_name;
++
+ 		sin6->sin6_family = AF_INET6;
+ 		sin6->sin6_port = 0;
+ 		sin6->sin6_addr = ip6->saddr;
+-
+ 		sin6->sin6_flowinfo = 0;
+ 		if (np->sndflow)
+ 			sin6->sin6_flowinfo = ip6_flowinfo(ip6);
+ 
+ 		sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+ 							  IP6CB(skb)->iif);
++		*addr_len = sizeof(*sin6);
+ 
+ 		if (inet6_sk(sk)->rxopt.all)
+ 			pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb);
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index 41e1d28..5cb8ddb 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -696,9 +696,6 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	if (flags & MSG_OOB)
+ 		goto out;
+ 
+-	if (addr_len)
+-		*addr_len = sizeof(*sin);
+-
+ 	if (flags & MSG_ERRQUEUE) {
+ 		err = ip_recv_error(sk, msg, len);
+ 		goto out;
+@@ -726,6 +723,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
+ 		sin->sin_port = 0;
+ 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
++		*addr_len = sizeof(*sin);
+ 	}
+ 	if (inet->cmsg_flags)
+ 		ip_cmsg_recv(msg, skb);
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 89909dd..998431c 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1235,12 +1235,6 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	int is_udplite = IS_UDPLITE(sk);
+ 	bool slow;
+ 
+-	/*
+-	 *	Check any passed addresses
+-	 */
+-	if (addr_len)
+-		*addr_len = sizeof(*sin);
+-
+ 	if (flags & MSG_ERRQUEUE)
+ 		return ip_recv_error(sk, msg, len);
+ 
+@@ -1302,6 +1296,7 @@ try_again:
+ 		sin->sin_port = udp_hdr(skb)->source;
+ 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
+ 		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
++		*addr_len = sizeof(*sin);
+ 	}
+ 	if (inet->cmsg_flags)
+ 		ip_cmsg_recv(msg, skb);
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index 3c00842..e24ff1d 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -465,9 +465,6 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 	if (flags & MSG_OOB)
+ 		return -EOPNOTSUPP;
+ 
+-	if (addr_len)
+-		*addr_len=sizeof(*sin6);
+-
+ 	if (flags & MSG_ERRQUEUE)
+ 		return ipv6_recv_error(sk, msg, len);
+ 
+@@ -506,6 +503,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 		sin6->sin6_flowinfo = 0;
+ 		sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,
+ 							  IP6CB(skb)->iif);
++		*addr_len = sizeof(*sin6);
+ 	}
+ 
+ 	sock_recv_ts_and_drops(msg, sk, skb);
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index f3893e8..81eb8cf 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -392,9 +392,6 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 	int is_udp4;
+ 	bool slow;
+ 
+-	if (addr_len)
+-		*addr_len = sizeof(struct sockaddr_in6);
+-
+ 	if (flags & MSG_ERRQUEUE)
+ 		return ipv6_recv_error(sk, msg, len);
+ 
+@@ -480,7 +477,7 @@ try_again:
+ 				ipv6_iface_scope_id(&sin6->sin6_addr,
+ 						    IP6CB(skb)->iif);
+ 		}
+-
++		*addr_len = sizeof(*sin6);
+ 	}
+ 	if (is_udp4) {
+ 		if (inet->cmsg_flags)
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
+index 571db8d..da1a1ce 100644
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -518,9 +518,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
+ 	if (flags & MSG_OOB)
+ 		goto out;
+ 
+-	if (addr_len)
+-		*addr_len = sizeof(*sin);
+-
+ 	skb = skb_recv_datagram(sk, flags, noblock, &err);
+ 	if (!skb)
+ 		goto out;
+@@ -543,6 +540,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
+ 		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
+ 		sin->sin_port = 0;
+ 		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
++		*addr_len = sizeof(*sin);
+ 	}
+ 	if (inet->cmsg_flags)
+ 		ip_cmsg_recv(msg, skb);
+diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
+index 12c30f3..38946b2 100644
+--- a/net/phonet/datagram.c
++++ b/net/phonet/datagram.c
+@@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 			MSG_CMSG_COMPAT))
+ 		goto out_nofree;
+ 
+-	if (addr_len)
+-		*addr_len = sizeof(sa);
+-
+ 	skb = skb_recv_datagram(sk, flags, noblock, &rval);
+ 	if (skb == NULL)
+ 		goto out_nofree;
+@@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
+ 
+ 	rval = (flags & MSG_TRUNC) ? skb->len : copylen;
+ 
+-	if (msg->msg_name != NULL)
+-		memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn));
++	if (msg->msg_name != NULL) {
++		memcpy(msg->msg_name, &sa, sizeof(sa));
++		*addr_len = sizeof(sa);
++	}
+ 
+ out:
+ 	skb_free_datagram(sk, skb);
+-- 
+1.8.3.1
+
diff --git a/kernel.spec b/kernel.spec
index 0c22f71..523f95a 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -809,6 +809,10 @@ Patch25158: via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch
 #rhbz 998342
 Patch25159: usbnet-fix-status-interrupt-urb-handling.patch
 
+#CVE-2013-6405 rhbz 1035875 1035887
+Patch25161: inet-prevent-leakage-of-uninitialized-memory-to-user.patch
+Patch25162: inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1566,6 +1570,10 @@ ApplyPatch via-velocity-fix-netif_receive_skb-use-in-irq-disable.patch
 #rhbz 998342
 ApplyPatch usbnet-fix-status-interrupt-urb-handling.patch
 
+#CVE-2013-6405 rhbz 1035875 1035887
+ApplyPatch inet-prevent-leakage-of-uninitialized-memory-to-user.patch
+ApplyPatch inet-fix-addr_len-msg_namelen-assignment-in-recv_error-and-rxpmtu-functions.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2378,6 +2386,9 @@ fi
 # and build.
 
 %changelog
+* Sat Nov 30 2013 Josh Boyer <jwboyer at fedoraproject.org>
+- CVE-2013-6405 net: leak of uninited mem to userspace via recv syscalls (rhbz 1035875 1035887)
+
 * Fri Nov 29 2013 Josh Boyer <jwboyer at fedoraproject.org> - 3.11.10-200
 - Linux v3.11.10
 - Fix memory leak in qxl (from Dave Airlie)


More information about the scm-commits mailing list