]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: don't play games with alignment around file_handle
authorLennart Poettering <lennart@poettering.net>
Mon, 18 Aug 2025 07:09:59 +0000 (09:09 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 18 Aug 2025 12:50:55 +0000 (21:50 +0900)
The payload of a file_handle structure is not 64bit aligned. So far used
_alignas_() to align it to 64bit as a whole, which by accident has the
side-effect that the payload ends up being aligned to 64bit too, but
this is ugly, because it's really just an accident...

Let's do this properly, and just use proper unaligned 64bit reads to
access the field, and do not assume aligning the structure as a whole
also aligns the payload part of it.

Follow-up for: fd51a7d8b5b1c710c3b59e877bc35b2739dcc350

src/basic/cgroup-util.c
src/basic/pidfd-util.c

index 6b84cc48c648579ff190b86109253ed4240b5968..5de64d990ecb7a75de0dd5f87e15744094c085be 100644 (file)
@@ -30,6 +30,7 @@
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
+#include "unaligned.h"
 #include "unit-name.h"
 #include "user-util.h"
 #include "xattr-util.h"
@@ -38,7 +39,7 @@
 typedef union {
         struct file_handle file_handle;
         uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)];
-} _alignas_(uint64_t) cg_file_handle;
+} cg_file_handle;
 
 #define CG_FILE_HANDLE_INIT                                     \
         (cg_file_handle) {                                      \
@@ -46,7 +47,8 @@ typedef union {
                 .file_handle.handle_type = FILEID_KERNFS,       \
         }
 
-#define CG_FILE_HANDLE_CGROUPID(fh) (*CAST_ALIGN_PTR(uint64_t, (fh).file_handle.f_handle))
+/* The .f_handle field is not aligned to 64bit on some archs, hence read it via an unaligned accessor */
+#define CG_FILE_HANDLE_CGROUPID(fh) unaligned_read_ne64(fh.file_handle.f_handle)
 
 int cg_path_open(const char *controller, const char *path) {
         _cleanup_free_ char *fs = NULL;
@@ -71,7 +73,7 @@ int cg_cgroupid_open(int cgroupfs_fd, uint64_t id) {
         }
 
         cg_file_handle fh = CG_FILE_HANDLE_INIT;
-        CG_FILE_HANDLE_CGROUPID(fh) = id;
+        unaligned_write_ne64(fh.file_handle.f_handle, id);
 
         return RET_NERRNO(open_by_handle_at(cgroupfs_fd, &fh.file_handle, O_DIRECTORY|O_CLOEXEC));
 }
index 328ed70d5291d4f44bc692a2bca965e19cbd021c..9910819aa79d949258cf2c970996d823b234b103 100644 (file)
@@ -16,6 +16,7 @@
 #include "stat-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
+#include "unaligned.h"
 
 static thread_local int have_pidfs = -1;
 
@@ -239,7 +240,7 @@ int pidfd_get_inode_id_impl(int fd, uint64_t *ret) {
                 union {
                         struct file_handle file_handle;
                         uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)];
-                } _alignas_(uint64_t) fh = {
+                } fh = {
                         .file_handle.handle_bytes = sizeof(uint64_t),
                         .file_handle.handle_type = FILEID_KERNFS,
                 };
@@ -248,7 +249,8 @@ int pidfd_get_inode_id_impl(int fd, uint64_t *ret) {
                 r = RET_NERRNO(name_to_handle_at(fd, "", &fh.file_handle, &mnt_id, AT_EMPTY_PATH));
                 if (r >= 0) {
                         if (ret)
-                                *ret = *CAST_ALIGN_PTR(uint64_t, fh.file_handle.f_handle);
+                                /* Note, "struct file_handle" is 32bit aligned usually, but we need to read a 64bit value from it */
+                                *ret = unaligned_read_ne64(fh.file_handle.f_handle);
                         return 0;
                 }
                 assert(r != -EOVERFLOW);