From: Zbigniew Jędrzejewski-Szmek Date: Thu, 17 Jul 2025 14:35:01 +0000 (+0200) Subject: basic/socket-util: reserve more space for timeval/timespec messages X-Git-Tag: v257.8~94 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=36a22a9f96d944efbb6ff5682f940bfab0366bc8;p=thirdparty%2Fsystemd.git basic/socket-util: reserve more space for timeval/timespec messages As reported in https://github.com/systemd/systemd/issues/38222, we get the buffer size calculation wrong on 32-bit arm. The reporter suggested checking if __TIMESIZE == 64, but I think it's better to just use the bigger size in all cases. The code to guesstimate the buffer size was already tweaked a few times and apparently it's not easy to get it right. Systemd and glibc might be compiled with different combinations of __TIMESIZE, so the compile-time check is not super reliable, and by using the bigger size, we don't depend on the details of how glibc decided whether to duplicate the struct or not. The cost is negligible, 16 bytes on stack, so let's do the easy and robust thing. Solution based on the suggestion by UZver24. While at it, drop the mock struct definitions. They are only used to calculate the size, but since the types involved are 8-bit values, there are no alignment issues and we can just calculate the size directly. Fixes https://github.com/systemd/systemd/issues/38222. (cherry picked from commit 0c927c98a7ba58e036a34f705c2a6b366107b6ea) --- diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 013edf0d4ff..57d1e4a8ce5 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -321,27 +321,14 @@ static inline int getsockopt_int(int fd, int level, int optname, int *ret) { int socket_bind_to_ifname(int fd, const char *ifname); int socket_bind_to_ifindex(int fd, int ifindex); -/* Define a 64-bit version of timeval/timespec in any case, even on 32-bit userspace. */ -struct timeval_large { - uint64_t tvl_sec, tvl_usec; -}; -struct timespec_large { - uint64_t tvl_sec, tvl_nsec; -}; /* 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 truncating control msg (recvmsg() MSG_CTRUNC). */ #define CMSG_SPACE_TIMEVAL \ - ((sizeof(struct timeval) == sizeof(struct timeval_large)) ? \ - CMSG_SPACE(sizeof(struct timeval)) : \ - CMSG_SPACE(sizeof(struct timeval)) + \ - CMSG_SPACE(sizeof(struct timeval_large))) + (CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(2 * sizeof(uint64_t))) #define CMSG_SPACE_TIMESPEC \ - ((sizeof(struct timespec) == sizeof(struct timespec_large)) ? \ - CMSG_SPACE(sizeof(struct timespec)) : \ - CMSG_SPACE(sizeof(struct timespec)) + \ - CMSG_SPACE(sizeof(struct timespec_large))) + (CMSG_SPACE(sizeof(struct timespec)) + CMSG_SPACE(2 * sizeof(uint64_t))) ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);