1. 08 May, 2024 4 commits
    • Jose E. Marchesi's avatar
      bpf: guard BPF_NO_PRESERVE_ACCESS_INDEX in skb_pkt_end.c · 911edc69
      Jose E. Marchesi authored
      This little patch is a follow-up to:
      https://lore.kernel.org/bpf/20240507095011.15867-1-jose.marchesi@oracle.com/T/#u
      
      The temporary workaround of passing -DBPF_NO_PRESERVE_ACCESS_INDEX
      when building with GCC triggers a redefinition preprocessor error when
      building progs/skb_pkt_end.c.  This patch adds a guard to avoid
      redefinition.
      Signed-off-by: default avatarJose E. Marchesi <jose.marchesi@oracle.com>
      Cc: david.faust@oracle.com
      Cc: cupertino.miranda@oracle.com
      Cc: Eduard Zingerman <eddyz87@gmail.com>
      Cc: Yonghong Song <yonghong.song@linux.dev>
      Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
      Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
      Link: https://lore.kernel.org/r/20240508110332.17332-1-jose.marchesi@oracle.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      911edc69
    • Jose E. Marchesi's avatar
      bpf: avoid UB in usages of the __imm_insn macro · 1209a523
      Jose E. Marchesi authored
      [Changes from V2:
       - no-strict-aliasing is only applied when building with GCC.
       - cpumask_failure.c is excluded, as it doesn't use __imm_insn.]
      
      The __imm_insn macro is defined in bpf_misc.h as:
      
        #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
      
      This may lead to type-punning and strict aliasing rules violations in
      it's typical usage where the address of a struct bpf_insn is passed as
      expr, like in:
      
        __imm_insn(st_mem,
                   BPF_ST_MEM(BPF_W, BPF_REG_1, offsetof(struct __sk_buff, mark), 42))
      
      Where:
      
        #define BPF_ST_MEM(SIZE, DST, OFF, IMM)				\
      	((struct bpf_insn) {					\
      		.code  = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM,	\
      		.dst_reg = DST,					\
      		.src_reg = 0,					\
      		.off   = OFF,					\
      		.imm   = IMM })
      
      In all the actual instances of this in the BPF selftests the value is
      fed to a volatile asm statement as soon as it gets read from memory,
      and thus it is unlikely anti-aliasing rules breakage may lead to
      misguided optimizations.
      
      However, GCC detects the potential problem (indirectly) by issuing a
      warning stating that a temporary <Uxxxxxx> is used uninitialized,
      where the temporary corresponds to the memory read by *(long *).
      
      This patch adds -fno-strict-aliasing to the compilation flags of the
      particular selftests that do type punning via __imm_insn, only for
      GCC.
      
      Tested in master bpf-next.
      No regressions.
      Signed-off-by: default avatarJose E. Marchesi <jose.marchesi@oracle.com>
      Cc: david.faust@oracle.com
      Cc: cupertino.miranda@oracle.com
      Cc: Yonghong Song <yonghong.song@linux.dev>
      Cc: Eduard Zingerman <eddyz87@gmail.com>
      Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
      Link: https://lore.kernel.org/r/20240508103551.14955-1-jose.marchesi@oracle.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      1209a523
    • Jose E. Marchesi's avatar
      bpf: avoid uninitialized warnings in verifier_global_subprogs.c · cd3fc3b9
      Jose E. Marchesi authored
      [Changes from V1:
      - The warning to disable is -Wmaybe-uninitialized, not -Wuninitialized.
      - This warning is only supported in GCC.]
      
      The BPF selftest verifier_global_subprogs.c contains code that
      purposedly performs out of bounds access to memory, to check whether
      the kernel verifier is able to catch them.  For example:
      
        __noinline int global_unsupp(const int *mem)
        {
      	if (!mem)
      		return 0;
      	return mem[100]; /* BOOM */
        }
      
      With -O1 and higher and no inlining, GCC notices this fact and emits a
      "maybe uninitialized" warning.  This is by design.  Note that the
      emission of these warnings is highly dependent on the precise
      optimizations that are performed.
      
      This patch adds a compiler pragma to verifier_global_subprogs.c to
      ignore these warnings.
      
      Tested in bpf-next master.
      No regressions.
      Signed-off-by: default avatarJose E. Marchesi <jose.marchesi@oracle.com>
      Cc: david.faust@oracle.com
      Cc: cupertino.miranda@oracle.com
      Cc: Yonghong Song <yonghong.song@linux.dev>
      Cc: Eduard Zingerman <eddyz87@gmail.com>
      Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
      Link: https://lore.kernel.org/r/20240507184756.1772-1-jose.marchesi@oracle.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      cd3fc3b9
    • Puranjay Mohan's avatar
      bpf, arm64: Add support for lse atomics in bpf_arena · e612b5c1
      Puranjay Mohan authored
      When LSE atomics are available, BPF atomic instructions are implemented
      as single ARM64 atomic instructions, therefore it is easy to enable
      these in bpf_arena using the currently available exception handling
      setup.
      
      LL_SC atomics use loops and therefore would need more work to enable in
      bpf_arena.
      
      Enable LSE atomics based instructions in bpf_arena and use the
      bpf_jit_supports_insn() callback to reject atomics in bpf_arena if LSE
      atomics are not available.
      
      All atomics and arena_atomics selftests are passing:
      
        [root@ip-172-31-2-216 bpf]# ./test_progs -a atomics,arena_atomics
        #3/1     arena_atomics/add:OK
        #3/2     arena_atomics/sub:OK
        #3/3     arena_atomics/and:OK
        #3/4     arena_atomics/or:OK
        #3/5     arena_atomics/xor:OK
        #3/6     arena_atomics/cmpxchg:OK
        #3/7     arena_atomics/xchg:OK
        #3       arena_atomics:OK
        #10/1    atomics/add:OK
        #10/2    atomics/sub:OK
        #10/3    atomics/and:OK
        #10/4    atomics/or:OK
        #10/5    atomics/xor:OK
        #10/6    atomics/cmpxchg:OK
        #10/7    atomics/xchg:OK
        #10      atomics:OK
        Summary: 2/14 PASSED, 0 SKIPPED, 0 FAILED
      Signed-off-by: default avatarPuranjay Mohan <puranjay@kernel.org>
      Link: https://lore.kernel.org/r/20240426161116.441-1-puranjay@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      e612b5c1
  2. 07 May, 2024 23 commits
  3. 06 May, 2024 3 commits
  4. 03 May, 2024 2 commits
    • Jose E. Marchesi's avatar
      libbpf: Avoid casts from pointers to enums in bpf_tracing.h · a9e7715c
      Jose E. Marchesi authored
      [Differences from V1:
        - Do not introduce a global typedef, as this is a public header.
        - Keep the void* casts in BPF_KPROBE_READ_RET_IP and
          BPF_KRETPROBE_READ_RET_IP, as these are necessary
          for converting to a const void* argument of
          bpf_probe_read_kernel.]
      
      The BPF_PROG, BPF_KPROBE and BPF_KSYSCALL macros defined in
      tools/lib/bpf/bpf_tracing.h use a clever hack in order to provide a
      convenient way to define entry points for BPF programs as if they were
      normal C functions that get typed actual arguments, instead of as
      elements in a single "context" array argument.
      
      For example, PPF_PROGS allows writing:
      
        SEC("struct_ops/cwnd_event")
        void BPF_PROG(cwnd_event, struct sock *sk, enum tcp_ca_event event)
        {
              bbr_cwnd_event(sk, event);
              dctcp_cwnd_event(sk, event);
              cubictcp_cwnd_event(sk, event);
        }
      
      That expands into a pair of functions:
      
        void ____cwnd_event (unsigned long long *ctx, struct sock *sk, enum tcp_ca_event event)
        {
              bbr_cwnd_event(sk, event);
              dctcp_cwnd_event(sk, event);
              cubictcp_cwnd_event(sk, event);
        }
      
        void cwnd_event (unsigned long long *ctx)
        {
              _Pragma("GCC diagnostic push")
              _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")
              return ____cwnd_event(ctx, (void*)ctx[0], (void*)ctx[1]);
              _Pragma("GCC diagnostic pop")
        }
      
      Note how the 64-bit unsigned integers in the incoming CTX get casted
      to a void pointer, and then implicitly converted to whatever type of
      the actual argument in the wrapped function.  In this case:
      
        Arg1: unsigned long long -> void * -> struct sock *
        Arg2: unsigned long long -> void * -> enum tcp_ca_event
      
      The behavior of GCC and clang when facing such conversions differ:
      
        pointer -> pointer
      
          Allowed by the C standard.
          GCC: no warning nor error.
          clang: no warning nor error.
      
        pointer -> integer type
      
          [C standard says the result of this conversion is implementation
           defined, and it may lead to unaligned pointer etc.]
      
          GCC: error: integer from pointer without a cast [-Wint-conversion]
          clang: error: incompatible pointer to integer conversion [-Wint-conversion]
      
        pointer -> enumerated type
      
          GCC: error: incompatible types in assigment (*)
          clang: error: incompatible pointer to integer conversion [-Wint-conversion]
      
      These macros work because converting pointers to pointers is allowed,
      and converting pointers to integers also works provided a suitable
      integer type even if it is implementation defined, much like casting a
      pointer to uintptr_t is guaranteed to work by the C standard.  The
      conversion errors emitted by both compilers by default are silenced by
      the pragmas.
      
      However, the GCC error marked with (*) above when assigning a pointer
      to an enumerated value is not associated with the -Wint-conversion
      warning, and it is not possible to turn it off.
      
      This is preventing building the BPF kernel selftests with GCC.
      
      This patch fixes this by avoiding intermediate casts to void*,
      replaced with casts to `unsigned long long', which is an integer type
      capable of safely store a BPF pointer, much like the standard
      uintptr_t.
      
      Testing performed in bpf-next master:
        - vmtest.sh -- ./test_verifier
        - vmtest.sh -- ./test_progs
        - make M=samples/bpf
      No regressions.
      Signed-off-by: default avatarJose E. Marchesi <jose.marchesi@oracle.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/20240502170925.3194-1-jose.marchesi@oracle.com
      a9e7715c
    • Jose E. Marchesi's avatar
      libbpf: Fix bpf_ksym_exists() in GCC · cf9bea94
      Jose E. Marchesi authored
      The macro bpf_ksym_exists is defined in bpf_helpers.h as:
      
        #define bpf_ksym_exists(sym) ({								\
        	_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak");	\
        	!!sym;											\
        })
      
      The purpose of the macro is to determine whether a given symbol has
      been defined, given the address of the object associated with the
      symbol.  It also has a compile-time check to make sure the object
      whose address is passed to the macro has been declared as weak, which
      makes the check on `sym' meaningful.
      
      As it happens, the check for weak doesn't work in GCC in all cases,
      because __builtin_constant_p not always folds at parse time when
      optimizing.  This is because optimizations that happen later in the
      compilation process, like inlining, may make a previously non-constant
      expression a constant.  This results in errors like the following when
      building the selftests with GCC:
      
        bpf_helpers.h:190:24: error: expression in static assertion is not constant
        190 |         _Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak");       \
            |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
      
      Fortunately recent versions of GCC support a __builtin_has_attribute
      that can be used to directly check for the __weak__ attribute.  This
      patch changes bpf_helpers.h to use that builtin when building with a
      recent enough GCC, and to omit the check if GCC is too old to support
      the builtin.
      
      The macro used for GCC becomes:
      
        #define bpf_ksym_exists(sym) ({									\
      	_Static_assert(__builtin_has_attribute (*sym, __weak__), #sym " should be marked as __weak");	\
      	!!sym;												\
        })
      
      Note that since bpf_ksym_exists is designed to get the address of the
      object associated with symbol SYM, we pass *sym to
      __builtin_has_attribute instead of sym.  When an expression is passed
      to __builtin_has_attribute then it is the type of the passed
      expression that is checked for the specified attribute.  The
      expression itself is not evaluated.  This accommodates well with the
      existing usages of the macro:
      
      - For function objects:
      
        struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym __weak;
        [...]
        bpf_ksym_exists(bpf_task_acquire)
      
      - For variable objects:
      
        extern const struct rq runqueues __ksym __weak; /* typed */
        [...]
        bpf_ksym_exists(&runqueues)
      
      Note also that BPF support was added in GCC 10 and support for
      __builtin_has_attribute in GCC 9.
      
      Locally tested in bpf-next master branch.
      No regressions.
      Signed-of-by: default avatarJose E. Marchesi <jose.marchesi@oracle.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
      Link: https://lore.kernel.org/bpf/20240428112559.10518-1-jose.marchesi@oracle.com
      cf9bea94
  5. 02 May, 2024 8 commits