move unix path length checks to config_sanity_check()

cfg->host is static configuration, so an over-long path is a config
error: validate it once at startup in config_sanity_check() for both
is_unix listen endpoints and is_unix protocol targets, instead of at
bind()/connect() time. This also fails fast for protocol targets,
where the previous runtime check only dropped each connection instead
of reporting the bad config.

The memset()/bounded strncpy() calls stay in place: they are what make
sun_path termination structurally safe regardless of the input length.
This commit is contained in:
Stefan Meinecke authored and Yves Rutschle committed 2026-10-18 22:04:22 +02:00
1 parent 7afa284efc
commit e20f2381c3
2 files changed
+21 -14

No files matched your search

-14
View File
@@ -205,13 +205,6 @@ static int start_listen_unix(struct listen_endpoint *sockfd[], int num_addr, str
{
struct sockaddr_un sun;
/* Fail before unlink()ing an existing file we could not bind anyway */
if (strlen(cfg->host) >= sizeof(sun.sun_path)) {
print_message(msg_config_error, "unix socket path too long (%zd, max %zd): %s\n",
strlen(cfg->host), sizeof(sun.sun_path) - 1, cfg->host);
exit(4);
}
int fd = socket(AF_UNIX, cfg->is_udp ? SOCK_DGRAM : SOCK_STREAM, 0);
CHECK_RES_DIE(fd, "socket(AF_UNIX)");
@@ -484,13 +477,6 @@ static int connect_unix(struct connection *cnx, int fd_from, connect_blocking bl
struct sockaddr_storage ss;
struct sockaddr_un* sun = (struct sockaddr_un*)&ss;
if (strlen(cnx->proto->host) >= sizeof(sun->sun_path)) {
print_message(msg_system_error, "unix socket path too long (%zd, max %zd): %s\n",
strlen(cnx->proto->host), sizeof(sun->sun_path) - 1,
cnx->proto->host);
return -1;
}
memset(&ss, 0, sizeof(ss));
sun->sun_family = AF_UNIX;
strncpy(sun->sun_path, cnx->proto->host, sizeof(sun->sun_path)-1);
+21
View File
@@ -30,6 +30,8 @@
#include <pcre2.h>
#endif
#include <sys/un.h>
#include "common.h"
#include "probe.h"
#include "log.h"
@@ -277,6 +279,21 @@ static void config_sanity_libwrap(const struct sslhcfg_protocols_item* prot)
#endif
}
/* sun_path has a fixed, compile-time size (typically 108 chars): a configured
* unix socket path that does not fit can never work, so reject it once at
* startup rather than at bind()/connect() time */
static void config_sanity_unix_path(const char* host)
{
size_t path_max = sizeof(((struct sockaddr_un*)0)->sun_path);
if (host && strlen(host) >= path_max) {
print_message(msg_config_error,
"unix socket path too long (%zd, max %zd): %s\n",
strlen(host), path_max - 1, host);
exit(4);
}
}
void config_sanity_check(struct sslhcfg_item* cfg)
{
size_t i;
@@ -291,6 +308,8 @@ void config_sanity_check(struct sslhcfg_item* cfg)
for (i = 0; i < cfg->listen_len; i++) {
config_sanity_listen_proxyprotocol(&cfg->listen[i]);
if (cfg->listen[i].is_unix)
config_sanity_unix_path(cfg->listen[i].host);
}
for (i = 0; i < cfg->protocols_len; ++i) {
@@ -312,6 +331,8 @@ void config_sanity_check(struct sslhcfg_item* cfg)
config_sanity_regex(&cfg->protocols[i]);
config_sanity_proxyprotocol(&cfg->protocols[i]);
config_sanity_libwrap(&cfg->protocols[i]);
if (cfg->protocols[i].is_unix)
config_sanity_unix_path(cfg->protocols[i].host);
if (cfg->protocols[i].is_udp) {
if (cfg->protocols[i].tfo_ok) {