Commit 8e9f6bdb35ae63a83ab8d0338eb13d72d596aba5
Committed by
Greg Kroah-Hartman
1 parent
a17f9bf1f7
ip: zero sockaddr returned on error queue
[ Upstream commit f812116b174e59a350acc8e4856213a166a91222 ] The sockaddr is returned in IP(V6)_RECVERR as part of errhdr. That structure is defined and allocated on the stack as struct { struct sock_extended_err ee; struct sockaddr_in(6) offender; } errhdr; The second part is only initialized for certain SO_EE_ORIGIN values. Always initialize it completely. An MTU exceeded error on a SOCK_RAW/IPPROTO_RAW is one example that would return uninitialized bytes. Signed-off-by: Willem de Bruijn <willemb@google.com> ---- Also verified that there is no padding between errhdr.ee and errhdr.offender that could leak additional kernel data. Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 2 changed files with 5 additions and 13 deletions Side-by-side Diff
net/ipv4/ip_sockglue.c
... | ... | @@ -443,15 +443,11 @@ |
443 | 443 | |
444 | 444 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
445 | 445 | sin = &errhdr.offender; |
446 | - sin->sin_family = AF_UNSPEC; | |
446 | + memset(sin, 0, sizeof(*sin)); | |
447 | 447 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) { |
448 | - struct inet_sock *inet = inet_sk(sk); | |
449 | - | |
450 | 448 | sin->sin_family = AF_INET; |
451 | 449 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
452 | - sin->sin_port = 0; | |
453 | - memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | |
454 | - if (inet->cmsg_flags) | |
450 | + if (inet_sk(sk)->cmsg_flags) | |
455 | 451 | ip_cmsg_recv(msg, skb); |
456 | 452 | } |
457 | 453 |
net/ipv6/datagram.c
... | ... | @@ -383,11 +383,10 @@ |
383 | 383 | |
384 | 384 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
385 | 385 | sin = &errhdr.offender; |
386 | - sin->sin6_family = AF_UNSPEC; | |
386 | + memset(sin, 0, sizeof(*sin)); | |
387 | + | |
387 | 388 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
388 | 389 | sin->sin6_family = AF_INET6; |
389 | - sin->sin6_flowinfo = 0; | |
390 | - sin->sin6_port = 0; | |
391 | 390 | if (np->rxopt.all) |
392 | 391 | ip6_datagram_recv_common_ctl(sk, msg, skb); |
393 | 392 | if (skb->protocol == htons(ETH_P_IPV6)) { |
394 | 393 | |
... | ... | @@ -398,12 +397,9 @@ |
398 | 397 | ipv6_iface_scope_id(&sin->sin6_addr, |
399 | 398 | IP6CB(skb)->iif); |
400 | 399 | } else { |
401 | - struct inet_sock *inet = inet_sk(sk); | |
402 | - | |
403 | 400 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
404 | 401 | &sin->sin6_addr); |
405 | - sin->sin6_scope_id = 0; | |
406 | - if (inet->cmsg_flags) | |
402 | + if (inet_sk(sk)->cmsg_flags) | |
407 | 403 | ip_cmsg_recv(msg, skb); |
408 | 404 | } |
409 | 405 | } |