1. 26 4月, 2022 1 次提交
  2. 25 4月, 2022 1 次提交
  3. 23 4月, 2022 1 次提交
    • A
      libbpf: Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() · 8462e0b4
      Andrii Nakryiko 提交于
      Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() on
      older kernels for programs that are attachable through
      BPF_RAW_TRACEPOINT_OPEN. This makes bpf_link_create() more unified and
      convenient interface for creating bpf_link-based attachments.
      
      With this approach end users can just use bpf_link_create() for
      tp_btf/fentry/fexit/fmod_ret/lsm program attachments without needing to
      care about kernel support, as libbpf will handle this transparently. On
      the other hand, as newer features (like BPF cookie) are added to
      LINK_CREATE interface, they will be readily usable though the same
      bpf_link_create() API without any major refactoring from user's
      standpoint.
      
      bpf_program__attach_btf_id() is now using bpf_link_create() internally
      as well and will take advantaged of this unified interface when BPF
      cookie is added for fentry/fexit.
      
      Doing proactive feature detection of LINK_CREATE support for
      fentry/tp_btf/etc is quite involved. It requires parsing vmlinux BTF,
      determining some stable and guaranteed to be in all kernels versions
      target BTF type (either raw tracepoint or fentry target function),
      actually attaching this program and thus potentially affecting the
      performance of the host kernel briefly, etc. So instead we are taking
      much simpler "lazy" approach of falling back to
      bpf_raw_tracepoint_open() call only if initial LINK_CREATE command
      fails. For modern kernels this will mean zero added overhead, while
      older kernels will incur minimal overhead with a single fast-failing
      LINK_CREATE call.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
      Reviewed-by: NKui-Feng Lee <kuifeng@fb.com>
      Link: https://lore.kernel.org/bpf/20220421033945.3602803-3-andrii@kernel.org
      8462e0b4
  4. 22 4月, 2022 1 次提交
  5. 21 4月, 2022 3 次提交
  6. 20 4月, 2022 3 次提交
  7. 12 4月, 2022 1 次提交
  8. 11 4月, 2022 2 次提交
  9. 09 4月, 2022 4 次提交
  10. 08 4月, 2022 7 次提交
  11. 07 4月, 2022 1 次提交
  12. 06 4月, 2022 5 次提交
    • A
      libbpf: Add x86-specific USDT arg spec parsing logic · 4c59e584
      Andrii Nakryiko 提交于
      Add x86/x86_64-specific USDT argument specification parsing. Each
      architecture will require their own logic, as all this is arch-specific
      assembly-based notation. Architectures that libbpf doesn't support for
      USDTs will pr_warn() with specific error and return -ENOTSUP.
      
      We use sscanf() as a very powerful and easy to use string parser. Those
      spaces in sscanf's format string mean "skip any whitespaces", which is
      pretty nifty (and somewhat little known) feature.
      
      All this was tested on little-endian architecture, so bit shifts are
      probably off on big-endian, which our CI will hopefully prove.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NAlan Maguire <alan.maguire@oracle.com>
      Reviewed-by: NDave Marchevsky <davemarchevsky@fb.com>
      Link: https://lore.kernel.org/bpf/20220404234202.331384-6-andrii@kernel.org
      4c59e584
    • A
      libbpf: Wire up spec management and other arch-independent USDT logic · 999783c8
      Andrii Nakryiko 提交于
      Last part of architecture-agnostic user-space USDT handling logic is to
      set up BPF spec and, optionally, IP-to-ID maps from user-space.
      usdt_manager performs a compact spec ID allocation to utilize
      fixed-sized BPF maps as efficiently as possible. We also use hashmap to
      deduplicate USDT arg spec strings and map identical strings to single
      USDT spec, minimizing the necessary BPF map size. usdt_manager supports
      arbitrary sequences of attachment and detachment, both of the same USDT
      and multiple different USDTs and internally maintains a free list of
      unused spec IDs. bpf_link_usdt's logic is extended with proper setup and
      teardown of this spec ID free list and supporting BPF maps.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NAlan Maguire <alan.maguire@oracle.com>
      Reviewed-by: NDave Marchevsky <davemarchevsky@fb.com>
      Link: https://lore.kernel.org/bpf/20220404234202.331384-5-andrii@kernel.org
      999783c8
    • A
      libbpf: Add USDT notes parsing and resolution logic · 74cc6311
      Andrii Nakryiko 提交于
      Implement architecture-agnostic parts of USDT parsing logic. The code is
      the documentation in this case, it's futile to try to succinctly
      describe how USDT parsing is done in any sort of concreteness. But
      still, USDTs are recorded in special ELF notes section (.note.stapsdt),
      where each USDT call site is described separately. Along with USDT
      provider and USDT name, each such note contains USDT argument
      specification, which uses assembly-like syntax to describe how to fetch
      value of USDT argument. USDT arg spec could be just a constant, or
      a register, or a register dereference (most common cases in x86_64), but
      it technically can be much more complicated cases, like offset relative
      to global symbol and stuff like that. One of the later patches will
      implement most common subset of this for x86 and x86-64 architectures,
      which seems to handle a lot of real-world production application.
      
      USDT arg spec contains a compact encoding allowing usdt.bpf.h from
      previous patch to handle the above 3 cases. Instead of recording which
      register might be needed, we encode register's offset within struct
      pt_regs to simplify BPF-side implementation. USDT argument can be of
      different byte sizes (1, 2, 4, and 8) and signed or unsigned. To handle
      this, libbpf pre-calculates necessary bit shifts to do proper casting
      and sign-extension in a short sequences of left and right shifts.
      
      The rest is in the code with sometimes extensive comments and references
      to external "documentation" for USDTs.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NAlan Maguire <alan.maguire@oracle.com>
      Reviewed-by: NDave Marchevsky <davemarchevsky@fb.com>
      Link: https://lore.kernel.org/bpf/20220404234202.331384-4-andrii@kernel.org
      74cc6311
    • A
      libbpf: Wire up USDT API and bpf_link integration · 2e4913e0
      Andrii Nakryiko 提交于
      Wire up libbpf USDT support APIs without yet implementing all the
      nitty-gritty details of USDT discovery, spec parsing, and BPF map
      initialization.
      
      User-visible user-space API is simple and is conceptually very similar
      to uprobe API.
      
      bpf_program__attach_usdt() API allows to programmatically attach given
      BPF program to a USDT, specified through binary path (executable or
      shared lib), USDT provider and name. Also, just like in uprobe case, PID
      filter is specified (0 - self, -1 - any process, or specific PID).
      Optionally, USDT cookie value can be specified. Such single API
      invocation will try to discover given USDT in specified binary and will
      use (potentially many) BPF uprobes to attach this program in correct
      locations.
      
      Just like any bpf_program__attach_xxx() APIs, bpf_link is returned that
      represents this attachment. It is a virtual BPF link that doesn't have
      direct kernel object, as it can consist of multiple underlying BPF
      uprobe links. As such, attachment is not atomic operation and there can
      be brief moment when some USDT call sites are attached while others are
      still in the process of attaching. This should be taken into
      consideration by user. But bpf_program__attach_usdt() guarantees that
      in the case of success all USDT call sites are successfully attached, or
      all the successfuly attachments will be detached as soon as some USDT
      call sites failed to be attached. So, in theory, there could be cases of
      failed bpf_program__attach_usdt() call which did trigger few USDT
      program invocations. This is unavoidable due to multi-uprobe nature of
      USDT and has to be handled by user, if it's important to create an
      illusion of atomicity.
      
      USDT BPF programs themselves are marked in BPF source code as either
      SEC("usdt"), in which case they won't be auto-attached through
      skeleton's <skel>__attach() method, or it can have a full definition,
      which follows the spirit of fully-specified uprobes:
      SEC("usdt/<path>:<provider>:<name>"). In the latter case skeleton's
      attach method will attempt auto-attachment. Similarly, generic
      bpf_program__attach() will have enought information to go off of for
      parameterless attachment.
      
      USDT BPF programs are actually uprobes, and as such for kernel they are
      marked as BPF_PROG_TYPE_KPROBE.
      
      Another part of this patch is USDT-related feature probing:
        - BPF cookie support detection from user-space;
        - detection of kernel support for auto-refcounting of USDT semaphore.
      
      The latter is optional. If kernel doesn't support such feature and USDT
      doesn't rely on USDT semaphores, no error is returned. But if libbpf
      detects that USDT requires setting semaphores and kernel doesn't support
      this, libbpf errors out with explicit pr_warn() message. Libbpf doesn't
      support poking process's memory directly to increment semaphore value,
      like BCC does on legacy kernels, due to inherent raciness and danger of
      such process memory manipulation. Libbpf let's kernel take care of this
      properly or gives up.
      
      Logistically, all the extra USDT-related infrastructure of libbpf is put
      into a separate usdt.c file and abstracted behind struct usdt_manager.
      Each bpf_object has lazily-initialized usdt_manager pointer, which is
      only instantiated if USDT programs are attempted to be attached. Closing
      BPF object frees up usdt_manager resources. usdt_manager keeps track of
      USDT spec ID assignment and few other small things.
      
      Subsequent patches will fill out remaining missing pieces of USDT
      initialization and setup logic.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NAlan Maguire <alan.maguire@oracle.com>
      Link: https://lore.kernel.org/bpf/20220404234202.331384-3-andrii@kernel.org
      2e4913e0
    • A
      libbpf: Add BPF-side of USDT support · d72e2968
      Andrii Nakryiko 提交于
      Add BPF-side implementation of libbpf-provided USDT support. This
      consists of single header library, usdt.bpf.h, which is meant to be used
      from user's BPF-side source code. This header is added to the list of
      installed libbpf header, along bpf_helpers.h and others.
      
      BPF-side implementation consists of two BPF maps:
        - spec map, which contains "a USDT spec" which encodes information
          necessary to be able to fetch USDT arguments and other information
          (argument count, user-provided cookie value, etc) at runtime;
        - IP-to-spec-ID map, which is only used on kernels that don't support
          BPF cookie feature. It allows to lookup spec ID based on the place
          in user application that triggers USDT program.
      
      These maps have default sizes, 256 and 1024, which are chosen
      conservatively to not waste a lot of space, but handling a lot of common
      cases. But there could be cases when user application needs to either
      trace a lot of different USDTs, or USDTs are heavily inlined and their
      arguments are located in a lot of differing locations. For such cases it
      might be necessary to size those maps up, which libbpf allows to do by
      overriding BPF_USDT_MAX_SPEC_CNT and BPF_USDT_MAX_IP_CNT macros.
      
      It is an important aspect to keep in mind. Single USDT (user-space
      equivalent of kernel tracepoint) can have multiple USDT "call sites".
      That is, single logical USDT is triggered from multiple places in user
      application. This can happen due to function inlining. Each such inlined
      instance of USDT invocation can have its own unique USDT argument
      specification (instructions about the location of the value of each of
      USDT arguments). So while USDT looks very similar to usual uprobe or
      kernel tracepoint, under the hood it's actually a collection of uprobes,
      each potentially needing different spec to know how to fetch arguments.
      
      User-visible API consists of three helper functions:
        - bpf_usdt_arg_cnt(), which returns number of arguments of current USDT;
        - bpf_usdt_arg(), which reads value of specified USDT argument (by
          it's zero-indexed position) and returns it as 64-bit value;
        - bpf_usdt_cookie(), which functions like BPF cookie for USDT
          programs; this is necessary as libbpf doesn't allow specifying actual
          BPF cookie and utilizes it internally for USDT support implementation.
      
      Each bpf_usdt_xxx() APIs expect struct pt_regs * context, passed into
      BPF program. On kernels that don't support BPF cookie it is used to
      fetch absolute IP address of the underlying uprobe.
      
      usdt.bpf.h also provides BPF_USDT() macro, which functions like
      BPF_PROG() and BPF_KPROBE() and allows much more user-friendly way to
      get access to USDT arguments, if USDT definition is static and known to
      the user. It is expected that majority of use cases won't have to use
      bpf_usdt_arg_cnt() and bpf_usdt_arg() directly and BPF_USDT() will cover
      all their needs.
      
      Last, usdt.bpf.h is utilizing BPF CO-RE for one single purpose: to
      detect kernel support for BPF cookie. If BPF CO-RE dependency is
      undesirable, user application can redefine BPF_USDT_HAS_BPF_COOKIE to
      either a boolean constant (or equivalently zero and non-zero), or even
      point it to its own .rodata variable that can be specified from user's
      application user-space code. It is important that
      BPF_USDT_HAS_BPF_COOKIE is known to BPF verifier as static value (thus
      .rodata and not just .data), as otherwise BPF code will still contain
      bpf_get_attach_cookie() BPF helper call and will fail validation at
      runtime, if not dead-code eliminated.
      Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NAlan Maguire <alan.maguire@oracle.com>
      Link: https://lore.kernel.org/bpf/20220404234202.331384-2-andrii@kernel.org
      d72e2968
  13. 05 4月, 2022 1 次提交
  14. 04 4月, 2022 4 次提交
  15. 21 3月, 2022 2 次提交
  16. 18 3月, 2022 3 次提交