Commit f812116b174e59a350acc8e4856213a166a91222

Authored by Willem de Bruijn
Committed by David S. Miller
1 parent 4315ef8d8b

ip: zero sockaddr returned on error queue

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>

Showing 2 changed files with 5 additions and 13 deletions Side-by-side Diff

net/ipv4/ip_sockglue.c
... ... @@ -461,17 +461,13 @@
461 461  
462 462 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
463 463 sin = &errhdr.offender;
464   - sin->sin_family = AF_UNSPEC;
  464 + memset(sin, 0, sizeof(*sin));
465 465  
466 466 if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
467 467 ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) {
468   - struct inet_sock *inet = inet_sk(sk);
469   -
470 468 sin->sin_family = AF_INET;
471 469 sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
472   - sin->sin_port = 0;
473   - memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
474   - if (inet->cmsg_flags)
  470 + if (inet_sk(sk)->cmsg_flags)
475 471 ip_cmsg_recv(msg, skb);
476 472 }
477 473  
... ... @@ -393,11 +393,10 @@
393 393  
394 394 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
395 395 sin = &errhdr.offender;
396   - sin->sin6_family = AF_UNSPEC;
  396 + memset(sin, 0, sizeof(*sin));
  397 +
397 398 if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
398 399 sin->sin6_family = AF_INET6;
399   - sin->sin6_flowinfo = 0;
400   - sin->sin6_port = 0;
401 400 if (np->rxopt.all) {
402 401 if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP &&
403 402 serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6)
404 403  
... ... @@ -412,12 +411,9 @@
412 411 ipv6_iface_scope_id(&sin->sin6_addr,
413 412 IP6CB(skb)->iif);
414 413 } else {
415   - struct inet_sock *inet = inet_sk(sk);
416   -
417 414 ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
418 415 &sin->sin6_addr);
419   - sin->sin6_scope_id = 0;
420   - if (inet->cmsg_flags)
  416 + if (inet_sk(sk)->cmsg_flags)
421 417 ip_cmsg_recv(msg, skb);
422 418 }
423 419 }