From 6eec5c0ac4990b2cf298afce48e0ea2529fa645c Mon Sep 17 00:00:00 2001 From: glebius Date: Tue, 6 Dec 2016 18:53:46 +0000 Subject: Merge r309639 from head: Fix possible buffer overflow(s) in link_ntoa(3). A specially crafted sockaddr_dl argument can trigger a static buffer overflow in the libc library, with possibility to rewrite with arbitrary data following static buffers that belong to other library functions. Reviewed by: kib Security: FreeBSD-SA-16:37.libc --- lib/libc/net/linkaddr.c | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'lib/libc/net/linkaddr.c') diff --git a/lib/libc/net/linkaddr.c b/lib/libc/net/linkaddr.c index 5be6e74..f14f22d 100644 --- a/lib/libc/net/linkaddr.c +++ b/lib/libc/net/linkaddr.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -125,31 +126,47 @@ link_ntoa(sdl) const struct sockaddr_dl *sdl; { static char obuf[64]; - char *out = obuf; - int i; - u_char *in = (u_char *)LLADDR(sdl); - u_char *inlim = in + sdl->sdl_alen; - int firsttime = 1; + _Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small"); + char *out; + const char *in, *inlim; + int namelen, i, rem; - if (sdl->sdl_nlen) { - bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen); - out += sdl->sdl_nlen; - if (sdl->sdl_alen) + namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ; + + out = obuf; + rem = sizeof(obuf); + if (namelen > 0) { + bcopy(sdl->sdl_data, out, namelen); + out += namelen; + rem -= namelen; + if (sdl->sdl_alen > 0) { *out++ = ':'; + rem--; + } } - while (in < inlim) { - if (firsttime) - firsttime = 0; - else + + in = (const char *)sdl->sdl_data + sdl->sdl_nlen; + inlim = in + sdl->sdl_alen; + + while (in < inlim && rem > 1) { + if (in != (const char *)sdl->sdl_data + sdl->sdl_nlen) { *out++ = '.'; + rem--; + } i = *in++; if (i > 0xf) { - out[1] = hexlist[i & 0xf]; + if (rem < 3) + break; + *out++ = hexlist[i & 0xf]; i >>= 4; - out[0] = hexlist[i]; - out += 2; - } else *out++ = hexlist[i]; + rem -= 2; + } else { + if (rem < 2) + break; + *out++ = hexlist[i]; + rem++; + } } *out = 0; return (obuf); -- cgit v1.1