]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: tighten aignment check for CMSG_TYPED_DATA()
authorLennart Poettering <lennart@poettering.net>
Thu, 13 Apr 2023 08:21:31 +0000 (10:21 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 13 Apr 2023 08:21:31 +0000 (10:21 +0200)
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)

src/basic/socket-util.h

index 0bfb29d417550520c73a3425450b8a379a411143..7d504319a827cd1dcef7749bb632898e665f5510 100644 (file)
@@ -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; \
         })