From: Miroslav Lichvar Date: Tue, 20 May 2025 14:02:09 +0000 (+0200) Subject: socket: drop messages from unterminated Unix paths X-Git-Tag: 4.7-pre1~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=545bd59563d80aac2f48b89e6305937d72895fa3;p=thirdparty%2Fchrony.git socket: drop messages from unterminated Unix paths On some systems (e.g. FreeBSD) the source Unix domain socket path provided by recvmsg() as msg_name is not always null-terminated even if more space than required for sockaddr_un is provided due to the padding in the sockaddr_all union, and the returned msg_namelen value does not indicate it is missing the termination. If a cmdmon client bound its socket to a maximum-length path (chronyc doesn't allow that), the path would be overread when printing a debug message and trying to send a response. Drop messages from paths not shorter than sun_path to avoid working with un-printf()able and/or unreachable addresses. The clients are expected to not use the maximum-length paths. --- diff --git a/socket.c b/socket.c index 80fafc73..13ea69fb 100644 --- a/socket.c +++ b/socket.c @@ -877,8 +877,10 @@ static int process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags, SCK_Message *message) { + int r = 1, path_len, max_path_len; struct cmsghdr *cmsg; - int r = 1; + + init_message_addresses(message, SCK_ADDR_UNSPEC); if (msg->msg_namelen <= sizeof (union sockaddr_all) && msg->msg_namelen > sizeof (((struct sockaddr *)msg->msg_name)->sa_family)) { @@ -891,18 +893,23 @@ process_header(struct msghdr *msg, int msg_length, int sock_fd, int flags, SCK_SockaddrToIPSockAddr(msg->msg_name, msg->msg_namelen, &message->remote_addr.ip); break; case AF_UNIX: + /* Make sure the path is terminated by '\0' */ + max_path_len = sizeof (((struct sockaddr_un *)msg->msg_name)->sun_path); + path_len = strnlen(((struct sockaddr_un *)msg->msg_name)->sun_path, max_path_len); + if (path_len >= max_path_len) { + DEBUG_LOG("Unterminated path"); + r = 0; + break; + } init_message_addresses(message, SCK_ADDR_UNIX); message->remote_addr.path = ((struct sockaddr_un *)msg->msg_name)->sun_path; break; default: - init_message_addresses(message, SCK_ADDR_UNSPEC); DEBUG_LOG("Unexpected address"); r = 0; break; } } else { - init_message_addresses(message, SCK_ADDR_UNSPEC); - if (msg->msg_namelen > sizeof (union sockaddr_all)) { DEBUG_LOG("Truncated source address"); r = 0;