diff options
author | millert <> | 2016-12-06 22:32:58 +0000 |
---|---|---|
committer | millert <> | 2016-12-06 22:32:58 +0000 |
commit | 4d9677358bc95023338532b4baff258fdc7e1aec (patch) | |
tree | 2e9e084dc27ddb18364fa91983e3904f2bf3b0a2 | |
parent | 1cef314a24bb06bab406c6609fa8bb3fcb626487 (diff) | |
download | openbsd-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.c | 54 |
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 | ||
36 | static char hexlist[] = "0123456789abcdef"; | 37 | static const char hexlist[] = "0123456789abcdef"; |
37 | 38 | ||
38 | char * | 39 | char * |
39 | link_ntoa(const struct sockaddr_dl *sdl) | 40 | link_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); |