• Yonghong Song's avatar
    bpf: Permit size-0 datasec · 13ca51d5
    Yonghong Song authored
    llvm patch https://reviews.llvm.org/D84002 permitted
    to emit empty rodata datasec if the elf .rodata section
    contains read-only data from local variables. These
    local variables will be not emitted as BTF_KIND_VARs
    since llvm converted these local variables as
    static variables with private linkage without debuginfo
    types. Such an empty rodata datasec will make
    skeleton code generation easy since for skeleton
    a rodata struct will be generated if there is a
    .rodata elf section. The existence of a rodata
    btf datasec is also consistent with the existence
    of a rodata map created by libbpf.
    
    The btf with such an empty rodata datasec will fail
    in the kernel though as kernel will reject a datasec
    with zero vlen and zero size. For example, for the below code,
        int sys_enter(void *ctx)
        {
           int fmt[6] = {1, 2, 3, 4, 5, 6};
           int dst[6];
    
           bpf_probe_read(dst, sizeof(dst), fmt);
           return 0;
        }
    We got the below btf (bpftool btf dump ./test.o):
        [1] PTR '(anon)' type_id=0
        [2] FUNC_PROTO '(anon)' ret_type_id=3 vlen=1
                'ctx' type_id=1
        [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
        [4] FUNC 'sys_enter' type_id=2 linkage=global
        [5] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
        [6] ARRAY '(anon)' type_id=5 index_type_id=7 nr_elems=4
        [7] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
        [8] VAR '_license' type_id=6, linkage=global-alloc
        [9] DATASEC '.rodata' size=0 vlen=0
        [10] DATASEC 'license' size=0 vlen=1
                type_id=8 offset=0 size=4
    When loading the ./test.o to the kernel with bpftool,
    we see the following error:
        libbpf: Error loading BTF: Invalid argument(22)
        libbpf: magic: 0xeb9f
        ...
        [6] ARRAY (anon) type_id=5 index_type_id=7 nr_elems=4
        [7] INT __ARRAY_SIZE_TYPE__ size=4 bits_offset=0 nr_bits=32 encoding=(none)
        [8] VAR _license type_id=6 linkage=1
        [9] DATASEC .rodata size=24 vlen=0 vlen == 0
        libbpf: Error loading .BTF into kernel: -22. BTF is optional, ignoring.
    
    Basically, libbpf changed .rodata datasec size to 24 since elf .rodata
    section size is 24. The kernel then rejected the BTF since vlen = 0.
    Note that the above kernel verifier failure can be worked around with
    changing local variable "fmt" to a static or global, optionally const, variable.
    
    This patch permits a datasec with vlen = 0 in kernel.
    Signed-off-by: default avatarYonghong Song <yhs@fb.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Link: https://lore.kernel.org/bpf/20210119153519.3901963-1-yhs@fb.com
    13ca51d5
btf.c 151 KB