Socket::unpack_sockaddr_un heap-buffer-overflow
authorDavid Mitchell <davem@iabyn.com>
Sun, 24 Feb 2013 16:46:19 +0000 (16:46 +0000)
committerDavid Mitchell <davem@iabyn.com>
Sun, 24 Feb 2013 20:27:17 +0000 (20:27 +0000)
[perl #111594]

A (fairly harmless) read buffer overflow can occur when copying sockaddr
buffers. Cherry-pick the fix from Socket 2.009 to keep ASAN happy.

ext/Socket/Socket.xs

index 9214fc1..e5abb71 100644 (file)
@@ -557,18 +557,22 @@ unpack_sockaddr_un(sun_sv)
        STRLEN sockaddrlen;
        char * sun_ad = SvPVbyte(sun_sv,sockaddrlen);
        int addr_len;
-#   ifndef __linux__
+#   ifdef __linux__
        /* On Linux sockaddrlen on sockets returned by accept, recvfrom,
           getpeername and getsockname is not equal to sizeof(addr). */
-       if (sockaddrlen != sizeof(addr)) {
-           croak("Bad arg length for %s, length is %d, should be %d",
-                       "Socket::unpack_sockaddr_un",
-                       sockaddrlen, sizeof(addr));
+       if (sockaddrlen < sizeof(addr)) {
+         Copy(sun_ad, &addr, sockaddrlen, char);
+         Zero(((char*)&addr) + sockaddrlen, sizeof(addr) - sockaddrlen, char);
+       } else {
+         Copy(sun_ad, &addr, sizeof(addr), char);
        }
+#   else
+       if (sockaddrlen != sizeof(addr))
+               croak("Bad arg length for %s, length is %"UVuf", should be %"UVuf,
+                     "Socket::unpack_sockaddr_un", (UV)sockaddrlen, (UV)sizeof(addr));
+       Copy(sun_ad, &addr, sizeof(addr), char);
 #   endif
 
-       Copy( sun_ad, &addr, sizeof addr, char );
-
        if ( addr.sun_family != AF_UNIX ) {
            croak("Bad address family for %s, got %d, should be %d",
                        "Socket::unpack_sockaddr_un",