]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
socket: drop messages from unterminated Unix paths
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 20 May 2025 14:02:09 +0000 (16:02 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 21 May 2025 10:41:13 +0000 (12:41 +0200)
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.

socket.c

index 80fafc7393473b532284e1026b9e6256df27b719..13ea69fb680c66a5e77d3ed35f63a2433ff80074 100644 (file)
--- 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;