Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf...
authorJakub Kicinski <kuba@kernel.org>
Tue, 12 Mar 2024 01:06:04 +0000 (18:06 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 12 Mar 2024 01:06:04 +0000 (18:06 -0700)
Alexei Starovoitov says:

====================
pull-request: bpf-next 2024-03-11

We've added 59 non-merge commits during the last 9 day(s) which contain
a total of 88 files changed, 4181 insertions(+), 590 deletions(-).

The main changes are:

1) Enforce VM_IOREMAP flag and range in ioremap_page_range and introduce
   VM_SPARSE kind and vm_area_[un]map_pages to be used in bpf_arena,
   from Alexei.

2) Introduce bpf_arena which is sparse shared memory region between bpf
   program and user space where structures inside the arena can have
   pointers to other areas of the arena, and pointers work seamlessly for
   both user-space programs and bpf programs, from Alexei and Andrii.

3) Introduce may_goto instruction that is a contract between the verifier
   and the program. The verifier allows the program to loop assuming it's
   behaving well, but reserves the right to terminate it, from Alexei.

4) Use IETF format for field definitions in the BPF standard
   document, from Dave.

5) Extend struct_ops libbpf APIs to allow specify version suffixes for
   stuct_ops map types, share the same BPF program between several map
   definitions, and other improvements, from Eduard.

6) Enable struct_ops support for more than one page in trampolines,
   from Kui-Feng.

7) Support kCFI + BPF on riscv64, from Puranjay.

8) Use bpf_prog_pack for arm64 bpf trampoline, from Puranjay.

9) Fix roundup_pow_of_two undefined behavior on 32-bit archs, from Toke.
====================

Link: https://lore.kernel.org/r/20240312003646.8692-1-alexei.starovoitov@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1  2 
kernel/bpf/verifier.c
tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c

Simple merge
index a955a6358206eac8a4b5065b531e0171d4cc2a62,04cdbce4652ff62fc711b4fee9662bd4acef302d..99e561f18f9b67aa44af233c8941cb1e37776248
@@@ -239,74 -237,103 +237,173 @@@ int bpf_loop_iter_limit_nested(void *un
        return 1000 * a + b + c;
  }
  
 +struct iter_limit_bug_ctx {
 +      __u64 a;
 +      __u64 b;
 +      __u64 c;
 +};
 +
 +static __naked void iter_limit_bug_cb(void)
 +{
 +      /* This is the same as C code below, but written
 +       * in assembly to control which branches are fall-through.
 +       *
 +       *   switch (bpf_get_prandom_u32()) {
 +       *   case 1:  ctx->a = 42; break;
 +       *   case 2:  ctx->b = 42; break;
 +       *   default: ctx->c = 42; break;
 +       *   }
 +       */
 +      asm volatile (
 +      "r9 = r2;"
 +      "call %[bpf_get_prandom_u32];"
 +      "r1 = r0;"
 +      "r2 = 42;"
 +      "r0 = 0;"
 +      "if r1 == 0x1 goto 1f;"
 +      "if r1 == 0x2 goto 2f;"
 +      "*(u64 *)(r9 + 16) = r2;"
 +      "exit;"
 +      "1: *(u64 *)(r9 + 0) = r2;"
 +      "exit;"
 +      "2: *(u64 *)(r9 + 8) = r2;"
 +      "exit;"
 +      :
 +      : __imm(bpf_get_prandom_u32)
 +      : __clobber_all
 +      );
 +}
 +
 +SEC("tc")
 +__failure
 +__flag(BPF_F_TEST_STATE_FREQ)
 +int iter_limit_bug(struct __sk_buff *skb)
 +{
 +      struct iter_limit_bug_ctx ctx = { 7, 7, 7 };
 +
 +      bpf_loop(2, iter_limit_bug_cb, &ctx, 0);
 +
 +      /* This is the same as C code below,
 +       * written in assembly to guarantee checks order.
 +       *
 +       *   if (ctx.a == 42 && ctx.b == 42 && ctx.c == 7)
 +       *     asm volatile("r1 /= 0;":::"r1");
 +       */
 +      asm volatile (
 +      "r1 = *(u64 *)%[ctx_a];"
 +      "if r1 != 42 goto 1f;"
 +      "r1 = *(u64 *)%[ctx_b];"
 +      "if r1 != 42 goto 1f;"
 +      "r1 = *(u64 *)%[ctx_c];"
 +      "if r1 != 7 goto 1f;"
 +      "r1 /= 0;"
 +      "1:"
 +      :
 +      : [ctx_a]"m"(ctx.a),
 +        [ctx_b]"m"(ctx.b),
 +        [ctx_c]"m"(ctx.c)
 +      : "r1"
 +      );
 +      return 0;
 +}
 +
+ #define ARR_SZ 1000000
+ int zero;
+ char arr[ARR_SZ];
+ SEC("socket")
+ __success __retval(0xd495cdc0)
+ int cond_break1(const void *ctx)
+ {
+       unsigned long i;
+       unsigned int sum = 0;
+       for (i = zero; i < ARR_SZ; cond_break, i++)
+               sum += i;
+       for (i = zero; i < ARR_SZ; i++) {
+               barrier_var(i);
+               sum += i + arr[i];
+               cond_break;
+       }
+       return sum;
+ }
+ SEC("socket")
+ __success __retval(999000000)
+ int cond_break2(const void *ctx)
+ {
+       int i, j;
+       int sum = 0;
+       for (i = zero; i < 1000; cond_break, i++)
+               for (j = zero; j < 1000; j++) {
+                       sum += i + j;
+                       cond_break;
+               }
+       return sum;
+ }
+ static __noinline int loop(void)
+ {
+       int i, sum = 0;
+       for (i = zero; i <= 1000000; i++, cond_break)
+               sum += i;
+       return sum;
+ }
+ SEC("socket")
+ __success __retval(0x6a5a2920)
+ int cond_break3(const void *ctx)
+ {
+       return loop();
+ }
+ SEC("socket")
+ __success __retval(1)
+ int cond_break4(const void *ctx)
+ {
+       int cnt = zero;
+       for (;;) {
+               /* should eventually break out of the loop */
+               cond_break;
+               cnt++;
+       }
+       /* if we looped a bit, it's a success */
+       return cnt > 1 ? 1 : 0;
+ }
+ static __noinline int static_subprog(void)
+ {
+       int cnt = zero;
+       for (;;) {
+               cond_break;
+               cnt++;
+       }
+       return cnt;
+ }
+ SEC("socket")
+ __success __retval(1)
+ int cond_break5(const void *ctx)
+ {
+       int cnt1 = zero, cnt2;
+       for (;;) {
+               cond_break;
+               cnt1++;
+       }
+       cnt2 = static_subprog();
+       /* main and subprog have to loop a bit */
+       return cnt1 > 1 && cnt2 > 1 ? 1 : 0;
+ }
  char _license[] SEC("license") = "GPL";