diff options
author | Willem de Bruijn <willemb@google.com> | 2015-01-15 13:18:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-15 19:41:16 -0500 |
commit | f812116b174e59a350acc8e4856213a166a91222 (patch) | |
tree | 9be0fd580d75289fec240cae10ab8ffcc6c85ed2 /net | |
parent | 4315ef8d8b2e90e093a52ad31074dd0dafbed654 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ip_sockglue.c | 8 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 10 |
2 files changed, 5 insertions, 13 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 8a89c738b7a3..6b85adb05003 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -461,17 +461,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
461 | 461 | ||
462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
463 | sin = &errhdr.offender; | 463 | sin = &errhdr.offender; |
464 | sin->sin_family = AF_UNSPEC; | 464 | memset(sin, 0, sizeof(*sin)); |
465 | 465 | ||
466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || |
467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { | 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { |
468 | struct inet_sock *inet = inet_sk(sk); | ||
469 | |||
470 | sin->sin_family = AF_INET; | 468 | sin->sin_family = AF_INET; |
471 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 469 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
472 | sin->sin_port = 0; | 470 | if (inet_sk(sk)->cmsg_flags) |
473 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
474 | if (inet->cmsg_flags) | ||
475 | ip_cmsg_recv(msg, skb); | 471 | ip_cmsg_recv(msg, skb); |
476 | } | 472 | } |
477 | 473 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 100c589a2a6c..49f5e73db122 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
393 | 393 | ||
394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
395 | sin = &errhdr.offender; | 395 | sin = &errhdr.offender; |
396 | sin->sin6_family = AF_UNSPEC; | 396 | memset(sin, 0, sizeof(*sin)); |
397 | |||
397 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 398 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
398 | sin->sin6_family = AF_INET6; | 399 | sin->sin6_family = AF_INET6; |
399 | sin->sin6_flowinfo = 0; | ||
400 | sin->sin6_port = 0; | ||
401 | if (np->rxopt.all) { | 400 | if (np->rxopt.all) { |
402 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && | 401 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && |
403 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) | 402 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) |
@@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
412 | ipv6_iface_scope_id(&sin->sin6_addr, | 411 | ipv6_iface_scope_id(&sin->sin6_addr, |
413 | IP6CB(skb)->iif); | 412 | IP6CB(skb)->iif); |
414 | } else { | 413 | } else { |
415 | struct inet_sock *inet = inet_sk(sk); | ||
416 | |||
417 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 414 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
418 | &sin->sin6_addr); | 415 | &sin->sin6_addr); |
419 | sin->sin6_scope_id = 0; | 416 | if (inet_sk(sk)->cmsg_flags) |
420 | if (inet->cmsg_flags) | ||
421 | ip_cmsg_recv(msg, skb); | 417 | ip_cmsg_recv(msg, skb); |
422 | } | 418 | } |
423 | } | 419 | } |