Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Dec 2016 18:53:22 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r309644 - stable/11/lib/libc/net
Message-ID:  <201612061853.uB6IrM1W021275@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Tue Dec  6 18:53:21 2016
New Revision: 309644
URL: https://svnweb.freebsd.org/changeset/base/309644

Log:
  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

Modified:
  stable/11/lib/libc/net/linkaddr.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libc/net/linkaddr.c
==============================================================================
--- stable/11/lib/libc/net/linkaddr.c	Tue Dec  6 18:52:33 2016	(r309643)
+++ stable/11/lib/libc/net/linkaddr.c	Tue Dec  6 18:53:21 2016	(r309644)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <net/if.h>
 #include <net/if_dl.h>
 #include <string.h>
 
@@ -122,31 +123,47 @@ 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;
-
-	if (sdl->sdl_nlen) {
-		bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
-		out += sdl->sdl_nlen;
-		if (sdl->sdl_alen)
+	_Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small");
+	char *out;
+	const char *in, *inlim;
+	int namelen, i, rem;
+
+	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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612061853.uB6IrM1W021275>