Check that UNIX socket filenames are not too long.
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 20 Jul 2021 13:57:37 +0000 (15:57 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 20 Jul 2021 13:57:37 +0000 (15:57 +0200)
UNIX socket filenames must fit in a struct sockaddr_un, and typically this
only has about 100 bytes of storage. This is perfectly fine for normal use
of tinc, but this caused failures when running make distcheck, which ends
up creating a rather deep directory structure. With this commit, at least
a proper error message is printed instead of silently truncating the
filename.

src/control.c
src/fd_device.c
src/tincctl.c
src/uml_device.c

index 71258b5..fc713c8 100644 (file)
@@ -195,14 +195,17 @@ bool init_control(void) {
                return false;
        }
 
-       struct sockaddr_un sa_un;
+       struct sockaddr_un sa_un = {
+               .sun_family = AF_UNIX,
+       };
 
-       sa_un.sun_family = AF_UNIX;
+       if(strlen(unixsocketname) >= sizeof(sa_un.sun_path)) {
+               logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket filename %s is too long!", unixsocketname);
+               return false;
+       }
 
        strncpy(sa_un.sun_path, unixsocketname, sizeof(sa_un.sun_path));
 
-       sa_un.sun_path[sizeof(sa_un.sun_path) - 1] = 0;
-
        if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof(sa_un)) >= 0) {
                logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
                return false;
index 0da8259..e879a34 100644 (file)
@@ -116,7 +116,9 @@ end:
 }
 
 static struct unix_socket_addr parse_socket_addr(const char *path) {
-       struct sockaddr_un socket_addr;
+       struct sockaddr_un socket_addr = {
+               .sun_family = AF_UNIX,
+       };
        size_t path_length;
 
        if(strlen(path) >= sizeof(socket_addr.sun_path)) {
@@ -126,7 +128,6 @@ static struct unix_socket_addr parse_socket_addr(const char *path) {
                };
        }
 
-       socket_addr.sun_family = AF_UNIX;
        strncpy(socket_addr.sun_path, path, sizeof(socket_addr.sun_path));
 
        if(path[0] == '@') {
index bfc16af..8b49c44 100644 (file)
@@ -853,14 +853,17 @@ bool connect_tincd(bool verbose) {
                return false;
        }
 
-       struct sockaddr_un sa;
+       struct sockaddr_un sa = {
+               .sun_family = AF_UNIX,
+       };
 
-       sa.sun_family = AF_UNIX;
+       if(strlen(unixsocketname) >= sizeof(sa.sun_path)) {
+               fprintf(stderr, "UNIX socket filename %s is too long!", unixsocketname);
+               return false;
+       }
 
        strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path));
 
-       sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
-
        fd = socket(AF_UNIX, SOCK_STREAM, 0);
 
        if(fd < 0) {
index a675b62..4b574e8 100644 (file)
@@ -47,10 +47,14 @@ static struct request {
        struct sockaddr_un sock;
 } request;
 
-static struct sockaddr_un data_sun;
+static struct sockaddr_un data_sun = {
+       .sun_family = AF_UNIX,
+};
 
 static bool setup_device(void) {
-       struct sockaddr_un listen_sun;
+       struct sockaddr_un listen_sun = {
+               .sun_family = AF_UNIX,
+       };
        static const int one = 1;
        struct {
                char zero;
@@ -105,7 +109,6 @@ static bool setup_device(void) {
        name.pid = getpid();
        gettimeofday(&tv, NULL);
        name.usecs = tv.tv_usec;
-       data_sun.sun_family = AF_UNIX;
        memcpy(&data_sun.sun_path, &name, sizeof(name));
 
        if(bind(data_fd, (struct sockaddr *)&data_sun, sizeof(data_sun)) < 0) {
@@ -131,9 +134,12 @@ static bool setup_device(void) {
                return false;
        }
 
-       listen_sun.sun_family = AF_UNIX;
+       if(strlen(device) >= sizeof(listen_sun.sun_path)) {
+               logger(DEBUG_ALWAYS, LOG_ERR, "UML socket filename %s is too long!", device);
+               return false;
+       }
+
        strncpy(listen_sun.sun_path, device, sizeof(listen_sun.sun_path));
-       listen_sun.sun_path[sizeof(listen_sun.sun_path) - 1] = 0;
 
        if(bind(listen_fd, (struct sockaddr *)&listen_sun, sizeof(listen_sun)) < 0) {
                logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind %s to %s: %s", device_info, device, strerror(errno));