summaryrefslogtreecommitdiff
path: root/src/basic/socket-util.h
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-04-13 10:21:31 +0200
committerLennart Poettering <lennart@poettering.net>2023-04-13 10:21:31 +0200
commit79dec6f5cc0b72d43dfb0469fa68b5cd023fbaf9 (patch)
tree4fe1052bdd3b12837ee0bd9f942c3a4ae9e8dbd9 /src/basic/socket-util.h
parent39857544ee3794481f165e6ecc5d5a81c65f0ee9 (diff)
downloadsystemd-79dec6f5cc0b72d43dfb0469fa68b5cd023fbaf9.tar.gz
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)
Diffstat (limited to 'src/basic/socket-util.h')
-rw-r--r--src/basic/socket-util.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 0bfb29d417..7d504319a8 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; \
})