]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Mon, 3 Apr 2023 13:01:57 +0000 (09:01 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 3 Apr 2023 13:01:57 +0000 (09:01 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/libbpf-fix-btf-to-c-converter-s-padding-logic.patch [new file with mode: 0644]
queue-5.10/libbpf-fix-btf_dump-s-packed-struct-determination.patch [new file with mode: 0644]
queue-5.10/selftests-bpf-add-few-corner-cases-to-test-padding-h.patch [new file with mode: 0644]
queue-5.10/selftests-bpf-test-btf-dump-for-struct-with-padding-.patch [new file with mode: 0644]
queue-5.10/series

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 (file)
index 0000000..8edde39
--- /dev/null
@@ -0,0 +1,426 @@
+From e5069d615aea9c6ffee024193f173458f6043116 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <andrii@kernel.org>
+
+[ 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 <per.xp.sundstrom@ericsson.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20221212211505.558851-6-andrii@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 `<type>: 0` aligning mark if next
++               * field is right on alignment offset and its
++               * alignment requirement is less strict than <type>'s
++               * alignment (so compiler won't naturally align to the
++               * offset we expect), or if subsequent `<type>: X`,
++               * will actually completely fit in the remaining hole,
++               * making compiler basically ignore `<type>: 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
++       * `<type>: sizeof(<type>);` markers, except for the last one, which
++       * might need smaller than sizeof(<type>) 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 (file)
index 0000000..1178e7b
--- /dev/null
@@ -0,0 +1,132 @@
+From 41ab94443cb5b5e086e40da23615243428d195bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Dec 2022 10:36:05 -0800
+Subject: libbpf: Fix btf_dump's packed struct determination
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+[ 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 <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/bpf/20221215183605.4149488-1-andrii@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..944847f
--- /dev/null
@@ -0,0 +1,229 @@
+From e407fa96a8f2c9fe4ea87f9547b4bb95c6a7313b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <andrii@kernel.org>
+
+[ 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 <andrii@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+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 <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..b7112d6
--- /dev/null
@@ -0,0 +1,51 @@
+From 9112f70a99b67102c00745722876ee806902660f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Oct 2022 13:44:25 +0300
+Subject: selftests/bpf: Test btf dump for struct with padding only fields
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+[ 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 <eddyz87@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+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 <sashal@kernel.org>
+---
+ .../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
+
index 69cd861f131375bb6665e91c8a88fc2cd6bf63ab..eaad3b728d518e53b9609c2b60591d82c1662918 100644 (file)
@@ -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