| From foo@baz Thu Dec 5 16:16:39 PST 2013 |
| From: Hannes Frederic Sowa <hannes@stressinduktion.org> |
| Date: Mon, 18 Nov 2013 07:07:45 +0100 |
| Subject: ping: prevent NULL pointer dereference on write to msg_name |
| |
| From: Hannes Frederic Sowa <hannes@stressinduktion.org> |
| |
| [ Upstream commit cf970c002d270c36202bd5b9c2804d3097a52da0 ] |
| |
| A plain read() on a socket does set msg->msg_name to NULL. So check for |
| NULL pointer first. |
| |
| Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/ping.c | 34 +++++++++++++++++++--------------- |
| 1 file changed, 19 insertions(+), 15 deletions(-) |
| |
| --- a/net/ipv4/ping.c |
| +++ b/net/ipv4/ping.c |
| @@ -867,11 +867,13 @@ int ping_recvmsg(struct kiocb *iocb, str |
| if (family == AF_INET) { |
| 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 (sin) { |
| + 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); |
| @@ -883,16 +885,18 @@ int ping_recvmsg(struct kiocb *iocb, str |
| 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 (sin6) { |
| + 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); |