summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2016-12-06 22:32:59 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2016-12-06 22:32:59 +0000
commit8050ae785ff25fb051f2861b23b86887bccab5aa (patch)
tree3052bbe601c86eac419ed53222477b5d05ce6979
parentdaad54a1e46f7cd844dbe60344527bd578aa8112 (diff)
CVE-2016-6559: fix potential buffer overflow(s) in link_ntoa(3).
A specially crafted struct sockaddr_dl argument can trigger a stack overflow of a static buffer in libc. An attacker may be able to use this to write to arbitrary locations in the data segment. From FreeBSD (glebius); OK deraadt@ mestre@
-rw-r--r--lib/libc/net/linkaddr.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/lib/libc/net/linkaddr.c b/lib/libc/net/linkaddr.c
index 8f90aca8f52..5b74d982190 100644
--- a/lib/libc/net/linkaddr.c
+++ b/lib/libc/net/linkaddr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linkaddr.c,v 1.6 2015/09/10 08:55:03 mpi Exp $ */
+/* $OpenBSD: linkaddr.c,v 1.7 2016/12/06 22:32:58 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,40 +30,56 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <net/if.h>
#include <net/if_dl.h>
#include <string.h>
-static char hexlist[] = "0123456789abcdef";
+static const char hexlist[] = "0123456789abcdef";
char *
link_ntoa(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;
+ 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) {
+ memcpy(out, sdl->sdl_data, 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);