aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-26 16:52:25 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-26 16:52:25 +0100
commit1361aa2e2d80cb144b4158722de3c913855e6002 (patch)
tree6fddc0669c8032c4381ba6ba1a32cc407670d905
parent57be1eefab8494efd96bcec0f54a84cef3f61e95 (diff)
downloadbusybox-w32-1361aa2e2d80cb144b4158722de3c913855e6002.tar.gz
busybox-w32-1361aa2e2d80cb144b4158722de3c913855e6002.tar.bz2
busybox-w32-1361aa2e2d80cb144b4158722de3c913855e6002.zip
udp_io: fix two more potential cases of unaligned accesses. 0 code size changes.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libbb/udp_io.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/libbb/udp_io.c b/libbb/udp_io.c
index b31f28416..d9375eac2 100644
--- a/libbb/udp_io.c
+++ b/libbb/udp_io.c
@@ -6,7 +6,6 @@
6 * 6 *
7 * Licensed under GPL version 2, see file LICENSE in this tarball for details. 7 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
8 */ 8 */
9
10#include "libbb.h" 9#include "libbb.h"
11 10
12/* 11/*
@@ -32,22 +31,23 @@ send_to_from(int fd, void *buf, size_t len, int flags,
32 socklen_t tolen) 31 socklen_t tolen)
33{ 32{
34#ifndef IP_PKTINFO 33#ifndef IP_PKTINFO
34 (void)from; /* suppress "unused from" warning */
35 return sendto(fd, buf, len, flags, to, tolen); 35 return sendto(fd, buf, len, flags, to, tolen);
36#else 36#else
37 struct iovec iov[1]; 37 struct iovec iov[1];
38 struct msghdr msg; 38 struct msghdr msg;
39 union { 39 union {
40 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; 40 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
41#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) 41# if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
42 char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 42 char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
43#endif 43# endif
44 } u; 44 } u;
45 struct cmsghdr* cmsgptr; 45 struct cmsghdr* cmsgptr;
46 46
47 if (from->sa_family != AF_INET 47 if (from->sa_family != AF_INET
48#if ENABLE_FEATURE_IPV6 48# if ENABLE_FEATURE_IPV6
49 && from->sa_family != AF_INET6 49 && from->sa_family != AF_INET6
50#endif 50# endif
51 ) { 51 ) {
52 /* ANY local address */ 52 /* ANY local address */
53 return sendto(fd, buf, len, flags, to, tolen); 53 return sendto(fd, buf, len, flags, to, tolen);
@@ -76,20 +76,26 @@ send_to_from(int fd, void *buf, size_t len, int flags,
76 cmsgptr->cmsg_type = IP_PKTINFO; 76 cmsgptr->cmsg_type = IP_PKTINFO;
77 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 77 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
78 pktptr = (struct in_pktinfo *)(CMSG_DATA(cmsgptr)); 78 pktptr = (struct in_pktinfo *)(CMSG_DATA(cmsgptr));
79 /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */ 79 /*pktptr->ipi_ifindex = 0; -- already done by memset(u...) */
80 /* In general, CMSG_DATA() can be unaligned, but in this case
81 * we know for sure it is sufficiently aligned:
82 * CMSG_FIRSTHDR simply returns &u above,
83 * and CMSG_DATA returns &u + size_t + int + int.
84 * Thus direct assignment is ok:
85 */
80 pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; 86 pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr;
81 } 87 }
82#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) 88# if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
83 else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { 89 else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
84 struct in6_pktinfo *pktptr; 90 struct in6_pktinfo *pktptr;
85 cmsgptr->cmsg_level = IPPROTO_IPV6; 91 cmsgptr->cmsg_level = IPPROTO_IPV6;
86 cmsgptr->cmsg_type = IPV6_PKTINFO; 92 cmsgptr->cmsg_type = IPV6_PKTINFO;
87 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 93 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
88 pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr)); 94 pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr));
89 /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */ 95 /* pktptr->ipi6_ifindex = 0; -- already done by memset(u...) */
90 pktptr->ipi6_addr = ((struct sockaddr_in6*)from)->sin6_addr; 96 pktptr->ipi6_addr = ((struct sockaddr_in6*)from)->sin6_addr;
91 } 97 }
92#endif 98# endif
93 msg.msg_controllen = cmsgptr->cmsg_len; 99 msg.msg_controllen = cmsgptr->cmsg_len;
94 100
95 return sendmsg(fd, &msg, flags); 101 return sendmsg(fd, &msg, flags);
@@ -106,15 +112,16 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
106 socklen_t sa_size) 112 socklen_t sa_size)
107{ 113{
108#ifndef IP_PKTINFO 114#ifndef IP_PKTINFO
115 (void)to; /* suppress "unused to" warning */
109 return recvfrom(fd, buf, len, flags, from, &sa_size); 116 return recvfrom(fd, buf, len, flags, from, &sa_size);
110#else 117#else
111 /* man recvmsg and man cmsg is needed to make sense of code below */ 118 /* man recvmsg and man cmsg is needed to make sense of code below */
112 struct iovec iov[1]; 119 struct iovec iov[1];
113 union { 120 union {
114 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; 121 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
115#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) 122# if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
116 char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 123 char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
117#endif 124# endif
118 } u; 125 } u;
119 struct cmsghdr *cmsgptr; 126 struct cmsghdr *cmsgptr;
120 struct msghdr msg; 127 struct msghdr msg;
@@ -135,6 +142,8 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
135 if (recv_length < 0) 142 if (recv_length < 0)
136 return recv_length; 143 return recv_length;
137 144
145# define to4 ((struct sockaddr_in*)to)
146# define to6 ((struct sockaddr_in6*)to)
138 /* Here we try to retrieve destination IP and memorize it */ 147 /* Here we try to retrieve destination IP and memorize it */
139 for (cmsgptr = CMSG_FIRSTHDR(&msg); 148 for (cmsgptr = CMSG_FIRSTHDR(&msg);
140 cmsgptr != NULL; 149 cmsgptr != NULL;
@@ -143,25 +152,27 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
143 if (cmsgptr->cmsg_level == IPPROTO_IP 152 if (cmsgptr->cmsg_level == IPPROTO_IP
144 && cmsgptr->cmsg_type == IP_PKTINFO 153 && cmsgptr->cmsg_type == IP_PKTINFO
145 ) { 154 ) {
146#define pktinfo(cmsgptr) ( (struct in_pktinfo*)(CMSG_DATA(cmsgptr)) ) 155# define pktinfo(cmsgptr) ( (struct in_pktinfo*)(CMSG_DATA(cmsgptr)) )
147 to->sa_family = AF_INET; 156 to->sa_family = AF_INET;
148 ((struct sockaddr_in*)to)->sin_addr = pktinfo(cmsgptr)->ipi_addr; 157 /*to4->sin_addr = pktinfo(cmsgptr)->ipi_addr; - may be unaligned */
149 /* ((struct sockaddr_in*)to)->sin_port = 123; */ 158 memcpy(&to4->sin_addr, &pktinfo(cmsgptr)->ipi_addr, sizeof(to4->sin_addr));
150#undef pktinfo 159 /*to4->sin_port = 123; - this data is not supplied by kernel */
160# undef pktinfo
151 break; 161 break;
152 } 162 }
153#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) 163# if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
154 if (cmsgptr->cmsg_level == IPPROTO_IPV6 164 if (cmsgptr->cmsg_level == IPPROTO_IPV6
155 && cmsgptr->cmsg_type == IPV6_PKTINFO 165 && cmsgptr->cmsg_type == IPV6_PKTINFO
156 ) { 166 ) {
157#define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) ) 167# define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) )
158 to->sa_family = AF_INET6; 168 to->sa_family = AF_INET6;
159 ((struct sockaddr_in6*)to)->sin6_addr = pktinfo(cmsgptr)->ipi6_addr; 169 /*to6->sin6_addr = pktinfo(cmsgptr)->ipi6_addr; - may be unaligned */
160 /* ((struct sockaddr_in6*)to)->sin6_port = 123; */ 170 memcpy(&to6->sin6_addr, &pktinfo(cmsgptr)->ipi6_addr, sizeof(to6->sin6_addr));
161#undef pktinfo 171 /*to6->sin6_port = 123; */
172# undef pktinfo
162 break; 173 break;
163 } 174 }
164#endif 175# endif
165 } 176 }
166 return recv_length; 177 return recv_length;
167#endif 178#endif