Commit 8e9f6bdb35ae63a83ab8d0338eb13d72d596aba5

Authored by Willem de Bruijn
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  
... ... @@ -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 }