Author: glebius
Date: Tue Dec  6 18:53:46 2016
New Revision: 309645
URL: https://svnweb.freebsd.org/changeset/base/309645

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/10/lib/libc/net/linkaddr.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/linkaddr.c
==============================================================================
--- stable/10/lib/libc/net/linkaddr.c   Tue Dec  6 18:53:21 2016        
(r309644)
+++ stable/10/lib/libc/net/linkaddr.c   Tue Dec  6 18:53:46 2016        
(r309645)
@@ -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>
 
@@ -125,31 +126,47 @@ link_ntoa(sdl)
        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);
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to