1. Dec 11, 2022
    • Eduard Zingerman's avatar
      bpf: use check_ids() for active_lock comparison · 4ea2bb15
      Eduard Zingerman authored
      An update for verifier.c:states_equal()/regsafe() to use check_ids()
      for active spin lock comparisons. This fixes the issue reported by
      Kumar Kartikeya Dwivedi in [1] using technique suggested by Edward Cree.
      
      W/o this commit the verifier might be tricked to accept the following
      program working with a map containing spin locks:
      
        0: r9 = map_lookup_elem(...)  ; Returns PTR_TO_MAP_VALUE_OR_NULL id=1.
        1: r8 = map_lookup_elem(...)  ; Returns PTR_TO_MAP_VALUE_OR_NULL id=2.
        2: if r9 == 0 goto exit       ; r9 -> PTR_TO_MAP_VALUE.
        3: if r8 == 0 goto exit       ; r8 -> PTR_TO_MAP_VALUE.
        4: r7 = ktime_get_ns()        ; Unbound SCALAR_VALUE.
        5: r6 = ktime_get_ns()        ; Unbound SCALAR_VALUE.
        6: bpf_spin_lock(r8)          ; active_lock.id == 2.
        7: if r6 > r7 goto +1         ; No new information about the state
                                      ; is derived from this check, thus
                                      ; produced verifier states differ only
                                      ; in 'insn_idx'.
        8: r9 = r8                    ; Optionally make r9.id == r8.id.
        --- checkpoint ---            ; Assume is_state_visisted() creates a
                                      ; checkpoint here.
        9: bpf_spin_unlock(r9)        ; (a,b) active_lock.id == 2.
                                      ; (a) r9.id == 2, (b) r9.id == 1.
       10: exit(0)
      
      Consider two verification paths:
      (a) 0-10
      (b) 0-7,9-10
      
      The path (a) is verified first. If checkpoint is created at (8)
      the (b) would assume that (8) is safe because regsafe() does not
      compare register ids for registers of type PTR_TO_MAP_VALUE.
      
      [1] https://lore.kernel.org/bpf/20221111202719.982118-1-memxor@gmail.com/
      
      
      
      Reported-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
      Suggested-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
      Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
      Link: https://lore.kernel.org/r/20221209135733.28851-6-eddyz87@gmail.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      4ea2bb15
    • Eduard Zingerman's avatar
      selftests/bpf: verify states_equal() maintains idmap across all frames · 7d057943
      Eduard Zingerman authored
      
      
      A test case that would erroneously pass verification if
      verifier.c:states_equal() maintains separate register ID mappings for
      call frames.
      
      Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
      Link: https://lore.kernel.org/r/20221209135733.28851-5-eddyz87@gmail.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      7d057943
    • Eduard Zingerman's avatar
      bpf: states_equal() must build idmap for all function frames · 5dd9cdbc
      Eduard Zingerman authored
      verifier.c:states_equal() must maintain register ID mapping across all
      function frames. Otherwise the following example might be erroneously
      marked as safe:
      
      main:
          fp[-24] = map_lookup_elem(...)  ; frame[0].fp[-24].id == 1
          fp[-32] = map_lookup_elem(...)  ; frame[0].fp[-32].id == 2
          r1 = &fp[-24]
          r2 = &fp[-32]
          call foo()
          r0 = 0
          exit
      
      foo:
        0: r9 = r1
        1: r8 = r2
        2: r7 = ktime_get_ns()
        3: r6 = ktime_get_ns()
        4: if (r6 > r7) goto skip_assign
        5: r9 = r8
      
      skip_assign:                ; <--- checkpoint
        6: r9 = *r9               ; (a) frame[1].r9.id == 2
                                  ; (b) frame[1].r9.id == 1
      
        7: if r9 == 0 goto exit:  ; mark_ptr_or_null_regs() transfers != 0 info
                                  ; for all regs sharing ID:
                                  ;   (a) r9 != 0 => &frame[0].fp[-32] != 0
                                  ;   (b) r9 != 0 => &frame[0].fp[-24] != 0
      
        8: r8 = *r8               ; (a) r8 == &frame[0].fp[-32]
                                  ; (b) r8 == &frame[0].fp[-32]
        9: r0 = *r8               ; (a) safe
                                  ; (b) unsafe
      
      exit:
       10: exit
      
      While processing call to foo() verifier considers the following
      execution paths:
      
      (a) 0-10
      (b) 0-4,6-10
      (There is also path 0-7,10 but it is not interesting for the issue at
       hand. (a) is verified first.)
      
      Suppose that checkpoint is created at (6) when path (a) is verified,
      next path (b) is verified and (6) is reached.
      
      If states_equal() maintains separate 'idmap' for each frame the
      mapping at (6) for frame[1] would be empty and
      regsafe(r9)::check_ids() would add a pair 2->1 and return true,
      which is an error.
      
      If states_equal() maintains single 'idmap' for all frames the mapping
      at (6) would be { 1->1, 2->2 } and regsafe(r9)::check_ids() would
      return false when trying to add a pair 2->1.
      
      This issue was suggested in the following discussion:
      https://lore.kernel.org/bpf/CAEf4BzbFB5g4oUfyxk9rHy-PJSLQ3h8q9mV=rVoXfr_JVm8+1Q@mail.gmail.com/
      
      
      
      Suggested-by: default avatarAndrii Nakryiko <andrii.nakryiko@gmail.com>
      Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
      Link: https://lore.kernel.org/r/20221209135733.28851-4-eddyz87@gmail.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      5dd9cdbc
    • Eduard Zingerman's avatar
      selftests/bpf: test cases for regsafe() bug skipping check_id() · cb578c1c
      Eduard Zingerman authored
      
      
      Under certain conditions it was possible for verifier.c:regsafe() to
      skip check_id() call. This commit adds negative test cases previously
      errorneously accepted as safe.
      
      Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
      Link: https://lore.kernel.org/r/20221209135733.28851-3-eddyz87@gmail.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      cb578c1c
    • Eduard Zingerman's avatar
      bpf: regsafe() must not skip check_ids() · 7c884339
      Eduard Zingerman authored
      
      
      The verifier.c:regsafe() has the following shortcut:
      
      	equal = memcmp(rold, rcur, offsetof(struct bpf_reg_state, parent)) == 0;
      	...
      	if (equal)
      		return true;
      
      Which is executed regardless old register type. This is incorrect for
      register types that might have an ID checked by check_ids(), namely:
       - PTR_TO_MAP_KEY
       - PTR_TO_MAP_VALUE
       - PTR_TO_PACKET_META
       - PTR_TO_PACKET
      
      The following pattern could be used to exploit this:
      
        0: r9 = map_lookup_elem(...)  ; Returns PTR_TO_MAP_VALUE_OR_NULL id=1.
        1: r8 = map_lookup_elem(...)  ; Returns PTR_TO_MAP_VALUE_OR_NULL id=2.
        2: r7 = ktime_get_ns()        ; Unbound SCALAR_VALUE.
        3: r6 = ktime_get_ns()        ; Unbound SCALAR_VALUE.
        4: if r6 > r7 goto +1         ; No new information about the state
                                      ; is derived from this check, thus
                                      ; produced verifier states differ only
                                      ; in 'insn_idx'.
        5: r9 = r8                    ; Optionally make r9.id == r8.id.
        --- checkpoint ---            ; Assume is_state_visisted() creates a
                                      ; checkpoint here.
        6: if r9 == 0 goto <exit>     ; Nullness info is propagated to all
                                      ; registers with matching ID.
        7: r1 = *(u64 *) r8           ; Not always safe.
      
      Verifier first visits path 1-7 where r8 is verified to be not null
      at (6). Later the jump from 4 to 6 is examined. The checkpoint for (6)
      looks as follows:
        R8_rD=map_value_or_null(id=2,off=0,ks=4,vs=8,imm=0)
        R9_rwD=map_value_or_null(id=2,off=0,ks=4,vs=8,imm=0)
        R10=fp0
      
      The current state is:
        R0=... R6=... R7=... fp-8=...
        R8=map_value_or_null(id=2,off=0,ks=4,vs=8,imm=0)
        R9=map_value_or_null(id=1,off=0,ks=4,vs=8,imm=0)
        R10=fp0
      
      Note that R8 states are byte-to-byte identical, so regsafe() would
      exit early and skip call to check_ids(), thus ID mapping 2->2 will not
      be added to 'idmap'. Next, states for R9 are compared: these are not
      identical and check_ids() is executed, but 'idmap' is empty, so
      check_ids() adds mapping 2->1 to 'idmap' and returns success.
      
      This commit pushes the 'equal' down to register types that don't need
      check_ids().
      
      Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
      Link: https://lore.kernel.org/r/20221209135733.28851-2-eddyz87@gmail.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      7c884339
  2. Dec 10, 2022
  3. Dec 09, 2022
  4. Dec 08, 2022
    • Alexei Starovoitov's avatar
      Merge branch 'Document some recent core kfunc additions' · 2d141236
      Alexei Starovoitov authored
      David Vernet says:
      
      ====================
      
      A series of recent patch sets introduced kfuncs that allowed struct
      task_struct and struct cgroup objects to be used as kptrs. These were
      introduced in [0], [1], and [2].
      
      [0]: https://lore.kernel.org/lkml/20221120051004.3605026-1-void@manifault.com/
      [1]: https://lore.kernel.org/lkml/20221122145300.251210-2-void@manifault.com/T/
      [2]: https://lore.kernel.org/lkml/20221122055458.173143-1-void@manifault.com/
      
      These are "core" kfuncs, in that they may be used by a wide variety of
      possible BPF tracepoint or struct_ops programs, and are defined in
      kernel/bpf/helpers.c. Even though as kfuncs they have no ABI stability
      guarantees, they should still be properly documented. This patch set
      adds that documentation.
      
      Some other kfuncs were added recently as well, such as
      bpf_rcu_read_lock() and bpf_rcu_read_unlock(). Those could and should be
      added to this "Core kfuncs" section as well in subsequent patch sets.
      
      Note that this patch set does not contain documentation for
      bpf_task_acquire_not_zero(), or bpf_task_kptr_get(). As discussed in
      [3], those kfuncs currently always return NULL pending resolution on how
      to properly protect their arguments using RCU.
      
      [3]: https://lore.kernel.org/all/20221206210538.597606-1-void@manifault.com/
      
      
      ---
      Changelog:
      v2 -> v3:
      - Don't document bpf_task_kptr_get(), and instead provide a more
        substantive example for bpf_cgroup_kptr_get().
      - Further clarify expected behavior of bpf_task_from_pid() in comments
        (Alexei)
      
      v1 -> v2:
      - Expand comment to specify that a map holds a reference to a task kptr
        if we don't end up releasing it (Alexei)
      - Just read task->pid instead of using a probed read (Alexei)
      ====================
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      2d141236
    • David Vernet's avatar
      bpf/docs: Document struct cgroup * kfuncs · 36aa10ff
      David Vernet authored
      
      
      bpf_cgroup_acquire(), bpf_cgroup_release(), bpf_cgroup_kptr_get(), and
      bpf_cgroup_ancestor(), are kfuncs that were recently added to
      kernel/bpf/helpers.c. These are "core" kfuncs in that they're available
      for use in any tracepoint or struct_ops BPF program. Though they have no
      ABI stability guarantees, we should still document them. This patch adds
      a struct cgroup * subsection to the Core kfuncs section which describes
      each of these kfuncs.
      
      Signed-off-by: default avatarDavid Vernet <void@manifault.com>
      Link: https://lore.kernel.org/r/20221207204911.873646-3-void@manifault.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      36aa10ff
    • David Vernet's avatar
      bpf/docs: Document struct task_struct * kfuncs · 25c5e92d
      David Vernet authored
      
      
      bpf_task_acquire(), bpf_task_release(), and bpf_task_from_pid() are
      kfuncs that were recently added to kernel/bpf/helpers.c. These are
      "core" kfuncs in that they're available for use for any tracepoint or
      struct_ops BPF program. Though they have no ABI stability guarantees, we
      should still document them. This patch adds a new Core kfuncs section to
      the BPF kfuncs doc, and adds entries for all of these task kfuncs.
      
      Note that bpf_task_kptr_get() is not documented, as it still returns
      NULL while we're working to resolve how it can use RCU to ensure struct
      task_struct * lifetime.
      
      Signed-off-by: default avatarDavid Vernet <void@manifault.com>
      Link: https://lore.kernel.org/r/20221207204911.873646-2-void@manifault.com
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      25c5e92d
    • Andrii Nakryiko's avatar
      selftests/bpf: convert dynptr_fail and map_kptr_fail subtests to generic tester · 26c386ec
      Andrii Nakryiko authored
      
      
      Convert big chunks of dynptr and map_kptr subtests to use generic
      verification_tester. They are switched from using manually maintained
      tables of test cases, specifying program name and expected error
      verifier message, to btf_decl_tag-based annotations directly on
      corresponding BPF programs: __failure to specify that BPF program is
      expected to fail verification, and __msg() to specify expected log
      message.
      
      Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Acked-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
      Link: https://lore.kernel.org/r/20221207201648.2990661-2-andrii@kernel.org
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      26c386ec
    • Andrii Nakryiko's avatar
      selftests/bpf: add generic BPF program tester-loader · 537c3f66
      Andrii Nakryiko authored
      
      
      It's become a common pattern to have a collection of small BPF programs
      in one BPF object file, each representing one test case. On user-space
      side of such tests we maintain a table of program names and expected
      failure or success, along with optional expected verifier log message.
      
      This works, but each set of tests reimplement this mundane code over and
      over again, which is a waste of time for anyone trying to add a new set
      of tests. Furthermore, it's quite error prone as it's way too easy to miss
      some entries in these manually maintained test tables (as evidences by
      dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
      accidentally missed; this is fixed in next patch).
      
      So this patch implements generic test_loader, which accepts skeleton
      name and handles the rest of details: opens and loads BPF object file,
      making sure each program is tested in isolation. Optionally each test
      case can specify expected BPF verifier log message. In case of failure,
      tester makes sure to report verifier log, but it also reports verifier
      log in verbose mode unconditionally.
      
      Now, the interesting deviation from existing custom implementations is
      the use of btf_decl_tag attribute to specify expected-to-fail vs
      expected-to-succeed markers and, optionally, expected log message
      directly next to BPF program source code, eliminating the need to
      manually create and update table of tests.
      
      We define few macros wrapping btf_decl_tag with a convention that all
      values of btf_decl_tag start with "comment:" prefix, and then utilizing
      a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
      define things like expected success/failure, expected verifier message,
      extra verifier log level (if necessary). This approach is demonstrated
      by next patch in which two existing sets of failure tests are converted.
      
      Tester supports both expected-to-fail and expected-to-succeed programs,
      though this patch set didn't convert any existing expected-to-succeed
      programs yet, as existing tests couple BPF program loading with their
      further execution through attach or test_prog_run. One way to allow
      testing scenarios like this would be ability to specify custom callback,
      executed for each successfully loaded BPF program. This is left for
      follow up patches, after some more analysis of existing test cases.
      
      This test_loader is, hopefully, a start of a test_verifier-like runner,
      but integrated into test_progs infrastructure. It will allow much better
      "user experience" of defining low-level verification tests that can take
      advantage of all the libbpf-provided nicety features on BPF side: global
      variables, declarative maps, etc.  All while having a choice of defining
      it in C or as BPF assembly (through __attribute__((naked)) functions and
      using embedded asm), depending on what makes most sense in each
      particular case. This will be explored in follow up patches as well.
      
      Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
      
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      537c3f66
    • Andrii Nakryiko's avatar
      bpf: Remove unused insn_cnt argument from visit_[func_call_]insn() · dcb2288b
      Andrii Nakryiko authored
      
      
      Number of total instructions in BPF program (including subprogs) can and
      is accessed from env->prog->len. visit_func_call_insn() doesn't do any
      checks against insn_cnt anymore, relying on push_insn() to do this check
      internally. So remove unnecessary insn_cnt input argument from
      visit_func_call_insn() and visit_insn() functions.
      
      Suggested-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      Link: https://lore.kernel.org/bpf/20221207195534.2866030-1-andrii@kernel.org
      dcb2288b
    • Alexei Starovoitov's avatar
      Merge "do not rely on ALLOW_ERROR_INJECTION for fmod_ret" into bpf-next · 0a6ea1ce
      Alexei Starovoitov authored
      Merge commit 5b481aca
      
       ("bpf: do not rely on ALLOW_ERROR_INJECTION for fmod_ret")
      from hid tree into bpf-next.
      
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      0a6ea1ce
  5. Dec 07, 2022