summaryrefslogtreecommitdiff
path: root/tools/lib
diff options
context:
space:
mode:
authorAndrii Nakryiko <andrii@kernel.org>2022-12-13 00:15:03 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-11 18:39:17 +0300
commit3938f01405d61fde44b25a960c2d6cc851c80467 (patch)
tree6dac6d911b145aab3a4047b9ee295b1b25985023 /tools/lib
parent1e950b9a841bc96e98ee25680d5c7aa305120be1 (diff)
downloadlinux-3938f01405d61fde44b25a960c2d6cc851c80467.tar.xz
libbpf: Fix btf__align_of() by taking into account field offsets
[ Upstream commit 25a4481b4136af7794e1df2d6c90ed2f354d60ce ] btf__align_of() is supposed to be return alignment requirement of a requested BTF type. For STRUCT/UNION it doesn't always return correct value, because it calculates alignment only based on field types. But for packed structs this is not enough, we need to also check field offsets and struct size. If field offset isn't aligned according to field type's natural alignment, then struct must be packed. Similarly, if struct size is not a multiple of struct's natural alignment, then struct must be packed as well. This patch fixes this issue precisely by additionally checking these conditions. Fixes: 3d208f4ca111 ("libbpf: Expose btf__align_of() API") Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20221212211505.558851-5-andrii@kernel.org Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/btf.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index e6f644cdc9f1..f7c48b1fb3a0 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -614,8 +614,21 @@ int btf__align_of(const struct btf *btf, __u32 id)
if (align <= 0)
return align;
max_align = max(max_align, align);
+
+ /* if field offset isn't aligned according to field
+ * type's alignment, then struct must be packed
+ */
+ if (btf_member_bitfield_size(t, i) == 0 &&
+ (m->offset % (8 * align)) != 0)
+ return 1;
}
+ /* if struct/union size isn't a multiple of its alignment,
+ * then struct must be packed
+ */
+ if ((t->size % max_align) != 0)
+ return 1;
+
return max_align;
}
default: