• Andrii Nakryiko's avatar
    bpf: Validate global subprogs lazily · 2afae08c
    Andrii Nakryiko authored
    Slightly change BPF verifier logic around eagerness and order of global
    subprog validation. Instead of going over every global subprog eagerly
    and validating it before main (entry) BPF program is verified, turn it
    around. Validate main program first, mark subprogs that were called from
    main program for later verification, but otherwise assume it is valid.
    Afterwards, go over marked global subprogs and validate those,
    potentially marking some more global functions as being called. Continue
    this process until all (transitively) callable global subprogs are
    validated. It's a BFS traversal at its heart and will always converge.
    
    This is an important change because it allows to feature-gate some
    subprograms that might not be verifiable on some older kernel, depending
    on supported set of features.
    
    E.g., at some point, global functions were allowed to accept a pointer
    to memory, which size is identified by user-provided type.
    Unfortunately, older kernels don't support this feature. With BPF CO-RE
    approach, the natural way would be to still compile BPF object file once
    and guard calls to this global subprog with some CO-RE check or using
    .rodata variables. That's what people do to guard usage of new helpers
    or kfuncs, and any other new BPF-side feature that might be missing on
    old kernels.
    
    That's currently impossible to do with global subprogs, unfortunately,
    because they are eagerly and unconditionally validated. This patch set
    aims to change this, so that in the future when global funcs gain new
    features, those can be guarded using BPF CO-RE techniques in the same
    fashion as any other new kernel feature.
    
    Two selftests had to be adjusted in sync with these changes.
    
    test_global_func12 relied on eager global subprog validation failing
    before main program failure is detected (unknown return value). Fix by
    making sure that main program is always valid.
    
    verifier_subprog_precision's parent_stack_slot_precise subtest relied on
    verifier checkpointing heuristic to do a checkpoint at instruction #5,
    but that's no longer true because we don't have enough jumps validated
    before reaching insn #5 due to global subprogs being validated later.
    
    Other than that, no changes, as one would expect.
    Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
    Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Link: https://lore.kernel.org/bpf/20231124035937.403208-3-andrii@kernel.org
    2afae08c
verifier_subprog_precision.c 18.2 KB