2026-05-01
The asker is doing kernel security research and needs to know the exact byte offset of the portid field within struct netlink_sock. They're using two different methods to determine this offset and getting conflicting results: pahole (a DWARF debug info tool) reports offset 792, while offsetof() in a loaded kernel module reports a different value.
This is a deceptively tricky problem, and the discrepancy almost certainly comes from one of these sources:
pahole operates on a static vmlinux binary's DWARF info, while offsetof() runs against the headers the module was compiled with. If the vmlinux file doesn't correspond exactly to the running kernel (different config, different version, different compiler), struct layouts can silently differ. Even a single CONFIG_ option change can add or remove fields via #ifdef, shifting every subsequent member.CONFIG_RANDSTRUCT, which randomizes the layout of certain structs at compile time using a per-build seed. If enabled, pahole against one build's vmlinux will show a layout that doesn't match a module compiled against different randomized headers. This is specifically designed to break the kind of hardcoded-offset technique the asker is attempting.pahole is inspecting. Distro kernels sometimes ship debug symbols separately, and version skew between the linux-headers package and the linux-image-dbg package is a real hazard.The approach to resolving this:
uname -r should correspond to the vmlinux file, and /proc/config.gz (or /boot/config-$(uname -r)) should be the config used to build both.CONFIG_RANDSTRUCT and CONFIG_RANDSTRUCT_FULL in that config. If enabled, offsets are intentionally non-deterministic across builds.pahole against /sys/kernel/btf/vmlinux (BTF info from the running kernel) rather than a separate vmlinux file. This guarantees you're reading the layout of the actual running kernel: pahole -C netlink_sock /sys/kernel/btf/vmlinux.pr_info("portid offset: %lu\n", offsetof(struct netlink_sock, portid)); and compare against the BTF-derived value. These should agree.A subtle gotcha: if the struct definition includes a flexible array member or uses __randomize_layout annotation, the compiler is free to reorder fields. The DWARF info will reflect the actual compiled layout, but the source-level field order becomes meaningless.
