From 6d88e4a4b43800ad2e5b6570052ef7e1c70b4d41 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Apr 2025 08:15:11 +0200 Subject: [PATCH 1/2] Revert "sd-netlink: prepare buffer for dropping unexpected message" This reverts commit bf478dcffbc3c568fb3a3c8e8b93b3e7b66f4228. I think we should avoid allocating memory needlessly just to free it again, in particular if this can be triggered by some rogue peer. --- src/libsystemd/sd-netlink/netlink-socket.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 5959959f42..9d2b3984c2 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -181,12 +181,6 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret log_debug("sd-netlink: ignoring message from PID %"PRIu32, sender.nl.nl_pid); if (peek) { - _cleanup_free_ uint8_t *b = new(uint8_t, n); - if (!b) - return -ENOMEM; - - iov = IOVEC_MAKE(b, n); - /* drop the message */ n = recvmsg_safe(fd, &msg, 0); if (n < 0) From 90755dac69dfb0c64e0e042aef0257c5dedb06c4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Apr 2025 08:19:43 +0200 Subject: [PATCH 2/2] netlink-socket: ignore ECHRNG/EXFULL errors from recvmsg_safe() if we expect truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we receive a netlink messages from userspace we need to drop it from the queue. Hence we need call recvmsg() on the socket for it. We do this with a zero-size socket read() buffer, so that the message would be truncated when copied to userspace, and we do not have to allocate any memory for it, but it's still dropped. This was broken in ad501930d749e00f9686d29692b3142c36914f31, which turned datagram truncation into an error (rightfully so I think – for the common case). That broke this code here, because here we *expect* truncation, and need to handle it gracefully. Hence simply check for the two error codes for truncated payload or cdata, and eat it up. --- src/libsystemd/sd-netlink/netlink-socket.c | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 9d2b3984c2..a6ac978930 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -162,11 +162,8 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret assert(peek || (buf && buf_size > 0)); 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; - } + if (ERRNO_IS_NEG_TRANSIENT(n)) + goto transient; if (n == -ENOBUFS) return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun"); if (n == -ECHRNG) @@ -181,15 +178,15 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret log_debug("sd-netlink: ignoring message from PID %"PRIu32, sender.nl.nl_pid); if (peek) { - /* drop the message */ + /* Drop the message. Note that we ignore ECHRNG/EXFULL errors here, which + * recvmsg_safe() returns in case the payload or cdata is truncated. Here it's quite + * likely it is truncated, because we pass a zero-sized buffer. */ n = recvmsg_safe(fd, &msg, 0); - if (n < 0) + if (n < 0 && !IN_SET(n, -ECHRNG, -EXFULL)) return (int) n; } - if (ret_mcast_group) - *ret_mcast_group = 0; - return 0; + goto transient; } if (ret_mcast_group) { @@ -203,6 +200,12 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret } return (int) n; + +transient: + if (ret_mcast_group) + *ret_mcast_group = 0; + + return 0; } DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(