]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: make recvmsg_safe() handle MSG_TRUNC too 34212/head
authorMike Yuan <me@yhndnzj.com>
Fri, 30 Aug 2024 22:17:13 +0000 (00:17 +0200)
committerMike Yuan <me@yhndnzj.com>
Wed, 4 Sep 2024 16:51:44 +0000 (18:51 +0200)
Also, unify MSG_TRUNC handling all across the codebase.

16 files changed:
src/basic/socket-util.c
src/basic/socket-util.h
src/core/manager.c
src/import/importd.c
src/journal/journald-server.c
src/libsystemd/sd-device/device-monitor.c
src/libsystemd/sd-netlink/netlink-socket.c
src/machine/machine-dbus.c
src/nspawn/nspawn.c
src/resolve/resolved-manager.c
src/resolve/test-resolved-dummy-server.c
src/shared/ask-password-api.c
src/sysupdate/sysupdate-transfer.c
src/sysupdate/sysupdated.c
src/timesync/timesyncd-manager.c
src/udev/udev-ctrl.c

index c59c6a16a14924128457963e81e77b446a40e9a4..e4fb5a280cb97cad82ef61062aee412771663dbb 100644 (file)
@@ -1447,18 +1447,22 @@ int socket_bind_to_ifindex(int fd, int ifindex) {
 ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
         ssize_t n;
 
-        /* A wrapper around recvmsg() that checks for MSG_CTRUNC, and turns it into an error, in a reasonably
-         * safe way, closing any SCM_RIGHTS fds in the error path.
+        /* A wrapper around recvmsg() that checks for MSG_CTRUNC and MSG_TRUNC, and turns them into an error,
+         * in a reasonably safe way, closing any received fds in the error path.
          *
          * Note that unlike our usual coding style this might modify *msg on failure. */
 
+        assert(sockfd >= 0);
+        assert(msg);
+
         n = recvmsg(sockfd, msg, flags);
         if (n < 0)
                 return -errno;
 
-        if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC)) {
+        if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ||
+            (!FLAGS_SET(flags, MSG_PEEK) && FLAGS_SET(msg->msg_flags, MSG_TRUNC))) {
                 cmsg_close_all(msg);
-                return -EXFULL; /* a recognizable error code */
+                return FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ? -ECHRNG : -EXFULL;
         }
 
         return n;
