Re: [PATCH v2 bpf-next 00/13] bpf: support resilient split BTF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 26, 2024 at 3:56 PM Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> On Wed, Apr 24, 2024 at 8:48 AM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote:
> >
> > Split BPF Type Format (BTF) provides huge advantages in that kernel
> > modules only have to provide type information for types that they do not
> > share with the core kernel; for core kernel types, split BTF refers to
> > core kernel BTF type ids.  So for a STRUCT sk_buff, a module that
> > uses that structure (or a pointer to it) simply needs to refer to the
> > core kernel type id, saving the need to define the structure and its many
> > dependents.  This cuts down on duplication and makes BTF as compact
> > as possible.
> >
> > However, there is a downside.  This scheme requires the references from
> > split BTF to base BTF to be valid not just at encoding time, but at use
> > time (when the module is loaded).  Even a small change in kernel types
> > can perturb the type ids in core kernel BTF, and due to pahole's
> > parallel processing of compilation units, even an unchanged kernel can
> > have different type ids if BTF is re-generated.  So we have a robustness
> > problem for split BTF for cases where a module is not always compiled at
> > the same time as the kernel.  This problem is particularly acute for
> > distros which generally want module builders to be able to compile a
> > module for the lifetime of a Linux stable-based release, and have it
> > continue to be valid over the lifetime of that release, even as changes
> > in data structures (and hence BTF types) accrue.  Today it's not
> > possible to generate BTF for modules that works beyond the initial
> > kernel it is compiled against - kernel bugfixes etc invalidate the split
> > BTF references to vmlinux BTF, and BTF is no longer usable for the
> > module.
> >
> > The goal of this series is to provide options to provide additional
> > context for cases like this.  That context comes in the form of
> > distilled base BTF; it stands in for the base BTF, and contains
> > information about the types referenced from split BTF, but not their
> > full descriptions.  The modified split BTF will refer to type ids in
> > this .BTF.base section, and when the kernel loads such modules it
> > will use that base BTF to map references from split BTF to the
> > current vmlinux BTF - a process of relocating split BTF with the
> > currently-running kernel's vmlinux base BTF.
> >
> > A module builder - using this series along with the pahole changes -
> > can then build a module with distilled base BTF via an out-of-tree
> > module build, i.e.
> >
> > make -C . M=path/2/module
> >
> > The module will have a .BTF section (the split BTF) and a
> > .BTF.base section.  The latter is small in size - distilled base
> > BTF does not need full struct/union/enum information for named
> > types for example.  For 2667 modules built with distilled base BTF,
> > the average size observed was 1556 bytes (stddev 1563).
> >
> > Note that for the in-tree modules, this approach is not needed as
> > split and base BTF in the case of in-tree modules are always built
> > and re-built together.
> >
> > The series first focuses on generating split BTF with distilled base
> > BTF, and provides btf__parse_opts() which allows specification
> > of the section name from which to read BTF data, since we now have
> > both .BTF and .BTF.base sections that can contain such data.
> >
> > Then we add support to resolve_btfids for generating the .BTF.ids
> > section with reference to the .BTF.base section - this ensures the
> > .BTF.ids match those used in the split/base BTF.
> >
> > Finally the series provides the mechanism for relocating split BTF with
> > a new base; the distilled base BTF is used to map the references to base
> > BTF in the split BTF to the new base.  For the kernel, this relocation
> > process happens at module load time, and we relocate split BTF
> > references to point at types in the current vmlinux BTF.  As part of
> > this, .BTF.ids references need to be mapped also.
> >
> > So concretely, what happens is
> >
> > - we generate split BTF in the .BTF section of a module that refers to
> >   types in the .BTF.base section as base types; these are not full
> >   type descriptions but provide information about the base type.  So
> >   a STRUCT sk_buff would be represented as a FWD struct sk_buff in
> >   distilled base BTF for example.
> > - when the module is loaded, the split BTF is relocated with vmlinux
> >   BTF; in the case of the FWD struct sk_buff, we find the STRUCT sk_buff
> >   in vmlinux BTF and map all split BTF references to the distilled base
> >   FWD sk_buff, replacing them with references to the vmlinux BTF
> >   STRUCT sk_buff.
> >
> > Support is also added to bpftool to be able to display split BTF
> > relative to its .BTF.base section, and also to display the relocated
> > form via the "-R path_to_base_btf".
> >
> > A previous approach to this problem [1] utilized standalone BTF for such
> > cases - where the BTF is not defined relative to base BTF so there is no
> > relocation required.  The problem with that approach is that from
> > the verifier perspective, some types are special, and having a custom
> > representation of a core kernel type that did not necessarily match the
> > current representation is not tenable.  So the approach taken here was
> > to preserve the split BTF model while minimizing the representation of
> > the context needed to relocate split and current vmlinux BTF.
> >
> > To generate distilled .BTF.base sections the associated dwarves
> > patch (to be applied on the "next" branch there) is needed.
> > Without it, things will still work but bpf_testmod will not be built
> > with a .BTF.base section.
> >
> > Changes since RFC [2]:
> >
> > - updated terminology; we replace clunky "base reference" BTF with
> >   distilling base BTF into a .BTF.base section. Similarly BTF
> >   reconcilation becomes BTF relocation (Andrii, most patches)
> > - add distilled base BTF by default for out-of-tree modules
> >   (Alexei, patch 8)
> > - distill algorithm updated to record size of embedded struct/union
> >   by recording it as a 0-vlen STRUCT/UNION with size preserved
> >   (Andrii, patch 2)
> > - verify size match on relocation for such STRUCT/UNIONs (Andrii,
> >   patch 9)
> > - with embedded STRUCT/UNION recording size, we can have bpftool
> >   dump a header representation using .BTF.base + .BTF sections
> >   rather than special-casing and refusing to use "format c" for
> >   that case (patch 5)
> > - match enum with enum64 and vice versa (Andrii, patch 9)
> > - ensure that resolve_btfids works with BTF without .BTF.base
> >   section (patch 7)
> > - update tests to cover embedded types, arrays and function
> >   prototypes (patches 3, 12)
> >
> > One change not made yet is adding anonymous struct/unions that the split
> > BTF references in base BTF to the module instead of adding them to the
> > .BTF.base section.  That would involve having to maintain two pipes for
> > writing BTF, one for the .BTF.base and one for the split BTF.  It would
> > be possible, but there are I think some edge cases that might make it
> > tricky.  For example consider a split BTF reference to a base BTF
> > ARRAY which in turn referenced an anonymous STRUCT as type.  In such a
> > case, it wouldn't make sense to have the array in the .BTF.base section
> > while having the STRUCT in the module.  The general concern is that once
>
> Hm.. not really? ARRAY is a reference type (and anonymous at that), so
> it would have to stay in module's BTF, no? I'll go read the patch
> series again, but let me know if I'm missing something.
>
> > we move a type to the module we would need to also ensure any base types
> > that refer to it move there too.  For now it is I think simpler to
> > retain the existing split/base type classifications.
>
> We would have to finalize this part before landing, as it has big
> implications on the relocation process.

