summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflorian <>2021-01-19 16:43:44 +0000
committerflorian <>2021-01-19 16:43:44 +0000
commit11fb2101811061cab904382a8a9392a1451bc040 (patch)
treeab34a192f1f66619f942099a65504d0d55b6001c
parentd5a424e282cee10e2123a6454e4ab9c6df85724d (diff)
downloadopenbsd-11fb2101811061cab904382a8a9392a1451bc040.tar.gz
openbsd-11fb2101811061cab904382a8a9392a1451bc040.tar.bz2
openbsd-11fb2101811061cab904382a8a9392a1451bc040.zip
Prevent an overflow in inet_net_pton(3) when the passed in buffer is
too small in the AF_INET6 case. Spotted by Brad House (brad AT brad-house.com) with the c-ares regression test. The man page says Caution: The dst field should be zeroed before calling inet_net_pton() as the function will only fill the number of bytes necessary to encode the network number in network byte order. Which seems to suggest that the function should work if the passed in storage is big enough to hold the prefix, which might be smaller than sizeof(in6_addr). Input & OK tb
-rw-r--r--src/lib/libc/net/inet_net_pton.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/src/lib/libc/net/inet_net_pton.c b/src/lib/libc/net/inet_net_pton.c
index 2aaeac4048..aaffc1802a 100644
--- a/src/lib/libc/net/inet_net_pton.c
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: inet_net_pton.c,v 1.10 2017/03/06 18:16:27 millert Exp $ */ 1/* $OpenBSD: inet_net_pton.c,v 1.11 2021/01/19 16:43:44 florian Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org> 4 * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org>
@@ -205,9 +205,10 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
205static int 205static int
206inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) 206inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
207{ 207{
208 int ret; 208 struct in6_addr in6;
209 int bits; 209 int ret;
210 char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")]; 210 int bits;
211 char buf[INET6_ADDRSTRLEN + sizeof("/128")];
211 char *sep; 212 char *sep;
212 const char *errstr; 213 const char *errstr;
213 214
@@ -220,18 +221,24 @@ inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
220 if (sep != NULL) 221 if (sep != NULL)
221 *sep++ = '\0'; 222 *sep++ = '\0';
222 223
223 ret = inet_pton(AF_INET6, buf, dst); 224 ret = inet_pton(AF_INET6, buf, &in6);
224 if (ret != 1) 225 if (ret != 1)
225 return (-1); 226 return (-1);
226 227
227 if (sep == NULL) 228 if (sep == NULL)
228 return 128; 229 bits = 128;
230 else {
231 bits = strtonum(sep, 0, 128, &errstr);
232 if (errstr) {
233 errno = EINVAL;
234 return (-1);
235 }
236 }
229 237
230 bits = strtonum(sep, 0, 128, &errstr); 238 if ((bits + 7) / 8 > size) {
231 if (errstr) { 239 errno = EMSGSIZE;
232 errno = EINVAL;
233 return (-1); 240 return (-1);
234 } 241 }
235 242 memcpy(dst, &in6.s6_addr, size);
236 return bits; 243 return (bits);
237} 244}