index 18699a5349ed42f8fea7b3018b2586670e5ee919..64eb6d7cdaabdd5bdd85f6f53e6d2623e999bb23 100644 (file)
@@ -329,7 +329,7 @@ struct timespec_large {
 
 /* glibc duplicates timespec/timeval on certain 32-bit arches, once in 32-bit and once in 64-bit.
  * See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them
- * to prevent from recvmsg_safe() returning -EXFULL. */
+ * to prevent truncating control msg (recvmsg() MSG_CTRUNC). */
 #define CMSG_SPACE_TIMEVAL                                              \
         ((sizeof(struct timeval) == sizeof(struct timeval_large)) ?     \
          CMSG_SPACE(sizeof(struct timeval)) :                           \
index 3f6cb3944a7557aa2f6a398c7ab7c654714bb6de..85ab09be2abf76c1a65d68924e2e7e546727e03d 100644 (file)
@@ -2750,13 +2750,17 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
                 return 0;
         }
 
-        n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
+        n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
         if (ERRNO_IS_NEG_TRANSIENT(n))
                 return 0; /* Spurious wakeup, try again */
-        if (n == -EXFULL) {
+        if (n == -ECHRNG) {
                 log_warning_errno(n, "Got message with truncated control data (too many fds sent?), ignoring.");
                 return 0;
         }
+        if (n == -EXFULL) {
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
+                return 0;
+        }
         if (n < 0)
                 /* If this is any other, real error, then stop processing this socket. This of course means
                  * we won't take notification messages anymore, but that's still better than busy looping:
@@ -2829,11 +2833,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
                 return 0;
         }
 
-        if ((size_t) n >= sizeof(buf) || (msghdr.msg_flags & MSG_TRUNC)) {
-                log_warning("Received notify message exceeded maximum size. Ignoring.");
-                return 0;
-        }
-
         /* As extra safety check, let's make sure the string we get doesn't contain embedded NUL bytes.
          * We permit one trailing NUL byte in the message, but don't expect it. */
         if (n > 1 && memchr(buf, 0, n-1)) {
@@ -4932,11 +4931,15 @@ static int manager_dispatch_handoff_timestamp_fd(sd_event_source *source, int fd
 
         assert(source);
 
-        n = recvmsg_safe(m->handoff_timestamp_fds[0], &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
+        n = recvmsg_safe(m->handoff_timestamp_fds[0], &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
         if (ERRNO_IS_NEG_TRANSIENT(n))
                 return 0; /* Spurious wakeup, try again */
+        if (n == -ECHRNG) {
+                log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
+                return 0;
+        }
         if (n == -EXFULL) {
-                log_warning("Got message with truncated control, ignoring.");
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
                 return 0;
         }
         if (n < 0)
@@ -4944,10 +4947,6 @@ static int manager_dispatch_handoff_timestamp_fd(sd_event_source *source, int fd
 
         cmsg_close_all(&msghdr);
 
-        if (msghdr.msg_flags & MSG_TRUNC) {
-                log_warning("Got truncated handoff timestamp message, ignoring.");
-                return 0;
-        }
         if (n != sizeof(ts)) {
                 log_warning("Got handoff timestamp message of unexpected size %zi (expected %zu), ignoring.", n, sizeof(ts));
                 return 0;
index 79c2e45276cf194f52802cf694b2b633a6a56323..a0c40cc3d0380272ce477db3e5aab33bb68cc460 100644 (file)
@@ -633,7 +633,7 @@ static Manager *manager_unref(Manager *m) {
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
 
 static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-
+        Manager *m = ASSERT_PTR(userdata);
         char buf[NOTIFY_BUFFER_MAX+1];
         struct iovec iovec = {
                 .iov_base = buf,
@@ -647,33 +647,32 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
         };
-        struct ucred *ucred;
-        Manager *m = userdata;
-        Transfer *t;
         ssize_t n;
-        char *p;
         int r;
 
         n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
-        if (n < 0) {
-                if (ERRNO_IS_TRANSIENT(n))
-                        return 0;
-                return (int) n;
+        if (ERRNO_IS_NEG_TRANSIENT(n))
+                return 0;
+        if (n == -ECHRNG) {
+                log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
+                return 0;
         }
-
-        cmsg_close_all(&msghdr);
-
-        if (msghdr.msg_flags & MSG_TRUNC) {
-                log_warning("Got overly long notification datagram, ignoring.");
+        if (n == -EXFULL) {
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
                 return 0;
         }
+        if (n < 0)
+                return (int) n;
 
-        ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
+        cmsg_close_all(&msghdr);
+
+        struct ucred *ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (!ucred || ucred->pid <= 0) {
                 log_warning("Got notification datagram lacking credential information, ignoring.");
                 return 0;
         }
 
+        Transfer *t;
         HASHMAP_FOREACH(t, m->transfers)
                 if (ucred->pid == t->pidref.pid)
                         break;
@@ -685,7 +684,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
 
         buf[n] = 0;
 
-        p = find_line_startswith(buf, "X_IMPORT_PROGRESS=");
+        char *p = find_line_startswith(buf, "X_IMPORT_PROGRESS=");
         if (!p)
                 return 0;
 
index 66f09e49453a245828e57f5a122c5b09eebc4eed..6198454bd5735472ec27e1f609417a23e0982ba8 100644 (file)
@@ -1549,39 +1549,42 @@ int server_process_datagram(
         iovec = IOVEC_MAKE(s->buffer, MALLOC_ELEMENTSOF(s->buffer) - 1); /* Leave room for trailing NUL we add later */
 
         n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
-        if (n < 0) {
-                if (ERRNO_IS_TRANSIENT(n))
-                        return 0;
-                if (n == -EXFULL) {
-                        log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
-                                              "Got message with truncated control data (too many fds sent?), ignoring.");
-                        return 0;
-                }
-                return log_ratelimit_error_errno(n, JOURNAL_LOG_RATELIMIT, "recvmsg() failed: %m");
+        if (ERRNO_IS_NEG_TRANSIENT(n))
+                return 0;
+        if (n == -ECHRNG) {
+                log_ratelimit_warning_errno(n, JOURNAL_LOG_RATELIMIT,
+                                            "Got message with truncated control data (too many fds sent?), ignoring.");
+                return 0;
         }
+        if (n == -EXFULL) {
+                log_ratelimit_warning_errno(n, JOURNAL_LOG_RATELIMIT, "Got message with truncated payload data, ignoring.");
+                return 0;
+        }
+        if (n < 0)
+                return log_ratelimit_error_errno(n, JOURNAL_LOG_RATELIMIT, "Failed to receive message: %m");
 
-        CMSG_FOREACH(cmsg, &msghdr)
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                    cmsg->cmsg_type == SCM_CREDENTIALS &&
+        CMSG_FOREACH(cmsg, &msghdr) {
+                if (cmsg->cmsg_level != SOL_SOCKET)
+                        continue;
+
+                if (cmsg->cmsg_type == SCM_CREDENTIALS &&
                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
                         assert(!ucred);
                         ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
-                } else if (cmsg->cmsg_level == SOL_SOCKET &&
-                         cmsg->cmsg_type == SCM_SECURITY) {
+                } else if (cmsg->cmsg_type == SCM_SECURITY) {
                         assert(!label);
                         label = CMSG_TYPED_DATA(cmsg, char);
                         label_len = cmsg->cmsg_len - CMSG_LEN(0);
-                } else if (cmsg->cmsg_level == SOL_SOCKET &&
-                           cmsg->cmsg_type == SCM_TIMESTAMP &&
+                } else if (cmsg->cmsg_type == SCM_TIMESTAMP &&
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
                         assert(!tv);
                         tv = memcpy(&tv_buf, CMSG_DATA(cmsg), sizeof(struct timeval));
-                } else if (cmsg->cmsg_level == SOL_SOCKET &&
-                         cmsg->cmsg_type == SCM_RIGHTS) {
+                } else if (cmsg->cmsg_type == SCM_RIGHTS) {
                         assert(!fds);
                         fds = CMSG_TYPED_DATA(cmsg, int);
                         n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
                 }
+        }
 
         /* And a trailing NUL, just in case */
         s->buffer[n] = 0;
index 287fb8d9f27658cb6b722c5238d0e2a4b8bc8fb9..d2892c4d3c09b1018658b50b5e6ac854fe34717f 100644 (file)
@@ -600,16 +600,15 @@ _public_ int sd_device_monitor_receive(sd_device_monitor *m, sd_device **ret) {
 
         iov = IOVEC_MAKE(message.buf, n);
 
-        n = recvmsg(m->sock, &smsg, 0);
+        n = recvmsg_safe(m->sock, &smsg, 0);
         if (n < 0) {
-                if (!ERRNO_IS_TRANSIENT(errno))
-                        log_monitor_errno(m, errno, "Failed to receive message: %m");
-                return -errno;
+                if (!ERRNO_IS_NEG_TRANSIENT(n))
+                        log_monitor_errno(m, n, "Failed to receive message: %s",
+                                          n == -ECHRNG ? "got truncated control data" :
+                                          n == -EXFULL ? "got truncated payload data" :
+                                          STRERROR((int) n));
+                return n;
         }
-
-        if (smsg.msg_flags & MSG_TRUNC)
-                return log_monitor_errno(m, SYNTHETIC_ERRNO(EINVAL), "Received truncated message, ignoring message.");
-
         if (n < 32)
                 return log_monitor_errno(m, SYNTHETIC_ERRNO(EINVAL), "Invalid message length (%zi), ignoring message.", n);
 
index 79729decbc2d235d92eea41f5a3d7aee8024ec9f..55a80e0f4c91bdf4e4592dfa11b200804baeb82c 100644 (file)
@@ -176,14 +176,19 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret
         assert(fd >= 0);
         assert(peek || (buf && buf_size > 0));
 
-        n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
-        if (n == -ENOBUFS)
-                return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
-        else if (ERRNO_IS_NEG_TRANSIENT(n)) {
+        n = recvmsg_safe(fd, &msg, peek ? (MSG_PEEK|MSG_TRUNC) : 0);
+        if (ERRNO_IS_NEG_TRANSIENT(n)) {
                 if (ret_mcast_group)
                         *ret_mcast_group = 0;
                 return 0;
-        } else if (n < 0)
+        }
+        if (n == -ENOBUFS)
+                return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
+        if (n == -ECHRNG)
+                return log_debug_errno(n, "sd-netlink: got truncated control message");
+        if (n == -EXFULL)
+                return log_debug_errno(n, "sd-netlink: got truncated payload message");
+        if (n < 0)
                 return (int) n;
 
         if (sender.nl.nl_pid != 0) {
@@ -202,9 +207,6 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret
                 return 0;
         }
 
-        if (!peek && (size_t) n > buf_size) /* message did not fit in read buffer */
-                return -EIO;
-
         if (ret_mcast_group) {
                 struct nl_pktinfo *pi;
 
index 49ec710df0e900d6b961e714b6b08894eedc9d8f..783463896f61a807ac113f594218b507cf2d3087 100644 (file)
@@ -282,9 +282,9 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
                         iov[0] = IOVEC_MAKE(&family, sizeof(family));
                         iov[1] = IOVEC_MAKE(&in_addr, sizeof(in_addr));
 
-                        n = recvmsg(pair[0], &mh, 0);
+                        n = recvmsg_safe(pair[0], &mh, 0);
                         if (n < 0)
-                                return -errno;
+                                return n;
                         if ((size_t) n < sizeof(family))
                                 break;
 
index 9cd52e06c08629cc54b14db710e41be49e6ad066..2694b11f1429fd15e0c8f6aecf56d9291775ed19 100644 (file)
@@ -4485,10 +4485,15 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
         n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
         if (ERRNO_IS_NEG_TRANSIENT(n))
                 return 0;
-        else if (n == -EXFULL) {
-                log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
+        if (n == -ECHRNG) {
+                log_warning_errno(n, "Got message with truncated control data (too many fds sent?), ignoring.");
                 return 0;
-        } else if (n < 0)
+        }
+        if (n == -EXFULL) {
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
+                return 0;
+        }
+        if (n < 0)
                 return log_warning_errno(n, "Couldn't read notification socket: %m");
 
         cmsg_close_all(&msghdr);
@@ -4499,11 +4504,6 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
                 return 0;
         }
 
-        if ((size_t) n >= sizeof(buf)) {
-                log_warning("Received notify message exceeded maximum size. Ignoring.");
-                return 0;
-        }
-
         buf[n] = 0;
         tags = strv_split(buf, "\n\r");
         if (!tags)
index 046f8dd1ce1fe3a5491d2399e201ec4a09e833d2..210a71c9d55c931143f1802d8ef8fb85d1d018ca 100644 (file)
@@ -867,8 +867,6 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
         if (l <= 0)
                 return l;
 
-        assert(!(mh.msg_flags & MSG_TRUNC));
-
         p->size = (size_t) l;
 
         p->family = sa.sa.sa_family;
index 58257d7832202bc625e87a51090e784a73672550..a47fafa2a6f0057c45f2e7e28c56e0ca9456e15a 100644 (file)
@@ -53,8 +53,6 @@ static int server_recv(int fd, DnsPacket **ret) {
         if (l <= 0)
                 return l;
 
-        assert(!(mh.msg_flags & MSG_TRUNC));
-
         p->size = (size_t) l;
 
         p->family = sa.sa.sa_family;
index 7706c3c2719a02a72a6a56dec01ed3b8753f811a..135f19706e7ac3cb8f3a3d8b2edab5f3b0c9793e 100644 (file)
@@ -873,10 +873,15 @@ int ask_password_agent(
                 n = recvmsg_safe(socket_fd, &msghdr, 0);
                 if (ERRNO_IS_NEG_TRANSIENT(n))
                         continue;
-                else if (n == -EXFULL) {
-                        log_debug("Got message with truncated control data, ignoring.");
+                if (n == -ECHRNG) {
+                        log_debug_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
                         continue;
-                } else if (n < 0) {
+                }
+                if (n == -EXFULL) {
+                        log_debug_errno(n, "Got message with truncated payload data, ignoring.");
+                        continue;
+                }
+                if (n < 0) {
                         r = (int) n;
                         goto finish;
                 }
index 7ea168961e4928958b5b22db2f966d17263814b5..cbf3f77f5bfd903fe9afd13b5a3083133298ea04 100644 (file)
@@ -938,18 +938,20 @@ static int helper_on_notify(sd_event_source *s, int fd, uint32_t revents, void *
         int r;
 
         n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
-        if (n < 0) {
-                if (ERRNO_IS_TRANSIENT(n))
-                        return 0;
-                return (int) n;
+        if (ERRNO_IS_NEG_TRANSIENT(n))
+                return 0;
+        if (n == -ECHRNG) {
+                log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
+                return 0;
         }
-
-        cmsg_close_all(&msghdr);
-
-        if (msghdr.msg_flags & MSG_TRUNC) {
-                log_warning("Got overly long notification datagram, ignoring.");
+        if (n == -EXFULL) {
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
                 return 0;
         }
+        if (n < 0)
+                return (int) n;
+
+        cmsg_close_all(&msghdr);
 
         ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (!ucred || ucred->pid <= 0) {
index 6f15177c94eb10e20871b426bfc28acb58e9e2b2..546f52a96ce5304f54a76597125f959902447c02 100644 (file)
@@ -419,7 +419,7 @@ static int job_start(Job *j) {
 
         if (IN_SET(j->type, JOB_UPDATE, JOB_VACUUM) && j->target->busy)
                 return log_notice_errno(SYNTHETIC_ERRNO(EBUSY), "Target %s busy, ignoring job.", j->target->name);
-                
+
         stdout_fd = memfd_new("sysupdate-stdout");
         if (stdout_fd < 0)
                 return log_error_errno(stdout_fd, "Failed to create memfd: %m");
@@ -1460,18 +1460,20 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
         char *version, *progress, *errno_str, *ready;
 
         n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
-        if (n < 0) {
-                if (ERRNO_IS_TRANSIENT(n))
-                        return 0;
-                return (int) n;
+        if (ERRNO_IS_NEG_TRANSIENT(n))
+                return 0;
+        if (n == -ECHRNG) {
+                log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
+                return 0;
         }
-
-        cmsg_close_all(&msghdr);
-
-        if (msghdr.msg_flags & MSG_TRUNC) {
-                log_warning("Got overly long notification datagram, ignoring.");
+        if (n == -EXFULL) {
+                log_warning_errno(n, "Got message with truncated payload data, ignoring.");
                 return 0;
         }
+        if (n < 0)
+                return (int) n;
+
+        cmsg_close_all(&msghdr);
 
         ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (!ucred || ucred->pid <= 0) {
index faf894fb47fc5750e5c6856fa1b6565f191f0471..5f16ed2b9480d361efb22de6f1ee9f4558b65bbb 100644 (file)
@@ -423,15 +423,18 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
         }
 
         len = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
-        if (len == -EAGAIN)
+        if (ERRNO_IS_NEG_TRANSIENT(len))
                 return 0;
         if (len < 0) {
-                log_warning_errno(len, "Error receiving message, disconnecting: %m");
+                log_warning_errno(len, "Error receiving message, disconnecting: %s",
+                                  len == -ECHRNG ? "got truncated control data" :
+                                  len == -EXFULL ? "got truncated payload data" :
+                                  STRERROR((int) len));
                 return manager_connect(m);
         }
 
-        /* Too short or too long packet? */
-        if (iov.iov_len < sizeof(struct ntp_msg) || (msghdr.msg_flags & MSG_TRUNC)) {
+        /* Too short packet? */
+        if (iov.iov_len < sizeof(struct ntp_msg)) {
                 log_warning("Invalid response from server. Disconnecting.");
                 return manager_connect(m);
         }
index 34cd6665d4c25e90a737adc9ec6ce07e14625bcd..56da1fb353d5a2fbe5794b3919e9e5bfeb7e0aac 100644 (file)
@@ -170,14 +170,22 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
         uctrl = udev_ctrl_ref(userdata);
 
         size = recvmsg_safe(fd, &smsg, 0);
-        if (size == -EINTR)
+        if (ERRNO_IS_NEG_TRANSIENT(size))
                 return 0;
+        if (size == -ECHRNG) {
+                log_warning_errno(size, "Got message with truncated control data (unexpected fds sent?), ignoring.");
+                return 0;
+        }
+        if (size == -EXFULL) {
+                log_warning_errno(size, "Got message with truncated payload data, ignoring.");
+                return 0;
+        }
         if (size < 0)
                 return log_error_errno(size, "Failed to receive ctrl message: %m");
 
         cmsg_close_all(&smsg);
 
-        if (size != sizeof(msg_wire) || FLAGS_SET(smsg->flags, MSG_TRUNC)) {
+        if (size != sizeof(msg_wire)) {
                 log_warning("Received message with invalid length, ignoring");
                 return 0;
         }