• Kumar Kartikeya Dwivedi's avatar
    bpf: Implement BPF exceptions · f18b03fa
    Kumar Kartikeya Dwivedi authored
    This patch implements BPF exceptions, and introduces a bpf_throw kfunc
    to allow programs to throw exceptions during their execution at runtime.
    A bpf_throw invocation is treated as an immediate termination of the
    program, returning back to its caller within the kernel, unwinding all
    stack frames.
    
    This allows the program to simplify its implementation, by testing for
    runtime conditions which the verifier has no visibility into, and assert
    that they are true. In case they are not, the program can simply throw
    an exception from the other branch.
    
    BPF exceptions are explicitly *NOT* an unlikely slowpath error handling
    primitive, and this objective has guided design choices of the
    implementation of the them within the kernel (with the bulk of the cost
    for unwinding the stack offloaded to the bpf_throw kfunc).
    
    The implementation of this mechanism requires use of add_hidden_subprog
    mechanism introduced in the previous patch, which generates a couple of
    instructions to move R1 to R0 and exit. The JIT then rewrites the
    prologue of this subprog to take the stack pointer and frame pointer as
    inputs and reset the stack frame, popping all callee-saved registers
    saved by the main subprog. The bpf_throw function then walks the stack
    at runtime, and invokes this exception subprog with the stack and frame
    pointers as parameters.
    
    Reviewers must take note that currently the main program is made to save
    all callee-saved registers on x86_64 during entry into the program. This
    is because we must do an equivalent of a lightweight context switch when
    unwinding the stack, therefore we need the callee-saved registers of the
    caller of the BPF program to be able to return with a sane state.
    
    Note that we have to additionally handle r12, even though it is not used
    by the program, because when throwing the exception the program makes an
    entry into the kernel which could clobber r12 after saving it on the
    stack. To be able to preserve the value we received on program entry, we
    push r12 and restore it from the generated subprogram when unwinding the
    stack.
    
    For now, bpf_throw invocation fails when lingering resources or locks
    exist in that path of the program. In a future followup, bpf_throw will
    be extended to perform frame-by-frame unwinding to release lingering
    resources for each stack frame, removing this limitation.
    Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
    Link: https://lore.kernel.org/r/20230912233214.1518551-5-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    f18b03fa
bpf_jit_comp.c 81.7 KB