diff options
| author | millert <> | 2016-12-06 22:32:58 +0000 |
|---|---|---|
| committer | millert <> | 2016-12-06 22:32:58 +0000 |
| commit | 9c7308f23068f3d90f1bb1a2ef7d36ecbed581d6 (patch) | |
| tree | 2e9e084dc27ddb18364fa91983e3904f2bf3b0a2 /src/lib/libc | |
| parent | 9d715a5790fa985150b95cc086e8d99daec28daa (diff) | |
| download | openbsd-9c7308f23068f3d90f1bb1a2ef7d36ecbed581d6.tar.gz openbsd-9c7308f23068f3d90f1bb1a2ef7d36ecbed581d6.tar.bz2 openbsd-9c7308f23068f3d90f1bb1a2ef7d36ecbed581d6.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@
Diffstat (limited to 'src/lib/libc')
| -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); |
