From: Lennart Poettering Date: Mon, 15 Oct 2018 16:54:12 +0000 (+0200) Subject: socket-util: tighten socket_address_verify() checks a bit X-Git-Tag: v240~538^2~4 X-Git-Url: http://git-history.diyao.me/?a=commitdiff_plain;h=8e8132c6b849a0aa34dbe8d97027beb50f71f1e3;p=systemd%2F.git socket-util: tighten socket_address_verify() checks a bit --- diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index c55f67964e..dd22d30fca 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -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; } }