Ran out of time, sorry, will continue on Monday. But please consider,
meanwhile, what I mentioned about only having named
structs/unions/enums in distilled base BTF.

>
>
> >
> > [1] https://lore.kernel.org/bpf/20231112124834.388735-14-alan.maguire@xxxxxxxxxx/
> > [2] https://lore.kernel.org/bpf/20240322102455.98558-1-alan.maguire@xxxxxxxxxx/
> >
> >
> >
> > Alan Maguire (13):
> >   libbpf: add support to btf__add_fwd() for ENUM64
> >   libbpf: add btf__distill_base() creating split BTF with distilled base
> >     BTF
> >   selftests/bpf: test distilled base, split BTF generation
> >   libbpf: add btf__parse_opts() API for flexible BTF parsing
> >   bpftool: support displaying raw split BTF using base BTF section as
> >     base
> >   kbuild,bpf: switch to using --btf_features for pahole v1.26 and later
> >   resolve_btfids: use .BTF.base ELF section as base BTF if -B option is
> >     used
> >   kbuild, bpf: add module-specific pahole/resolve_btfids flags for
> >     distilled base BTF
> >   libbpf: split BTF relocation
> >   module, bpf: store BTF base pointer in struct module
> >   libbpf,bpf: share BTF relocate-related code with kernel
> >   selftests/bpf: extend distilled BTF tests to cover BTF relocation
> >   bpftool: support displaying relocated-with-base split BTF
> >
> >  include/linux/btf.h                           |  32 +
> >  include/linux/module.h                        |   2 +
> >  kernel/bpf/Makefile                           |   8 +
> >  kernel/bpf/btf.c                              | 227 +++++--
> >  kernel/module/main.c                          |   5 +-
> >  scripts/Makefile.btf                          |  12 +-
> >  scripts/Makefile.modfinal                     |   4 +-
> >  .../bpf/bpftool/Documentation/bpftool-btf.rst |  15 +-
> >  tools/bpf/bpftool/bash-completion/bpftool     |   7 +-
> >  tools/bpf/bpftool/btf.c                       |  20 +-
> >  tools/bpf/bpftool/main.c                      |  14 +-
> >  tools/bpf/bpftool/main.h                      |   2 +
> >  tools/bpf/resolve_btfids/main.c               |  22 +-
> >  tools/lib/bpf/Build                           |   2 +-
> >  tools/lib/bpf/btf.c                           | 561 +++++++++++-----
> >  tools/lib/bpf/btf.h                           |  61 ++
> >  tools/lib/bpf/btf_common.c                    | 146 ++++
> >  tools/lib/bpf/btf_relocate.c                  | 630 ++++++++++++++++++
> >  tools/lib/bpf/libbpf.map                      |   3 +
> >  tools/lib/bpf/libbpf_internal.h               |   2 +
> >  .../selftests/bpf/prog_tests/btf_distill.c    | 298 +++++++++
> >  21 files changed, 1864 insertions(+), 209 deletions(-)
> >  create mode 100644 tools/lib/bpf/btf_common.c
> >  create mode 100644 tools/lib/bpf/btf_relocate.c
> >  create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_distill.c
> >
> > --
> > 2.31.1
> >





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux