Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: permit map_ptr arithmetic with opcode add and offset 0 #9

Closed
wants to merge 3 commits into from

Commits on Sep 6, 2020

  1. adding ci files

    tsipa committed Sep 6, 2020
    Configuration menu
    Copy the full SHA
    74afea3 View commit details
    Browse the repository at this point in the history
  2. Commit 41c48f3 ("bpf: Support access

    to bpf map fields") added support to access map fields
    with CORE support. For example,
    
                struct bpf_map {
                        __u32 max_entries;
                } __attribute__((preserve_access_index));
    
                struct bpf_array {
                        struct bpf_map map;
                        __u32 elem_size;
                } __attribute__((preserve_access_index));
    
                struct {
                        __uint(type, BPF_MAP_TYPE_ARRAY);
                        __uint(max_entries, 4);
                        __type(key, __u32);
                        __type(value, __u32);
                } m_array SEC(".maps");
    
                SEC("cgroup_skb/egress")
                int cg_skb(void *ctx)
                {
                        struct bpf_array *array = (struct bpf_array *)&m_array;
    
                        /* .. array->map.max_entries .. */
                }
    
    In kernel, bpf_htab has similar structure,
    
    	    struct bpf_htab {
    		    struct bpf_map map;
                        ...
                }
    
    In the above cg_skb(), to access array->map.max_entries, with CORE, the clang will
    generate two builtin's.
                base = &m_array;
                /* access array.map */
                map_addr = __builtin_preserve_struct_access_info(base, 0, 0);
                /* access array.map.max_entries */
                max_entries_addr = __builtin_preserve_struct_access_info(map_addr, 0, 0);
    	    max_entries = *max_entries_addr;
    
    In the current llvm, if two builtin's are in the same function or
    in the same function after inlining, the compiler is smart enough to chain
    them together and generates like below:
                base = &m_array;
                max_entries = *(base + reloc_offset); /* reloc_offset = 0 in this case */
    and we are fine.
    
    But if we force no inlining for one of functions in test_map_ptr() selftest, e.g.,
    check_default(), the above two __builtin_preserve_* will be in two different
    functions. In this case, we will have code like:
       func check_hash():
                reloc_offset_map = 0;
                base = &m_array;
                map_base = base + reloc_offset_map;
                check_default(map_base, ...)
       func check_default(map_base, ...):
                max_entries = *(map_base + reloc_offset_max_entries);
    
    In kernel, map_ptr (CONST_PTR_TO_MAP) does not allow any arithmetic.
    The above "map_base = base + reloc_offset_map" will trigger a verifier failure.
      ; VERIFY(check_default(&hash->map, map));
      0: (18) r7 = 0xffffb4fe8018a004
      2: (b4) w1 = 110
      3: (63) *(u32 *)(r7 +0) = r1
       R1_w=invP110 R7_w=map_value(id=0,off=4,ks=4,vs=8,imm=0) R10=fp0
      ; VERIFY_TYPE(BPF_MAP_TYPE_HASH, check_hash);
      4: (18) r1 = 0xffffb4fe8018a000
      6: (b4) w2 = 1
      7: (63) *(u32 *)(r1 +0) = r2
       R1_w=map_value(id=0,off=0,ks=4,vs=8,imm=0) R2_w=invP1 R7_w=map_value(id=0,off=4,ks=4,vs=8,imm=0) R10=fp0
      8: (b7) r2 = 0
      9: (18) r8 = 0xffff90bcb500c000
      11: (18) r1 = 0xffff90bcb500c000
      13: (0f) r1 += r2
      R1 pointer arithmetic on map_ptr prohibited
    
    To fix the issue, let us permit map_ptr + 0 arithmetic which will
    result in exactly the same map_ptr.
    
    Signed-off-by: Yonghong Song <yhs@fb.com>
    ---
     kernel/bpf/verifier.c | 3 +++
     1 file changed, 3 insertions(+)
    yonghong-song authored and tsipa committed Sep 6, 2020
    Configuration menu
    Copy the full SHA
    61ef24b View commit details
    Browse the repository at this point in the history
  3. change selftest map_ptr_kern.c which will fail without previous

    verifier change. Also added to verifier test for both
    "map_ptr += scalar" and "scalar += map_ptr" arithmetic.
    
    Signed-off-by: Yonghong Song <yhs@fb.com>
    ---
     .../selftests/bpf/progs/map_ptr_kern.c        |  4 +--
     .../testing/selftests/bpf/verifier/map_ptr.c  | 32 +++++++++++++++++++
     2 files changed, 34 insertions(+), 2 deletions(-)
    yonghong-song authored and tsipa committed Sep 6, 2020
    Configuration menu
    Copy the full SHA
    46203f8 View commit details
    Browse the repository at this point in the history