DEFINE_TRIVIAL_CLEANUP_FUNC(struct restrict_fsaccess_bpf *, restrict_fsaccess_bpf_free);
-/* Verify that restrict_fsaccess_bss matches the skeleton's .bss layout. The sizeof
- * check catches field additions/removals; the offsetof checks catch field
- * reordering. Field order in restrict_fsaccess_bss must match the BPF global
- * declaration order in restrict-fsaccess.bpf.c — this is what bpftool uses for the
- * generated struct. The read-modify-write in restrict_fsaccess_clear_initramfs_trust()
- * depends on this layout. */
-assert_cc(sizeof(struct restrict_fsaccess_bss) == sizeof_field(struct restrict_fsaccess_bpf, bss[0]));
-assert_cc(offsetof(struct restrict_fsaccess_bss, initramfs_s_dev) ==
- offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]), initramfs_s_dev));
-assert_cc(offsetof(struct restrict_fsaccess_bss, protected_map_id_verity) ==
- offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]), protected_map_id_verity));
-assert_cc(offsetof(struct restrict_fsaccess_bss, protected_map_id_bss) ==
- offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]), protected_map_id_bss));
+/* Offset of initramfs_s_dev within the BPF program's .bss section, taken from
+ * the generated skeleton so it matches whichever BPF compiler (clang or gcc)
+ * emitted the object. clang and gcc do not necessarily place .bss globals in
+ * source declaration order, so the offset must come from the skeleton rather
+ * than a hand-maintained mirror struct. restrict_fsaccess_clear_initramfs_trust()
+ * mmaps the .bss map and clears this field via a single store. */
+#define INITRAMFS_S_DEV_OFF \
+ offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]), initramfs_s_dev)
+/* The single aligned 32-bit store in restrict_fsaccess_clear_initramfs_trust()
+ * is only atomic if the field is 4-byte aligned. */
+assert_cc(INITRAMFS_S_DEV_OFF % sizeof(uint32_t) == 0);
/* Build the skeleton links array indexed by the link enum.
* For BDEV_SETINTEGRITY, use whichever variant was loaded (full or compat).
void *p;
assert(bss_map_fd >= 0);
- assert_cc(offsetof(struct restrict_fsaccess_bss, initramfs_s_dev) == 0);
p = mmap(NULL, page_size(), PROT_READ | PROT_WRITE, MAP_SHARED, bss_map_fd, 0);
if (p == MAP_FAILED)
return log_error_errno(errno, "bpf-restrict-fsaccess: Failed to mmap .bss map: %m");
- /* initramfs_s_dev is at offset 0 in the .bss layout. Single aligned
- * 32-bit store is atomic — BPF programs see either the old or new value,
- * no torn reads possible. Guard globals are untouched. */
- *(uint32_t *) p = 0;
+ /* Single aligned 32-bit store at INITRAMFS_S_DEV_OFF is atomic — BPF
+ * programs see either the old or new value, no torn reads possible.
+ * Guard globals are untouched. */
+ *(uint32_t *) ((uint8_t *) p + INITRAMFS_S_DEV_OFF) = 0;
/* munmap failure here is harmless: the clear above already landed in
* the kernel, and the mapping is discarded by exec anyway. */
/* Maximum number of dm-verity devices tracked in the BPF hash map. */
#define DMVERITY_DEVICES_MAX (16U*1024U)
-/* Mirrors the BPF program's .bss section layout for read-modify-write via
- * bpf_map_lookup_elem/bpf_map_update_elem on the serialized .bss map FD. */
-struct restrict_fsaccess_bss {
- uint32_t initramfs_s_dev; /* kernel dev_t encoding: (major << 20) | minor */
- uint32_t protected_map_id_verity;
- uint32_t protected_map_id_bss;
- uint32_t protected_prog_ids[_RESTRICT_FILESYSTEM_ACCESS_LINK_MAX];
- uint32_t protected_link_ids[_RESTRICT_FILESYSTEM_ACCESS_LINK_MAX];
-};
-
extern const char* const restrict_fsaccess_link_names[_RESTRICT_FILESYSTEM_ACCESS_LINK_MAX];
bool dm_verity_require_signatures(void);