lkml.org 
[lkml]   [2022]   [Sep]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.19 027/155] bpf: Tidy up verifier check_func_arg()
    Date
    From: Joanne Koong <joannelkoong@gmail.com>

    [ Upstream commit 8ab4cdcf03d0b060fbf73f76460f199bbd759ff7 ]

    This patch does two things:

    1. For matching against the arg type, the match should be against the
    base type of the arg type, since the arg type can have different
    bpf_type_flags set on it.

    2. Uses switch casing to improve readability + efficiency.

    Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
    Acked-by: Hao Luo <haoluo@google.com>
    Link: https://lore.kernel.org/r/20220712210603.123791-1-joannelkoong@gmail.com
    Signed-off-by: Alexei Starovoitov <ast@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    kernel/bpf/verifier.c | 66 +++++++++++++++++++++++++------------------
    1 file changed, 38 insertions(+), 28 deletions(-)

    diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
    index f0dd73bf69ddf..20df58c351abf 100644
    --- a/kernel/bpf/verifier.c
    +++ b/kernel/bpf/verifier.c
    @@ -5533,17 +5533,6 @@ static bool arg_type_is_mem_size(enum bpf_arg_type type)
    type == ARG_CONST_SIZE_OR_ZERO;
    }

    -static bool arg_type_is_alloc_size(enum bpf_arg_type type)
    -{
    - return type == ARG_CONST_ALLOC_SIZE_OR_ZERO;
    -}
    -
    -static bool arg_type_is_int_ptr(enum bpf_arg_type type)
    -{
    - return type == ARG_PTR_TO_INT ||
    - type == ARG_PTR_TO_LONG;
    -}
    -
    static bool arg_type_is_release(enum bpf_arg_type type)
    {
    return type & OBJ_RELEASE;
    @@ -5929,7 +5918,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    meta->ref_obj_id = reg->ref_obj_id;
    }

    - if (arg_type == ARG_CONST_MAP_PTR) {
    + switch (base_type(arg_type)) {
    + case ARG_CONST_MAP_PTR:
    /* bpf_map_xxx(map_ptr) call: remember that map_ptr */
    if (meta->map_ptr) {
    /* Use map_uid (which is unique id of inner map) to reject:
    @@ -5954,7 +5944,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    }
    meta->map_ptr = reg->map_ptr;
    meta->map_uid = reg->map_uid;
    - } else if (arg_type == ARG_PTR_TO_MAP_KEY) {
    + break;
    + case ARG_PTR_TO_MAP_KEY:
    /* bpf_map_xxx(..., map_ptr, ..., key) call:
    * check that [key, key + map->key_size) are within
    * stack limits and initialized
    @@ -5971,7 +5962,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    err = check_helper_mem_access(env, regno,
    meta->map_ptr->key_size, false,
    NULL);
    - } else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE) {
    + break;
    + case ARG_PTR_TO_MAP_VALUE:
    if (type_may_be_null(arg_type) && register_is_null(reg))
    return 0;

    @@ -5987,14 +5979,16 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    err = check_helper_mem_access(env, regno,
    meta->map_ptr->value_size, false,
    meta);
    - } else if (arg_type == ARG_PTR_TO_PERCPU_BTF_ID) {
    + break;
    + case ARG_PTR_TO_PERCPU_BTF_ID:
    if (!reg->btf_id) {
    verbose(env, "Helper has invalid btf_id in R%d\n", regno);
    return -EACCES;
    }
    meta->ret_btf = reg->btf;
    meta->ret_btf_id = reg->btf_id;
    - } else if (arg_type == ARG_PTR_TO_SPIN_LOCK) {
    + break;
    + case ARG_PTR_TO_SPIN_LOCK:
    if (meta->func_id == BPF_FUNC_spin_lock) {
    if (process_spin_lock(env, regno, true))
    return -EACCES;
    @@ -6005,12 +5999,15 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    verbose(env, "verifier internal error\n");
    return -EFAULT;
    }
    - } else if (arg_type == ARG_PTR_TO_TIMER) {
    + break;
    + case ARG_PTR_TO_TIMER:
    if (process_timer_func(env, regno, meta))
    return -EACCES;
    - } else if (arg_type == ARG_PTR_TO_FUNC) {
    + break;
    + case ARG_PTR_TO_FUNC:
    meta->subprogno = reg->subprogno;
    - } else if (base_type(arg_type) == ARG_PTR_TO_MEM) {
    + break;
    + case ARG_PTR_TO_MEM:
    /* The access to this pointer is only checked when we hit the
    * next is_mem_size argument below.
    */
    @@ -6020,11 +6017,14 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    fn->arg_size[arg], false,
    meta);
    }
    - } else if (arg_type_is_mem_size(arg_type)) {
    - bool zero_size_allowed = (arg_type == ARG_CONST_SIZE_OR_ZERO);
    -
    - err = check_mem_size_reg(env, reg, regno, zero_size_allowed, meta);
    - } else if (arg_type_is_dynptr(arg_type)) {
    + break;
    + case ARG_CONST_SIZE:
    + err = check_mem_size_reg(env, reg, regno, false, meta);
    + break;
    + case ARG_CONST_SIZE_OR_ZERO:
    + err = check_mem_size_reg(env, reg, regno, true, meta);
    + break;
    + case ARG_PTR_TO_DYNPTR:
    if (arg_type & MEM_UNINIT) {
    if (!is_dynptr_reg_valid_uninit(env, reg)) {
    verbose(env, "Dynptr has to be an uninitialized dynptr\n");
    @@ -6058,21 +6058,28 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    err_extra, arg + 1);
    return -EINVAL;
    }
    - } else if (arg_type_is_alloc_size(arg_type)) {
    + break;
    + case ARG_CONST_ALLOC_SIZE_OR_ZERO:
    if (!tnum_is_const(reg->var_off)) {
    verbose(env, "R%d is not a known constant'\n",
    regno);
    return -EACCES;
    }
    meta->mem_size = reg->var_off.value;
    - } else if (arg_type_is_int_ptr(arg_type)) {
    + break;
    + case ARG_PTR_TO_INT:
    + case ARG_PTR_TO_LONG:
    + {
    int size = int_ptr_type_to_size(arg_type);

    err = check_helper_mem_access(env, regno, size, false, meta);
    if (err)
    return err;
    err = check_ptr_alignment(env, reg, 0, size, true);
    - } else if (arg_type == ARG_PTR_TO_CONST_STR) {
    + break;
    + }
    + case ARG_PTR_TO_CONST_STR:
    + {
    struct bpf_map *map = reg->map_ptr;
    int map_off;
    u64 map_addr;
    @@ -6111,9 +6118,12 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    verbose(env, "string is not zero-terminated\n");
    return -EINVAL;
    }
    - } else if (arg_type == ARG_PTR_TO_KPTR) {
    + break;
    + }
    + case ARG_PTR_TO_KPTR:
    if (process_kptr_func(env, regno, meta))
    return -EACCES;
    + break;
    }

    return err;
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-09-06 17:27    [W:4.927 / U:0.264 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site