summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorderaadt <>2025-11-13 10:34:32 +0000
committerderaadt <>2025-11-13 10:34:32 +0000
commit825e052c574fe0fd3afe3cf1322f333551ca4888 (patch)
tree91903c439b8433ac80e85f001a34fa1b2975949a
parent286cd02a2b95cd94707d1ae63155b59302dfefc7 (diff)
downloadopenbsd-825e052c574fe0fd3afe3cf1322f333551ca4888.tar.gz
openbsd-825e052c574fe0fd3afe3cf1322f333551ca4888.tar.bz2
openbsd-825e052c574fe0fd3afe3cf1322f333551ca4888.zip
the structure produced has alignment, which contained uninitialized data.
This is obviously fixed by using calloc(), but it was also observed that the precalculated storage requirement was higher than what is actually filled. So all the math has been rewritten to be byte accurate. Temporarily, a syslog_r check is added to report if we ever get count inconsistancy again so that can be fixed quickly. ok claudio
-rw-r--r--src/lib/libc/net/getifaddrs.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
index 069ee9afab..448e76097f 100644
--- a/src/lib/libc/net/getifaddrs.c
+++ b/src/lib/libc/net/getifaddrs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: getifaddrs.c,v 1.14 2021/11/29 03:20:37 deraadt Exp $ */ 1/* $OpenBSD: getifaddrs.c,v 1.15 2025/11/13 10:34:32 deraadt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1995, 1999 4 * Copyright (c) 1995, 1999
@@ -25,10 +25,10 @@
25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp 25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 */ 26 */
27 27
28#include <sys/param.h> /* ALIGN ALIGNBYTES */
29#include <sys/types.h> 28#include <sys/types.h>
30#include <sys/ioctl.h> 29#include <sys/ioctl.h>
31#include <sys/socket.h> 30#include <sys/socket.h>
31#include <sys/syslog.h>
32#include <net/if.h> 32#include <net/if.h>
33#include <net/route.h> 33#include <net/route.h>
34#include <sys/sysctl.h> 34#include <sys/sysctl.h>
@@ -38,35 +38,32 @@
38#include <ifaddrs.h> 38#include <ifaddrs.h>
39#include <stddef.h> 39#include <stddef.h>
40#include <stdlib.h> 40#include <stdlib.h>
41#include <stdint.h>
41#include <string.h> 42#include <string.h>
42#include <unistd.h> 43#include <unistd.h>
44#include <stdio.h>
43 45
44#define SALIGN (sizeof(long) - 1) 46#define roundup(x, y) ((((uintptr_t)(x)+((y)-1))/(y))*(y))
45#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1)) 47#define proundup(x, y) (void *)roundup(x,y)
48
49#define SA_RLEN(sa) ((sa)->sa_len ? \
50 roundup((sa)->sa_len, sizeof(long)) : \
51 roundup(1, sizeof(long)))
46 52
47int 53int
48getifaddrs(struct ifaddrs **pif) 54getifaddrs(struct ifaddrs **pif)
49{ 55{
50 int icnt = 1; 56 int icnt = 1, dcnt = 0, ncnt = 0, mib[6], i;
51 int dcnt = 0;
52 int ncnt = 0;
53 int mib[6];
54 size_t needed; 57 size_t needed;
55 char *buf = NULL, *bufp; 58 char *buf = NULL, *bufp, *data, *names, *next, *p, *p0;
56 char *next; 59 struct ifaddrs *cif = 0, *ifa, *ift;
57 struct ifaddrs *cif = 0;
58 char *p, *p0;
59 struct rt_msghdr *rtm; 60 struct rt_msghdr *rtm;
60 struct if_msghdr *ifm; 61 struct if_msghdr *ifm;
61 struct ifa_msghdr *ifam; 62 struct ifa_msghdr *ifam;
62 struct sockaddr_dl *dl; 63 struct sockaddr_dl *dl;
63 struct sockaddr *sa; 64 struct sockaddr *sa;
64 u_short index = 0; 65 u_short index = 0;
65 size_t len, alen, dlen; 66 size_t len, alen, dlen, dsize;
66 struct ifaddrs *ifa, *ift;
67 int i;
68 char *data;
69 char *names;
70 67
71 mib[0] = CTL_NET; 68 mib[0] = CTL_NET;
72 mib[1] = PF_ROUTE; 69 mib[1] = PF_ROUTE;
@@ -95,6 +92,7 @@ getifaddrs(struct ifaddrs **pif)
95 break; 92 break;
96 } 93 }
97 94
95 /* Calculate data buffer size */
98 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 96 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
99 rtm = (struct rt_msghdr *)next; 97 rtm = (struct rt_msghdr *)next;
100 if (rtm->rtm_version != RTM_VERSION) 98 if (rtm->rtm_version != RTM_VERSION)
@@ -107,10 +105,15 @@ getifaddrs(struct ifaddrs **pif)
107 ++icnt; 105 ++icnt;
108 dl = (struct sockaddr_dl *)(next + 106 dl = (struct sockaddr_dl *)(next +
109 rtm->rtm_hdrlen); 107 rtm->rtm_hdrlen);
110 dcnt += SA_RLEN((struct sockaddr *)dl) +
111 ALIGNBYTES;
112 dcnt += sizeof(ifm->ifm_data);
113 ncnt += dl->sdl_nlen + 1; 108 ncnt += dl->sdl_nlen + 1;
109
110 /* sockaddr's need long alignment */
111 dcnt = roundup(dcnt, sizeof(long));
112 dcnt += SA_RLEN((struct sockaddr *)dl);
113
114 /* ifm_data[] needs long long alignment */
115 dcnt = roundup(dcnt, sizeof(long long));
116 dcnt += sizeof(ifm->ifm_data);
114 } else 117 } else
115 index = 0; 118 index = 0;
116 break; 119 break;
@@ -145,6 +148,8 @@ getifaddrs(struct ifaddrs **pif)
145 continue; 148 continue;
146 sa = (struct sockaddr *)p; 149 sa = (struct sockaddr *)p;
147 len = SA_RLEN(sa); 150 len = SA_RLEN(sa);
151 /* sockaddr's need long alignment */
152 dcnt = roundup(dcnt, sizeof(long));
148 if (i == RTAX_NETMASK && sa->sa_len == 0) 153 if (i == RTAX_NETMASK && sa->sa_len == 0)
149 dcnt += alen; 154 dcnt += alen;
150 else 155 else
@@ -155,23 +160,29 @@ getifaddrs(struct ifaddrs **pif)
155 } 160 }
156 } 161 }
157 162
158 if (icnt + dcnt + ncnt == 1) { 163 if (icnt + ncnt + dcnt == 1) {
159 *pif = NULL; 164 *pif = NULL;
160 free(buf); 165 free(buf);
161 return (0); 166 return (0);
162 } 167 }
163 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt); 168
169 dsize = sizeof(struct ifaddrs) * icnt;
170 dsize += ncnt;
171 dsize = roundup(dsize, sizeof(long long));
172 dsize += dcnt;
173
174 data = calloc(dsize, 1);
164 if (data == NULL) { 175 if (data == NULL) {
165 free(buf); 176 free(buf);
166 return(-1); 177 return(-1);
167 } 178 }
168 179
169 ifa = (struct ifaddrs *)data; 180 /* ifaddrs[], names, then if_data[] */
181 ift = ifa = (struct ifaddrs *)data;
170 data += sizeof(struct ifaddrs) * icnt; 182 data += sizeof(struct ifaddrs) * icnt;
171 names = data + dcnt; 183 names = data;
172 184 data += ncnt;
173 memset(ifa, 0, sizeof(struct ifaddrs) * icnt); 185 data = proundup(data, sizeof(long long));
174 ift = ifa;
175 186
176 index = 0; 187 index = 0;
177 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 188 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
@@ -193,19 +204,21 @@ getifaddrs(struct ifaddrs **pif)
193 names[dl->sdl_nlen] = 0; 204 names[dl->sdl_nlen] = 0;
194 names += dl->sdl_nlen + 1; 205 names += dl->sdl_nlen + 1;
195 206
207 data = proundup(data, sizeof(long));
196 ift->ifa_addr = (struct sockaddr *)data; 208 ift->ifa_addr = (struct sockaddr *)data;
197 memcpy(data, dl, 209 memcpy(data, dl,
198 ((struct sockaddr *)dl)->sa_len); 210 ((struct sockaddr *)dl)->sa_len);
199 data += SA_RLEN((struct sockaddr *)dl); 211 data += SA_RLEN((struct sockaddr *)dl);
200 212
201 /* ifm_data needs to be aligned */ 213 /* if_data needs long long alignment */
202 ift->ifa_data = data = (void *)ALIGN(data); 214 data = proundup(data, sizeof(long long));
215 ift->ifa_data = data;
203 dlen = rtm->rtm_hdrlen - 216 dlen = rtm->rtm_hdrlen -
204 offsetof(struct if_msghdr, ifm_data); 217 offsetof(struct if_msghdr, ifm_data);
205 if (dlen > sizeof(ifm->ifm_data)) 218 if (dlen > sizeof(ifm->ifm_data))
206 dlen = sizeof(ifm->ifm_data); 219 dlen = sizeof(ifm->ifm_data);
207 memcpy(data, &ifm->ifm_data, dlen); 220 memcpy(data, &ifm->ifm_data, dlen);
208 data += sizeof(ifm->ifm_data); 221 data += dlen;
209 222
210 ift = (ift->ifa_next = ift + 1); 223 ift = (ift->ifa_next = ift + 1);
211 } else 224 } else
@@ -245,12 +258,14 @@ getifaddrs(struct ifaddrs **pif)
245 len = SA_RLEN(sa); 258 len = SA_RLEN(sa);
246 switch (i) { 259 switch (i) {
247 case RTAX_IFA: 260 case RTAX_IFA:
261 data = proundup(data, sizeof(long));
248 ift->ifa_addr = (struct sockaddr *)data; 262 ift->ifa_addr = (struct sockaddr *)data;
249 memcpy(data, p, len); 263 memcpy(data, p, len);
250 data += len; 264 data += len;
251 break; 265 break;
252 266
253 case RTAX_NETMASK: 267 case RTAX_NETMASK:
268 data = proundup(data, sizeof(long));
254 ift->ifa_netmask = 269 ift->ifa_netmask =
255 (struct sockaddr *)data; 270 (struct sockaddr *)data;
256 if (sa->sa_len == 0) { 271 if (sa->sa_len == 0) {
@@ -263,6 +278,7 @@ getifaddrs(struct ifaddrs **pif)
263 break; 278 break;
264 279
265 case RTAX_BRD: 280 case RTAX_BRD:
281 data = proundup(data, sizeof(long));
266 ift->ifa_broadaddr = 282 ift->ifa_broadaddr =
267 (struct sockaddr *)data; 283 (struct sockaddr *)data;
268 memcpy(data, p, len); 284 memcpy(data, p, len);
@@ -278,6 +294,17 @@ getifaddrs(struct ifaddrs **pif)
278 } 294 }
279 } 295 }
280 296
297 /* XXX temporary paranoia until we are sure it is bug free */
298 if (dsize != (char *)data - (char *)ifa) {
299 char buf[1024];
300
301 /* <10> is LOG_CRIT */
302 snprintf(buf, sizeof buf,
303 "<10>%s: getifaddrs: allocated %lu used %lu\n",
304 __progname, dsize, (char *)data - (char *)ifa);
305 sendsyslog(buf, strlen(buf), LOG_CONS);
306 }
307
281 free(buf); 308 free(buf);
282 if (--ift >= ifa) { 309 if (--ift >= ifa) {
283 ift->ifa_next = NULL; 310 ift->ifa_next = NULL;