summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillert <>2016-12-06 22:32:58 +0000
committermillert <>2016-12-06 22:32:58 +0000
commit4d9677358bc95023338532b4baff258fdc7e1aec (patch)
tree2e9e084dc27ddb18364fa91983e3904f2bf3b0a2
parent1cef314a24bb06bab406c6609fa8bb3fcb626487 (diff)
downloadopenbsd-4d9677358bc95023338532b4baff258fdc7e1aec.tar.gz
openbsd-4d9677358bc95023338532b4baff258fdc7e1aec.tar.bz2
openbsd-4d9677358bc95023338532b4baff258fdc7e1aec.zip
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--src/lib/libc/net/linkaddr.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/src/lib/libc/net/linkaddr.c b/src/lib/libc/net/linkaddr.c
index 8f90aca8f5..5b74d98219 100644
--- a/src/lib/libc/net/linkaddr.c
+++ b/src/lib/libc/net/linkaddr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: linkaddr.c,v 1.6 2015/09/10 08:55:03 mpi Exp $ */ 1/* $OpenBSD: linkaddr.c,v 1.7 2016/12/06 22:32:58 millert Exp $ */
2/*- 2/*-
3 * Copyright (c) 1990, 1993 3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -30,40 +30,56 @@
30 30
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/socket.h> 32#include <sys/socket.h>
33#include <net/if.h>
33#include <net/if_dl.h> 34#include <net/if_dl.h>
34#include <string.h> 35#include <string.h>
35 36
36static char hexlist[] = "0123456789abcdef"; 37static const char hexlist[] = "0123456789abcdef";
37 38
38char * 39char *
39link_ntoa(const struct sockaddr_dl *sdl) 40link_ntoa(const struct sockaddr_dl *sdl)
40{ 41{
41 static char obuf[64]; 42 static char obuf[64];
42 char *out = obuf; 43 char *out;
43 int i; 44 const char *in, *inlim;
44 u_char *in = (u_char *)LLADDR(sdl); 45 int namelen, i, rem;
45 u_char *inlim = in + sdl->sdl_alen;
46 int firsttime = 1;
47 46
48 if (sdl->sdl_nlen) { 47 namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ;
49 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen); 48
50 out += sdl->sdl_nlen; 49 out = obuf;
51 if (sdl->sdl_alen) 50 rem = sizeof(obuf);
51 if (namelen > 0) {
52 memcpy(out, sdl->sdl_data, namelen);
53 out += namelen;
54 rem -= namelen;
55 if (sdl->sdl_alen > 0) {
52 *out++ = ':'; 56 *out++ = ':';
57 rem--;
58 }
53 } 59 }
54 while (in < inlim) { 60
55 if (firsttime) 61 in = (const char *)sdl->sdl_data + sdl->sdl_nlen;
56 firsttime = 0; 62 inlim = in + sdl->sdl_alen;
57 else 63
64 while (in < inlim && rem > 1) {
65 if (in != (const char *)sdl->sdl_data + sdl->sdl_nlen) {
58 *out++ = '.'; 66 *out++ = '.';
67 rem--;
68 }
59 i = *in++; 69 i = *in++;
60 if (i > 0xf) { 70 if (i > 0xf) {
61 out[1] = hexlist[i & 0xf]; 71 if (rem < 3)
72 break;
73 *out++ = hexlist[i & 0xf];
62 i >>= 4; 74 i >>= 4;
63 out[0] = hexlist[i];
64 out += 2;
65 } else
66 *out++ = hexlist[i]; 75 *out++ = hexlist[i];
76 rem -= 2;
77 } else {
78 if (rem < 2)
79 break;
80 *out++ = hexlist[i];
81 rem++;
82 }
67 } 83 }
68 *out = 0; 84 *out = 0;
69 return (obuf); 85 return (obuf);