1. 06 Mar, 2022 2 commits
    • Hao Luo's avatar
      compiler_types: Define __percpu as __attribute__((btf_type_tag("percpu"))) · 9216c916
      Hao Luo authored
      This is similar to commit 7472d5a6 ("compiler_types: define __user as
      __attribute__((btf_type_tag("user")))"), where a type tag "user" was
      introduced to identify the pointers that point to user memory. With that
      change, the newest compile toolchain can encode __user information into
      vmlinux BTF, which can be used by the BPF verifier to enforce safe
      program behaviors.
      
      Similarly, we have __percpu attribute, which is mainly used to indicate
      memory is allocated in percpu region. The __percpu pointers in kernel
      are supposed to be used together with functions like per_cpu_ptr() and
      this_cpu_ptr(), which perform necessary calculation on the pointer's
      base address. Without the btf_type_tag introduced in this patch,
      __percpu pointers will be treated as regular memory pointers in vmlinux
      BTF and BPF programs are allowed to directly dereference them, generating
      incorrect behaviors. Now with "percpu" btf_type_tag, the BPF verifier is
      able to differentiate __percpu pointers from regular pointers and forbids
      unexpected behaviors like direct load.
      
      The following is an example similar to the one given in commit
      7472d5a6:
      
        [$ ~] cat test.c
        #define __percpu __attribute__((btf_type_tag("percpu")))
        int foo(int __percpu *arg) {
        	return *arg;
        }
        [$ ~] clang -O2 -g -c test.c
        [$ ~] pahole -JV test.o
        ...
        File test.o:
        [1] INT int size=4 nr_bits=32 encoding=SIGNED
        [2] TYPE_TAG percpu type_id=1
        [3] PTR (anon) type_id=2
        [4] FUNC_PROTO (anon) return=1 args=(3 arg)
        [5] FUNC foo type_id=4
        [$ ~]
      
      for the function argument "int __percpu *arg", its type is described as
      	PTR -> TYPE_TAG(percpu) -> INT
      The kernel can use this information for bpf verification or other
      use cases.
      
      Like commit 7472d5a6, this feature requires clang (>= clang14) and
      pahole (>= 1.23).
      Signed-off-by: default avatarHao Luo <haoluo@google.com>
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Acked-by: default avatarYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20220304191657.981240-3-haoluo@google.com
      9216c916
    • Hao Luo's avatar
      bpf: Fix checking PTR_TO_BTF_ID in check_mem_access · bff61f6f
      Hao Luo authored
      With the introduction of MEM_USER in
      
       commit c6f1bfe8 ("bpf: reject program if a __user tagged memory accessed in kernel way")
      
      PTR_TO_BTF_ID can be combined with a MEM_USER tag. Therefore, most
      likely, when we compare reg_type against PTR_TO_BTF_ID, we want to use
      the reg's base_type. Previously the check in check_mem_access() wants
      to say: if the reg is BTF_ID but not NULL, the execution flow falls
      into the 'then' branch. But now a reg of (BTF_ID | MEM_USER), which
      should go into the 'then' branch, goes into the 'else'.
      
      The end results before and after this patch are the same: regs tagged
      with MEM_USER get rejected, but not in a way we intended. So fix the
      condition, the error message now is correct.
      
      Before (log from commit 696c3901):
      
        $ ./test_progs -v -n 22/3
        ...
        libbpf: prog 'test_user1': BPF program load failed: Permission denied
        libbpf: prog 'test_user1': -- BEGIN PROG LOAD LOG --
        R1 type=ctx expected=fp
        0: R1=ctx(id=0,off=0,imm=0) R10=fp0
        ; int BPF_PROG(test_user1, struct bpf_testmod_btf_type_tag_1 *arg)
        0: (79) r1 = *(u64 *)(r1 +0)
        func 'bpf_testmod_test_btf_type_tag_user_1' arg0 has btf_id 136561 type STRUCT 'bpf_testmod_btf_type_tag_1'
        1: R1_w=user_ptr_bpf_testmod_btf_type_tag_1(id=0,off=0,imm=0)
        ; g = arg->a;
        1: (61) r1 = *(u32 *)(r1 +0)
        R1 invalid mem access 'user_ptr_'
      
      Now:
      
        libbpf: prog 'test_user1': BPF program load failed: Permission denied
        libbpf: prog 'test_user1': -- BEGIN PROG LOAD LOG --
        R1 type=ctx expected=fp
        0: R1=ctx(id=0,off=0,imm=0) R10=fp0
        ; int BPF_PROG(test_user1, struct bpf_testmod_btf_type_tag_1 *arg)
        0: (79) r1 = *(u64 *)(r1 +0)
        func 'bpf_testmod_test_btf_type_tag_user_1' arg0 has btf_id 104036 type STRUCT 'bpf_testmod_btf_type_tag_1'
        1: R1_w=user_ptr_bpf_testmod_btf_type_tag_1(id=0,ref_obj_id=0,off=0,imm=0)
        ; g = arg->a;
        1: (61) r1 = *(u32 *)(r1 +0)
        R1 is ptr_bpf_testmod_btf_type_tag_1 access user memory: off=0
      
      Note the error message for the reason of rejection.
      
      Fixes: c6f1bfe8 ("bpf: reject program if a __user tagged memory accessed in kernel way")
      Signed-off-by: default avatarHao Luo <haoluo@google.com>
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Acked-by: default avatarYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20220304191657.981240-2-haoluo@google.com
      bff61f6f
  2. 05 Mar, 2022 38 commits