From: Sasha Levin Date: Mon, 3 Apr 2023 13:01:57 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v4.14.312~15^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=66bd6b31e20418ae8852a38c4d63a13bba4820cd;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/libbpf-fix-btf-to-c-converter-s-padding-logic.patch b/queue-5.10/libbpf-fix-btf-to-c-converter-s-padding-logic.patch new file mode 100644 index 00000000000..8edde392276 --- /dev/null +++ b/queue-5.10/libbpf-fix-btf-to-c-converter-s-padding-logic.patch @@ -0,0 +1,426 @@ +From e5069d615aea9c6ffee024193f173458f6043116 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 13:15:04 -0800 +Subject: libbpf: Fix BTF-to-C converter's padding logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andrii Nakryiko + +[ Upstream commit ea2ce1ba99aa6a60c8d8a706e3abadf3de372163 ] + +Turns out that btf_dump API doesn't handle a bunch of tricky corner +cases, as reported by Per, and further discovered using his testing +Python script ([0]). + +This patch revamps btf_dump's padding logic significantly, making it +more correct and also avoiding unnecessary explicit padding, where +compiler would pad naturally. This overall topic turned out to be very +tricky and subtle, there are lots of subtle corner cases. The comments +in the code tries to give some clues, but comments themselves are +supposed to be paired with good understanding of C alignment and padding +rules. Plus some experimentation to figure out subtle things like +whether `long :0;` means that struct is now forced to be long-aligned +(no, it's not, turns out). + +Anyways, Per's script, while not completely correct in some known +situations, doesn't show any obvious cases where this logic breaks, so +this is a nice improvement over the previous state of this logic. + +Some selftests had to be adjusted to accommodate better use of natural +alignment rules, eliminating some unnecessary padding, or changing it to +`type: 0;` alignment markers. + +Note also that for when we are in between bitfields, we emit explicit +bit size, while otherwise we use `: 0`, this feels much more natural in +practice. + +Next patch will add few more test cases, found through randomized Per's +script. + + [0] https://lore.kernel.org/bpf/85f83c333f5355c8ac026f835b18d15060725fcb.camel@ericsson.com/ + +Reported-by: Per Sundström XP +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20221212211505.558851-6-andrii@kernel.org +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf_dump.c | 169 +++++++++++++----- + .../bpf/progs/btf_dump_test_case_bitfields.c | 2 +- + .../bpf/progs/btf_dump_test_case_padding.c | 58 ++++-- + 3 files changed, 164 insertions(+), 65 deletions(-) + +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index 0e2d63da24e91..4d27b08074a56 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -788,6 +788,25 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) + } + } + ++static int btf_natural_align_of(const struct btf *btf, __u32 id) ++{ ++ const struct btf_type *t = btf__type_by_id(btf, id); ++ int i, align, vlen; ++ const struct btf_member *m; ++ ++ if (!btf_is_composite(t)) ++ return btf__align_of(btf, id); ++ ++ align = 1; ++ m = btf_members(t); ++ vlen = btf_vlen(t); ++ for (i = 0; i < vlen; i++, m++) { ++ align = max(align, btf__align_of(btf, m->type)); ++ } ++ ++ return align; ++} ++ + static bool btf_is_struct_packed(const struct btf *btf, __u32 id, + const struct btf_type *t) + { +@@ -795,16 +814,16 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id, + int align, i, bit_sz; + __u16 vlen; + +- align = btf__align_of(btf, id); +- /* size of a non-packed struct has to be a multiple of its alignment*/ +- if (align && t->size % align) ++ align = btf_natural_align_of(btf, id); ++ /* size of a non-packed struct has to be a multiple of its alignment */ ++ if (align && (t->size % align) != 0) + return true; + + m = btf_members(t); + vlen = btf_vlen(t); + /* all non-bitfield fields have to be naturally aligned */ + for (i = 0; i < vlen; i++, m++) { +- align = btf__align_of(btf, m->type); ++ align = btf_natural_align_of(btf, m->type); + bit_sz = btf_member_bitfield_size(t, i); + if (align && bit_sz == 0 && m->offset % (8 * align) != 0) + return true; +@@ -817,44 +836,97 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id, + return false; + } + +-static int chip_away_bits(int total, int at_most) +-{ +- return total % at_most ? : at_most; +-} +- + static void btf_dump_emit_bit_padding(const struct btf_dump *d, +- int cur_off, int m_off, int m_bit_sz, +- int align, int lvl) ++ int cur_off, int next_off, int next_align, ++ bool in_bitfield, int lvl) + { +- int off_diff = m_off - cur_off; +- int ptr_bits = d->ptr_sz * 8; ++ const struct { ++ const char *name; ++ int bits; ++ } pads[] = { ++ {"long", d->ptr_sz * 8}, {"int", 32}, {"short", 16}, {"char", 8} ++ }; ++ int new_off, pad_bits, bits, i; ++ const char *pad_type; ++ ++ if (cur_off >= next_off) ++ return; /* no gap */ ++ ++ /* For filling out padding we want to take advantage of ++ * natural alignment rules to minimize unnecessary explicit ++ * padding. First, we find the largest type (among long, int, ++ * short, or char) that can be used to force naturally aligned ++ * boundary. Once determined, we'll use such type to fill in ++ * the remaining padding gap. In some cases we can rely on ++ * compiler filling some gaps, but sometimes we need to force ++ * alignment to close natural alignment with markers like ++ * `long: 0` (this is always the case for bitfields). Note ++ * that even if struct itself has, let's say 4-byte alignment ++ * (i.e., it only uses up to int-aligned types), using `long: ++ * X;` explicit padding doesn't actually change struct's ++ * overall alignment requirements, but compiler does take into ++ * account that type's (long, in this example) natural ++ * alignment requirements when adding implicit padding. We use ++ * this fact heavily and don't worry about ruining correct ++ * struct alignment requirement. ++ */ ++ for (i = 0; i < ARRAY_SIZE(pads); i++) { ++ pad_bits = pads[i].bits; ++ pad_type = pads[i].name; + +- if (off_diff <= 0) +- /* no gap */ +- return; +- if (m_bit_sz == 0 && off_diff < align * 8) +- /* natural padding will take care of a gap */ +- return; ++ new_off = roundup(cur_off, pad_bits); ++ if (new_off <= next_off) ++ break; ++ } + +- while (off_diff > 0) { +- const char *pad_type; +- int pad_bits; +- +- if (ptr_bits > 32 && off_diff > 32) { +- pad_type = "long"; +- pad_bits = chip_away_bits(off_diff, ptr_bits); +- } else if (off_diff > 16) { +- pad_type = "int"; +- pad_bits = chip_away_bits(off_diff, 32); +- } else if (off_diff > 8) { +- pad_type = "short"; +- pad_bits = chip_away_bits(off_diff, 16); +- } else { +- pad_type = "char"; +- pad_bits = chip_away_bits(off_diff, 8); ++ if (new_off > cur_off && new_off <= next_off) { ++ /* We need explicit `: 0` aligning mark if next ++ * field is right on alignment offset and its ++ * alignment requirement is less strict than 's ++ * alignment (so compiler won't naturally align to the ++ * offset we expect), or if subsequent `: X`, ++ * will actually completely fit in the remaining hole, ++ * making compiler basically ignore `: X` ++ * completely. ++ */ ++ if (in_bitfield || ++ (new_off == next_off && roundup(cur_off, next_align * 8) != new_off) || ++ (new_off != next_off && next_off - new_off <= new_off - cur_off)) ++ /* but for bitfields we'll emit explicit bit count */ ++ btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, ++ in_bitfield ? new_off - cur_off : 0); ++ cur_off = new_off; ++ } ++ ++ /* Now we know we start at naturally aligned offset for a chosen ++ * padding type (long, int, short, or char), and so the rest is just ++ * a straightforward filling of remaining padding gap with full ++ * `: sizeof();` markers, except for the last one, which ++ * might need smaller than sizeof() padding. ++ */ ++ while (cur_off != next_off) { ++ bits = min(next_off - cur_off, pad_bits); ++ if (bits == pad_bits) { ++ btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits); ++ cur_off += bits; ++ continue; ++ } ++ /* For the remainder padding that doesn't cover entire ++ * pad_type bit length, we pick the smallest necessary type. ++ * This is pure aesthetics, we could have just used `long`, ++ * but having smallest necessary one communicates better the ++ * scale of the padding gap. ++ */ ++ for (i = ARRAY_SIZE(pads) - 1; i >= 0; i--) { ++ pad_type = pads[i].name; ++ pad_bits = pads[i].bits; ++ if (pad_bits < bits) ++ continue; ++ ++ btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, bits); ++ cur_off += bits; ++ break; + } +- btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits); +- off_diff -= pad_bits; + } + } + +@@ -873,9 +945,11 @@ static void btf_dump_emit_struct_def(struct btf_dump *d, + { + const struct btf_member *m = btf_members(t); + bool is_struct = btf_is_struct(t); +- int align, i, packed, off = 0; ++ bool packed, prev_bitfield = false; ++ int align, i, off = 0; + __u16 vlen = btf_vlen(t); + ++ align = btf__align_of(d->btf, id); + packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0; + + btf_dump_printf(d, "%s%s%s {", +@@ -885,33 +959,36 @@ static void btf_dump_emit_struct_def(struct btf_dump *d, + + for (i = 0; i < vlen; i++, m++) { + const char *fname; +- int m_off, m_sz; ++ int m_off, m_sz, m_align; ++ bool in_bitfield; + + fname = btf_name_of(d, m->name_off); + m_sz = btf_member_bitfield_size(t, i); + m_off = btf_member_bit_offset(t, i); +- align = packed ? 1 : btf__align_of(d->btf, m->type); ++ m_align = packed ? 1 : btf__align_of(d->btf, m->type); + +- btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1); ++ in_bitfield = prev_bitfield && m_sz != 0; ++ ++ btf_dump_emit_bit_padding(d, off, m_off, m_align, in_bitfield, lvl + 1); + btf_dump_printf(d, "\n%s", pfx(lvl + 1)); + btf_dump_emit_type_decl(d, m->type, fname, lvl + 1); + + if (m_sz) { + btf_dump_printf(d, ": %d", m_sz); + off = m_off + m_sz; ++ prev_bitfield = true; + } else { + m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type)); + off = m_off + m_sz * 8; ++ prev_bitfield = false; + } ++ + btf_dump_printf(d, ";"); + } + + /* pad at the end, if necessary */ +- if (is_struct) { +- align = packed ? 1 : btf__align_of(d->btf, id); +- btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align, +- lvl + 1); +- } ++ if (is_struct) ++ btf_dump_emit_bit_padding(d, off, t->size * 8, align, false, lvl + 1); + + if (vlen) + btf_dump_printf(d, "\n"); +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c +index 8f44767a75fa5..22a7cd8fd9acf 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c +@@ -53,7 +53,7 @@ struct bitfields_only_mixed_types { + */ + /* ------ END-EXPECTED-OUTPUT ------ */ + struct bitfield_mixed_with_others { +- long: 4; /* char is enough as a backing field */ ++ char: 4; /* char is enough as a backing field */ + int a: 4; + /* 8-bit implicit padding */ + short b; /* combined with previous bitfield */ +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +index db5458da61826..28833f2694e9c 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +@@ -19,7 +19,7 @@ struct padded_implicitly { + /* + *struct padded_explicitly { + * int a; +- * int: 32; ++ * long: 0; + * int b; + *}; + * +@@ -28,41 +28,28 @@ struct padded_implicitly { + + struct padded_explicitly { + int a; +- int: 1; /* algo will explicitly pad with full 32 bits here */ ++ int: 1; /* algo will emit aligning `long: 0;` here */ + int b; + }; + + /* ----- START-EXPECTED-OUTPUT ----- */ +-/* +- *struct padded_a_lot { +- * int a; +- * long: 32; +- * long: 64; +- * long: 64; +- * int b; +- *}; +- * +- */ +-/* ------ END-EXPECTED-OUTPUT ------ */ +- + struct padded_a_lot { + int a; +- /* 32 bit of implicit padding here, which algo will make explicit */ + long: 64; + long: 64; + int b; + }; + ++/* ------ END-EXPECTED-OUTPUT ------ */ ++ + /* ----- START-EXPECTED-OUTPUT ----- */ + /* + *struct padded_cache_line { + * int a; +- * long: 32; + * long: 64; + * long: 64; + * long: 64; + * int b; +- * long: 32; + * long: 64; + * long: 64; + * long: 64; +@@ -85,7 +72,7 @@ struct padded_cache_line { + *struct zone { + * int a; + * short b; +- * short: 16; ++ * long: 0; + * struct zone_padding __pad__; + *}; + * +@@ -108,6 +95,39 @@ struct padding_wo_named_members { + long: 64; + }; + ++struct padding_weird_1 { ++ int a; ++ long: 64; ++ short: 16; ++ short b; ++}; ++ ++/* ------ END-EXPECTED-OUTPUT ------ */ ++ ++/* ----- START-EXPECTED-OUTPUT ----- */ ++/* ++ *struct padding_weird_2 { ++ * long: 56; ++ * char a; ++ * long: 56; ++ * char b; ++ * char: 8; ++ *}; ++ * ++ */ ++/* ------ END-EXPECTED-OUTPUT ------ */ ++struct padding_weird_2 { ++ int: 32; /* these paddings will be collapsed into `long: 56;` */ ++ short: 16; ++ char: 8; ++ char a; ++ int: 32; /* these paddings will be collapsed into `long: 56;` */ ++ short: 16; ++ char: 8; ++ char b; ++ char: 8; ++}; ++ + /* ------ END-EXPECTED-OUTPUT ------ */ + + int f(struct { +@@ -117,6 +137,8 @@ int f(struct { + struct padded_cache_line _4; + struct zone _5; + struct padding_wo_named_members _6; ++ struct padding_weird_1 _7; ++ struct padding_weird_2 _8; + } *_) + { + return 0; +-- +2.39.2 + diff --git a/queue-5.10/libbpf-fix-btf_dump-s-packed-struct-determination.patch b/queue-5.10/libbpf-fix-btf_dump-s-packed-struct-determination.patch new file mode 100644 index 00000000000..1178e7b90f5 --- /dev/null +++ b/queue-5.10/libbpf-fix-btf_dump-s-packed-struct-determination.patch @@ -0,0 +1,132 @@ +From 41ab94443cb5b5e086e40da23615243428d195bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Dec 2022 10:36:05 -0800 +Subject: libbpf: Fix btf_dump's packed struct determination + +From: Andrii Nakryiko + +[ Upstream commit 4fb877aaa179dcdb1676d55216482febaada457e ] + +Fix bug in btf_dump's logic of determining if a given struct type is +packed or not. The notion of "natural alignment" is not needed and is +even harmful in this case, so drop it altogether. The biggest difference +in btf_is_struct_packed() compared to its original implementation is +that we don't really use btf__align_of() to determine overall alignment +of a struct type (because it could be 1 for both packed and non-packed +struct, depending on specifci field definitions), and just use field's +actual alignment to calculate whether any field is requiring packing or +struct's size overall necessitates packing. + +Add two simple test cases that demonstrate the difference this change +would make. + +Fixes: ea2ce1ba99aa ("libbpf: Fix BTF-to-C converter's padding logic") +Reported-by: Eduard Zingerman +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Acked-by: Eduard Zingerman +Link: https://lore.kernel.org/bpf/20221215183605.4149488-1-andrii@kernel.org +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf_dump.c | 33 ++++--------------- + .../bpf/progs/btf_dump_test_case_packing.c | 19 +++++++++++ + 2 files changed, 25 insertions(+), 27 deletions(-) + +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index 4d27b08074a56..558d34fbd331c 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -788,47 +788,26 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) + } + } + +-static int btf_natural_align_of(const struct btf *btf, __u32 id) +-{ +- const struct btf_type *t = btf__type_by_id(btf, id); +- int i, align, vlen; +- const struct btf_member *m; +- +- if (!btf_is_composite(t)) +- return btf__align_of(btf, id); +- +- align = 1; +- m = btf_members(t); +- vlen = btf_vlen(t); +- for (i = 0; i < vlen; i++, m++) { +- align = max(align, btf__align_of(btf, m->type)); +- } +- +- return align; +-} +- + static bool btf_is_struct_packed(const struct btf *btf, __u32 id, + const struct btf_type *t) + { + const struct btf_member *m; +- int align, i, bit_sz; ++ int max_align = 1, align, i, bit_sz; + __u16 vlen; + +- align = btf_natural_align_of(btf, id); +- /* size of a non-packed struct has to be a multiple of its alignment */ +- if (align && (t->size % align) != 0) +- return true; +- + m = btf_members(t); + vlen = btf_vlen(t); + /* all non-bitfield fields have to be naturally aligned */ + for (i = 0; i < vlen; i++, m++) { +- align = btf_natural_align_of(btf, m->type); ++ align = btf__align_of(btf, m->type); + bit_sz = btf_member_bitfield_size(t, i); + if (align && bit_sz == 0 && m->offset % (8 * align) != 0) + return true; ++ max_align = max(align, max_align); + } +- ++ /* size of a non-packed struct has to be a multiple of its alignment */ ++ if (t->size % max_align != 0) ++ return true; + /* + * if original struct was marked as packed, but its layout is + * naturally aligned, we'll detect that it's not packed +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c +index 3f7755247591c..22dbd12134347 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c +@@ -116,6 +116,23 @@ struct usb_host_endpoint { + long: 0; + }; + ++/* ----- START-EXPECTED-OUTPUT ----- */ ++struct nested_packed_struct { ++ int a; ++ char b; ++} __attribute__((packed)); ++ ++struct outer_nonpacked_struct { ++ short a; ++ struct nested_packed_struct b; ++}; ++ ++struct outer_packed_struct { ++ short a; ++ struct nested_packed_struct b; ++} __attribute__((packed)); ++ ++/* ------ END-EXPECTED-OUTPUT ------ */ + + int f(struct { + struct packed_trailing_space _1; +@@ -128,6 +145,8 @@ int f(struct { + union jump_code_union _8; + struct outer_implicitly_packed_struct _9; + struct usb_host_endpoint _10; ++ struct outer_nonpacked_struct _11; ++ struct outer_packed_struct _12; + } *_) + { + return 0; +-- +2.39.2 + diff --git a/queue-5.10/selftests-bpf-add-few-corner-cases-to-test-padding-h.patch b/queue-5.10/selftests-bpf-add-few-corner-cases-to-test-padding-h.patch new file mode 100644 index 00000000000..944847f6ceb --- /dev/null +++ b/queue-5.10/selftests-bpf-add-few-corner-cases-to-test-padding-h.patch @@ -0,0 +1,229 @@ +From e407fa96a8f2c9fe4ea87f9547b4bb95c6a7313b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 13:15:05 -0800 +Subject: selftests/bpf: Add few corner cases to test padding handling of + btf_dump + +From: Andrii Nakryiko + +[ Upstream commit b148c8b9b926e257a59c8eb2cd6fa3adfd443254 ] + +Add few hand-crafted cases and few randomized cases found using script +from [0] that tests btf_dump's padding logic. + + [0] https://lore.kernel.org/bpf/85f83c333f5355c8ac026f835b18d15060725fcb.camel@ericsson.com/ + +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20221212211505.558851-7-andrii@kernel.org +Stable-dep-of: 4fb877aaa179 ("libbpf: Fix btf_dump's packed struct determination") +Signed-off-by: Sasha Levin +--- + .../bpf/progs/btf_dump_test_case_packing.c | 61 +++++++++- + .../bpf/progs/btf_dump_test_case_padding.c | 104 ++++++++++++++++++ + 2 files changed, 164 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c +index 1cef3bec1dc7f..3f7755247591c 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_packing.c +@@ -58,7 +58,64 @@ union jump_code_union { + } __attribute__((packed)); + }; + +-/*------ END-EXPECTED-OUTPUT ------ */ ++/* ----- START-EXPECTED-OUTPUT ----- */ ++/* ++ *struct nested_packed_but_aligned_struct { ++ * int x1; ++ * int x2; ++ *}; ++ * ++ *struct outer_implicitly_packed_struct { ++ * char y1; ++ * struct nested_packed_but_aligned_struct y2; ++ *} __attribute__((packed)); ++ * ++ */ ++/* ------ END-EXPECTED-OUTPUT ------ */ ++ ++struct nested_packed_but_aligned_struct { ++ int x1; ++ int x2; ++} __attribute__((packed)); ++ ++struct outer_implicitly_packed_struct { ++ char y1; ++ struct nested_packed_but_aligned_struct y2; ++}; ++/* ----- START-EXPECTED-OUTPUT ----- */ ++/* ++ *struct usb_ss_ep_comp_descriptor { ++ * char: 8; ++ * char bDescriptorType; ++ * char bMaxBurst; ++ * short wBytesPerInterval; ++ *}; ++ * ++ *struct usb_host_endpoint { ++ * long: 64; ++ * char: 8; ++ * struct usb_ss_ep_comp_descriptor ss_ep_comp; ++ * long: 0; ++ *} __attribute__((packed)); ++ * ++ */ ++/* ------ END-EXPECTED-OUTPUT ------ */ ++ ++struct usb_ss_ep_comp_descriptor { ++ char: 8; ++ char bDescriptorType; ++ char bMaxBurst; ++ int: 0; ++ short wBytesPerInterval; ++} __attribute__((packed)); ++ ++struct usb_host_endpoint { ++ long: 64; ++ char: 8; ++ struct usb_ss_ep_comp_descriptor ss_ep_comp; ++ long: 0; ++}; ++ + + int f(struct { + struct packed_trailing_space _1; +@@ -69,6 +126,8 @@ int f(struct { + union union_is_never_packed _6; + union union_does_not_need_packing _7; + union jump_code_union _8; ++ struct outer_implicitly_packed_struct _9; ++ struct usb_host_endpoint _10; + } *_) + { + return 0; +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +index 28833f2694e9c..0b3cdffbfcf71 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +@@ -128,6 +128,98 @@ struct padding_weird_2 { + char: 8; + }; + ++/* ----- START-EXPECTED-OUTPUT ----- */ ++struct exact_1byte { ++ char x; ++}; ++ ++struct padded_1byte { ++ char: 8; ++}; ++ ++struct exact_2bytes { ++ short x; ++}; ++ ++struct padded_2bytes { ++ short: 16; ++}; ++ ++struct exact_4bytes { ++ int x; ++}; ++ ++struct padded_4bytes { ++ int: 32; ++}; ++ ++struct exact_8bytes { ++ long x; ++}; ++ ++struct padded_8bytes { ++ long: 64; ++}; ++ ++struct ff_periodic_effect { ++ int: 32; ++ short magnitude; ++ long: 0; ++ short phase; ++ long: 0; ++ int: 32; ++ int custom_len; ++ short *custom_data; ++}; ++ ++struct ib_wc { ++ long: 64; ++ long: 64; ++ int: 32; ++ int byte_len; ++ void *qp; ++ union {} ex; ++ long: 64; ++ int slid; ++ int wc_flags; ++ long: 64; ++ char smac[6]; ++ long: 0; ++ char network_hdr_type; ++}; ++ ++struct acpi_object_method { ++ long: 64; ++ char: 8; ++ char type; ++ short reference_count; ++ char flags; ++ short: 0; ++ char: 8; ++ char sync_level; ++ long: 64; ++ void *node; ++ void *aml_start; ++ union {} dispatch; ++ long: 64; ++ int aml_length; ++}; ++ ++struct nested_unpacked { ++ int x; ++}; ++ ++struct nested_packed { ++ struct nested_unpacked a; ++ char c; ++} __attribute__((packed)); ++ ++struct outer_mixed_but_unpacked { ++ struct nested_packed b1; ++ short a1; ++ struct nested_packed b2; ++}; ++ + /* ------ END-EXPECTED-OUTPUT ------ */ + + int f(struct { +@@ -139,6 +231,18 @@ int f(struct { + struct padding_wo_named_members _6; + struct padding_weird_1 _7; + struct padding_weird_2 _8; ++ struct exact_1byte _100; ++ struct padded_1byte _101; ++ struct exact_2bytes _102; ++ struct padded_2bytes _103; ++ struct exact_4bytes _104; ++ struct padded_4bytes _105; ++ struct exact_8bytes _106; ++ struct padded_8bytes _107; ++ struct ff_periodic_effect _200; ++ struct ib_wc _201; ++ struct acpi_object_method _202; ++ struct outer_mixed_but_unpacked _203; + } *_) + { + return 0; +-- +2.39.2 + diff --git a/queue-5.10/selftests-bpf-test-btf-dump-for-struct-with-padding-.patch b/queue-5.10/selftests-bpf-test-btf-dump-for-struct-with-padding-.patch new file mode 100644 index 00000000000..b7112d641a0 --- /dev/null +++ b/queue-5.10/selftests-bpf-test-btf-dump-for-struct-with-padding-.patch @@ -0,0 +1,51 @@ +From 9112f70a99b67102c00745722876ee806902660f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 13:44:25 +0300 +Subject: selftests/bpf: Test btf dump for struct with padding only fields + +From: Eduard Zingerman + +[ Upstream commit d503f1176b14f722a40ea5110312614982f9a80b ] + +Structures with zero regular fields but some padding constitute a +special case in btf_dump.c:btf_dump_emit_struct_def with regards to +newline before closing '}'. + +Signed-off-by: Eduard Zingerman +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20221001104425.415768-2-eddyz87@gmail.com +Stable-dep-of: ea2ce1ba99aa ("libbpf: Fix BTF-to-C converter's padding logic") +Signed-off-by: Sasha Levin +--- + .../selftests/bpf/progs/btf_dump_test_case_padding.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +index 35c512818a56b..db5458da61826 100644 +--- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c ++++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_padding.c +@@ -102,12 +102,21 @@ struct zone { + struct zone_padding __pad__; + }; + ++/* ----- START-EXPECTED-OUTPUT ----- */ ++struct padding_wo_named_members { ++ long: 64; ++ long: 64; ++}; ++ ++/* ------ END-EXPECTED-OUTPUT ------ */ ++ + int f(struct { + struct padded_implicitly _1; + struct padded_explicitly _2; + struct padded_a_lot _3; + struct padded_cache_line _4; + struct zone _5; ++ struct padding_wo_named_members _6; + } *_) + { + return 0; +-- +2.39.2 + diff --git a/queue-5.10/series b/queue-5.10/series index 69cd861f131..eaad3b728d5 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -161,3 +161,7 @@ xtensa-fix-kasan-report-for-show_stack.patch rcu-fix-rcu_torture_read-ftrace-event.patch drm-etnaviv-fix-reference-leak-when-mmaping-imported-buffer.patch drm-amd-display-add-dsc-support-for-synaptics-cascaded-mst-hub.patch +selftests-bpf-test-btf-dump-for-struct-with-padding-.patch +libbpf-fix-btf-to-c-converter-s-padding-logic.patch +selftests-bpf-add-few-corner-cases-to-test-padding-h.patch +libbpf-fix-btf_dump-s-packed-struct-determination.patch