diff options
author | Steffen Hurrle <steffen@hurrle.net> | 2014-01-17 16:53:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-19 02:04:16 -0500 |
commit | 342dfc306fb32155314dad277f3c3686b83fb9f1 (patch) | |
tree | a0d220f9310725c72bac70945261c9282e7cf305 /net/ipv6 | |
parent | ea02f9411d9faa3553ed09ce0ec9f00ceae9885e (diff) |
net: add build-time checks for msg->msg_name size
This is a follow-up patch to f3d3342602f8bc ("net: rework recvmsg
handler msg_name and msg_namelen logic").
DECLARE_SOCKADDR validates that the structure we use for writing the
name information to is not larger than the buffer which is reserved
for msg->msg_name (which is 128 bytes). Also use DECLARE_SOCKADDR
consistently in sendmsg code paths.
Signed-off-by: Steffen Hurrle <steffen@hurrle.net>
Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/datagram.c | 6 | ||||
-rw-r--r-- | net/ipv6/ping.c | 2 | ||||
-rw-r--r-- | net/ipv6/raw.c | 4 | ||||
-rw-r--r-- | net/ipv6/udp.c | 6 |
4 files changed, 7 insertions, 11 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 6983058942ea..bce73cbd203a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -322,7 +322,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
322 | struct ipv6_pinfo *np = inet6_sk(sk); | 322 | struct ipv6_pinfo *np = inet6_sk(sk); |
323 | struct sock_exterr_skb *serr; | 323 | struct sock_exterr_skb *serr; |
324 | struct sk_buff *skb, *skb2; | 324 | struct sk_buff *skb, *skb2; |
325 | struct sockaddr_in6 *sin; | 325 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin, msg->msg_name); |
326 | struct { | 326 | struct { |
327 | struct sock_extended_err ee; | 327 | struct sock_extended_err ee; |
328 | struct sockaddr_in6 offender; | 328 | struct sockaddr_in6 offender; |
@@ -348,7 +348,6 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
348 | 348 | ||
349 | serr = SKB_EXT_ERR(skb); | 349 | serr = SKB_EXT_ERR(skb); |
350 | 350 | ||
351 | sin = (struct sockaddr_in6 *)msg->msg_name; | ||
352 | if (sin) { | 351 | if (sin) { |
353 | const unsigned char *nh = skb_network_header(skb); | 352 | const unsigned char *nh = skb_network_header(skb); |
354 | sin->sin6_family = AF_INET6; | 353 | sin->sin6_family = AF_INET6; |
@@ -429,8 +428,8 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, | |||
429 | { | 428 | { |
430 | struct ipv6_pinfo *np = inet6_sk(sk); | 429 | struct ipv6_pinfo *np = inet6_sk(sk); |
431 | struct sk_buff *skb; | 430 | struct sk_buff *skb; |
432 | struct sockaddr_in6 *sin; | ||
433 | struct ip6_mtuinfo mtu_info; | 431 | struct ip6_mtuinfo mtu_info; |
432 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin, msg->msg_name); | ||
434 | int err; | 433 | int err; |
435 | int copied; | 434 | int copied; |
436 | 435 | ||
@@ -452,7 +451,6 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, | |||
452 | 451 | ||
453 | memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info)); | 452 | memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info)); |
454 | 453 | ||
455 | sin = (struct sockaddr_in6 *)msg->msg_name; | ||
456 | if (sin) { | 454 | if (sin) { |
457 | sin->sin6_family = AF_INET6; | 455 | sin->sin6_family = AF_INET6; |
458 | sin->sin6_flowinfo = 0; | 456 | sin->sin6_flowinfo = 0; |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 15d23b8c2129..cd71f3a540be 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
@@ -103,7 +103,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
103 | return err; | 103 | return err; |
104 | 104 | ||
105 | if (msg->msg_name) { | 105 | if (msg->msg_name) { |
106 | struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; | 106 | DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name); |
107 | if (msg->msg_namelen < sizeof(struct sockaddr_in6) || | 107 | if (msg->msg_namelen < sizeof(struct sockaddr_in6) || |
108 | u->sin6_family != AF_INET6) { | 108 | u->sin6_family != AF_INET6) { |
109 | return -EINVAL; | 109 | return -EINVAL; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5f10b7ea7ccc..b4523117aeae 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -457,7 +457,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
457 | int noblock, int flags, int *addr_len) | 457 | int noblock, int flags, int *addr_len) |
458 | { | 458 | { |
459 | struct ipv6_pinfo *np = inet6_sk(sk); | 459 | struct ipv6_pinfo *np = inet6_sk(sk); |
460 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)msg->msg_name; | 460 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
461 | struct sk_buff *skb; | 461 | struct sk_buff *skb; |
462 | size_t copied; | 462 | size_t copied; |
463 | int err; | 463 | int err; |
@@ -734,7 +734,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
734 | struct msghdr *msg, size_t len) | 734 | struct msghdr *msg, size_t len) |
735 | { | 735 | { |
736 | struct ipv6_txoptions opt_space; | 736 | struct ipv6_txoptions opt_space; |
737 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 737 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
738 | struct in6_addr *daddr, *final_p, final; | 738 | struct in6_addr *daddr, *final_p, final; |
739 | struct inet_sock *inet = inet_sk(sk); | 739 | struct inet_sock *inet = inet_sk(sk); |
740 | struct ipv6_pinfo *np = inet6_sk(sk); | 740 | struct ipv6_pinfo *np = inet6_sk(sk); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fa9d988f4012..233c3ab6aee4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -460,9 +460,7 @@ try_again: | |||
460 | 460 | ||
461 | /* Copy the address. */ | 461 | /* Copy the address. */ |
462 | if (msg->msg_name) { | 462 | if (msg->msg_name) { |
463 | struct sockaddr_in6 *sin6; | 463 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
464 | |||
465 | sin6 = (struct sockaddr_in6 *) msg->msg_name; | ||
466 | sin6->sin6_family = AF_INET6; | 464 | sin6->sin6_family = AF_INET6; |
467 | sin6->sin6_port = udp_hdr(skb)->source; | 465 | sin6->sin6_port = udp_hdr(skb)->source; |
468 | sin6->sin6_flowinfo = 0; | 466 | sin6->sin6_flowinfo = 0; |
@@ -1041,7 +1039,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1041 | struct udp_sock *up = udp_sk(sk); | 1039 | struct udp_sock *up = udp_sk(sk); |
1042 | struct inet_sock *inet = inet_sk(sk); | 1040 | struct inet_sock *inet = inet_sk(sk); |
1043 | struct ipv6_pinfo *np = inet6_sk(sk); | 1041 | struct ipv6_pinfo *np = inet6_sk(sk); |
1044 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; | 1042 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
1045 | struct in6_addr *daddr, *final_p, final; | 1043 | struct in6_addr *daddr, *final_p, final; |
1046 | struct ipv6_txoptions *opt = NULL; | 1044 | struct ipv6_txoptions *opt = NULL; |
1047 | struct ip6_flowlabel *flowlabel = NULL; | 1045 | struct ip6_flowlabel *flowlabel = NULL; |