From: Lennart Poettering Date: Thu, 13 Apr 2023 08:21:31 +0000 (+0200) Subject: socket-util: tighten aignment check for CMSG_TYPED_DATA() X-Git-Tag: v254-rc1~721^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=79dec6f5cc0b72d43dfb0469fa68b5cd023fbaf9;p=thirdparty%2Fsystemd.git socket-util: tighten aignment check for CMSG_TYPED_DATA() Apparently CMSG_DATA() alignment is very much undefined. Which is quite an ABI fuck-up, but we need to deal with this. CMSG_TYPED_DATA() already checks alignment of the specified pointer. Let's also check matching alignment of the underlying structures, which we already can do at compile-time. See: #27241 (This does not fix #27241, but should catch such errors already at compile-time instead of runtime) --- diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 0bfb29d4175..7d504319a82 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -175,9 +175,16 @@ int flush_accept(int fd); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) +/* Returns the cmsghdr's data pointer, but safely cast to the specified type. Does two alignment checks: one + * at compile time, that the requested type has a smaller or same alignment as 'struct cmsghdr', and one + * during runtime, that the actual pointer matches the alignment too. This is supposed to catch cases such as + * 'struct timeval' is embedded into 'struct cmsghdr' on architectures where the alignment of the former is 8 + * bytes (because of a 64bit time_t), but of the latter is 4 bytes (because size_t is 32bit), such as + * riscv32. */ #define CMSG_TYPED_DATA(cmsg, type) \ ({ \ struct cmsghdr *_cmsg = cmsg; \ + assert_cc(__alignof__(type) <= __alignof__(struct cmsghdr)); \ _cmsg ? CAST_ALIGN_PTR(type, CMSG_DATA(_cmsg)) : (type*) NULL; \ })