From 95baa36f10743d4d2bd6f6ff05457f77bd14e96d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 20 Jul 2021 15:57:37 +0200 Subject: [PATCH] Check that UNIX socket filenames are not too long. 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 | 11 +++++++---- src/fd_device.c | 5 +++-- src/tincctl.c | 11 +++++++---- src/uml_device.c | 16 +++++++++++----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/control.c b/src/control.c index 71258b58..fc713c8b 100644 --- a/src/control.c +++ b/src/control.c @@ -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; diff --git a/src/fd_device.c b/src/fd_device.c index 0da82591..e879a341 100644 --- a/src/fd_device.c +++ b/src/fd_device.c @@ -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] == '@') { diff --git a/src/tincctl.c b/src/tincctl.c index bfc16af4..8b49c449 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -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) { diff --git a/src/uml_device.c b/src/uml_device.c index a675b62e..4b574e81 100644 --- a/src/uml_device.c +++ b/src/uml_device.c @@ -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)); -- 2.20.1