• Ilya Leoshkevich's avatar
    s390/bpf: Fix bpf_plt pointer arithmetic · 7ded842b
    Ilya Leoshkevich authored
    Kui-Feng Lee reported a crash on s390x triggered by the
    dummy_st_ops/dummy_init_ptr_arg test [1]:
    
      [<0000000000000002>] 0x2
      [<00000000009d5cde>] bpf_struct_ops_test_run+0x156/0x250
      [<000000000033145a>] __sys_bpf+0xa1a/0xd00
      [<00000000003319dc>] __s390x_sys_bpf+0x44/0x50
      [<0000000000c4382c>] __do_syscall+0x244/0x300
      [<0000000000c59a40>] system_call+0x70/0x98
    
    This is caused by GCC moving memcpy() after assignments in
    bpf_jit_plt(), resulting in NULL pointers being written instead of
    the return and the target addresses.
    
    Looking at the GCC internals, the reordering is allowed because the
    alias analysis thinks that the memcpy() destination and the assignments'
    left-hand-sides are based on different objects: new_plt and
    bpf_plt_ret/bpf_plt_target respectively, and therefore they cannot
    alias.
    
    This is in turn due to a violation of the C standard:
    
      When two pointers are subtracted, both shall point to elements of the
      same array object, or one past the last element of the array object
      ...
    
    From the C's perspective, bpf_plt_ret and bpf_plt are distinct objects
    and cannot be subtracted. In the practical terms, doing so confuses the
    GCC's alias analysis.
    
    The code was written this way in order to let the C side know a few
    offsets defined in the assembly. While nice, this is by no means
    necessary. Fix the noncompliance by hardcoding these offsets.
    
    [1] https://lore.kernel.org/bpf/c9923c1d-971d-4022-8dc8-1364e929d34c@gmail.com/
    
    Fixes: f1d5df84 ("s390/bpf: Implement bpf_arch_text_poke()")
    Signed-off-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
    Message-ID: <20240320015515.11883-1-iii@linux.ibm.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    7ded842b
bpf_jit_comp.c 71.1 KB