]> tinc-vpn.org Git - tinc/commitdiff
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 71258b58da2361c3ee072f8ed5b6b47a6bcdf482..fc713c8b95c4393807d54d3d168d2c3e86fb8e70 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 0da82591cca8876351b13e83c0ae7998b0564cd1..e879a341361338ac1f8f3d41485836f07f47f045 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 bfc16af44aadcb7402a9d9e152a451741e7c2428..8b49c4499b2c508ba04bc4595c377cfffe6a2bac 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 a675b62e045ab8b2c285d2c028c8f0441892c432..4b574e814a3284d0abd0027e3db015d0540b1f3c 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));