• David Vernet's avatar
    bpf: Allow trusted pointers to be passed to KF_TRUSTED_ARGS kfuncs · 3f00c523
    David Vernet authored
    Kfuncs currently support specifying the KF_TRUSTED_ARGS flag to signal
    to the verifier that it should enforce that a BPF program passes it a
    "safe", trusted pointer. Currently, "safe" means that the pointer is
    either PTR_TO_CTX, or is refcounted. There may be cases, however, where
    the kernel passes a BPF program a safe / trusted pointer to an object
    that the BPF program wishes to use as a kptr, but because the object
    does not yet have a ref_obj_id from the perspective of the verifier, the
    program would be unable to pass it to a KF_ACQUIRE | KF_TRUSTED_ARGS
    kfunc.
    
    The solution is to expand the set of pointers that are considered
    trusted according to KF_TRUSTED_ARGS, so that programs can invoke kfuncs
    with these pointers without getting rejected by the verifier.
    
    There is already a PTR_UNTRUSTED flag that is set in some scenarios,
    such as when a BPF program reads a kptr directly from a map
    without performing a bpf_kptr_xchg() call. These pointers of course can
    and should be rejected by the verifier. Unfortunately, however,
    PTR_UNTRUSTED does not cover all the cases for safety that need to
    be addressed to adequately protect kfuncs. Specifically, pointers
    obtained by a BPF program "walking" a struct are _not_ considered
    PTR_UNTRUSTED according to BPF. For example, say that we were to add a
    kfunc called bpf_task_acquire(), with KF_ACQUIRE | KF_TRUSTED_ARGS, to
    acquire a struct task_struct *. If we only used PTR_UNTRUSTED to signal
    that a task was unsafe to pass to a kfunc, the verifier would mistakenly
    allow the following unsafe BPF program to be loaded:
    
    SEC("tp_btf/task_newtask")
    int BPF_PROG(unsafe_acquire_task,
                 struct task_struct *task,
                 u64 clone_flags)
    {
            struct task_struct *acquired, *nested;
    
            nested = task->last_wakee;
    
            /* Would not be rejected by the verifier. */
            acquired = bpf_task_acquire(nested);
            if (!acquired)
                    return 0;
    
            bpf_task_release(acquired);
            return 0;
    }
    
    To address this, this patch defines a new type flag called PTR_TRUSTED
    which tracks whether a PTR_TO_BTF_ID pointer is safe to pass to a
    KF_TRUSTED_ARGS kfunc or a BPF helper function. PTR_TRUSTED pointers are
    passed directly from the kernel as a tracepoint or struct_ops callback
    argument. Any nested pointer that is obtained from walking a PTR_TRUSTED
    pointer is no longer PTR_TRUSTED. From the example above, the struct
    task_struct *task argument is PTR_TRUSTED, but the 'nested' pointer
    obtained from 'task->last_wakee' is not PTR_TRUSTED.
    
    A subsequent patch will add kfuncs for storing a task kfunc as a kptr,
    and then another patch will add selftests to validate.
    Signed-off-by: default avatarDavid Vernet <void@manifault.com>
    Link: https://lore.kernel.org/r/20221120051004.3605026-3-void@manifault.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    3f00c523
ref_tracking.c 30.8 KB