[kernel/stabilization] 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:13:07 UTC 2013
commit 1adede449e46945c585aaa0eafaa8775e5bf9a7d
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 80cbe67..dde8113 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -758,6 +758,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
@@ -1484,6 +1488,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
@@ -2287,6 +2295,9 @@ fi
# ||----w |
# || ||
%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>
- Linux v3.12.2
- Fix memory leak in qxl (from Dave Airlie)
More information about the scm-commits
mailing list