]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: tighten socket_address_verify() checks a bit
authorLennart Poettering <lennart@poettering.net>
Mon, 15 Oct 2018 16:54:12 +0000 (18:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 15 Oct 2018 17:40:51 +0000 (19:40 +0200)
src/basic/socket-util.c

index c55f67964ee28f136360a2facd6ffec0b96d1643..dd22d30fca928cf91407af259973ea6c17aa2667 100644 (file)
@@ -293,19 +293,28 @@ int socket_address_verify(const SocketAddress *a) {
         case AF_UNIX:
                 if (a->size < offsetof(struct sockaddr_un, sun_path))
                         return -EINVAL;
+                if (a->size > sizeof(struct sockaddr_un)+1) /* Allow one extra byte, since getsockname() on Linux will
+                                                             * append a NUL byte if we have path sockets that are above
+                                                             * sun_path' full size */
+                        return -EINVAL;
 
-                if (a->size > offsetof(struct sockaddr_un, sun_path)) {
-
-                        if (a->sockaddr.un.sun_path[0] != 0) {
-                                char *e;
+                if (a->size > offsetof(struct sockaddr_un, sun_path) &&
+                    a->sockaddr.un.sun_path[0] != 0) { /* Only validate file system sockets here */
 
-                                /* path */
-                                e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
-                                if (!e)
-                                        return -EINVAL;
+                        const char *e;
 
+                        e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
+                        if (e) {
+                                /* If there's an embedded NUL byte, make sure the size of the socket addresses matches it */
                                 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
                                         return -EINVAL;
+                        } else {
+                                /* If there's no embedded NUL byte, then then the size needs to match the whole
+                                 * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
+                                 * and considers both equivalent: getsockname() even extends sockaddr_un beyond its
+                                 * size if the path is non NUL terminated.)*/
+                                if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1))
+                                        return -EINVAL;
                         }
                 }