diff mbox series

[bpf-next,v1] bpf: Tidy up verifier check_func_arg()

Message ID 20220712210603.123791-1-joannelkoong@gmail.com (mailing list archive)
State Accepted
Commit 8ab4cdcf03d0b060fbf73f76460f199bbd759ff7
Delegated to: BPF
Headers show
Series [bpf-next,v1] bpf: Tidy up verifier check_func_arg() | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 20 this patch: 20
netdev/cc_maintainers warning 8 maintainers not CCed: haoluo@google.com song@kernel.org yhs@fb.com martin.lau@linux.dev john.fastabend@gmail.com jolsa@kernel.org sdf@google.com kpsingh@kernel.org
netdev/build_clang success Errors and warnings before: 6 this patch: 6
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 20 this patch: 20
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 143 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-1 success Logs for Kernel LATEST on ubuntu-latest with gcc
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Kernel LATEST on ubuntu-latest with llvm-15
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Kernel LATEST on z15 with gcc

Commit Message

Joanne Koong July 12, 2022, 9:06 p.m. UTC
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>
---
 kernel/bpf/verifier.c | 66 +++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 28 deletions(-)

Comments

Stanislav Fomichev July 12, 2022, 10:44 p.m. UTC | #1
On 07/12, Joanne Koong wrote:
> 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.

Does this need a fixes tag? Something around the following maybe:

Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")

?

> 2. Uses switch casing to improve readability + efficiency.

> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> ---
>   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 328cfab3af60..26e7e787c20a 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.30.2
Joanne Koong July 13, 2022, 1:10 a.m. UTC | #2
On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
>
> On 07/12, Joanne Koong wrote:
> > 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.
>
> Does this need a fixes tag? Something around the following maybe:
>
> Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
>
> ?
I will add that tag. Thanks!
>
> > 2. Uses switch casing to improve readability + efficiency.
>
> > Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> > ---
> >   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 328cfab3af60..26e7e787c20a 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.30.2
>
Hao Luo July 13, 2022, 1:20 a.m. UTC | #3
On Tue, Jul 12, 2022 at 6:10 PM Joanne Koong <joannelkoong@gmail.com> wrote:
>
> On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
> >
> > On 07/12, Joanne Koong wrote:
> > > 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.
> >
> > Does this need a fixes tag? Something around the following maybe:
> >
> > Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
> >
> > ?
> I will add that tag. Thanks!

Joanne and Stan, IMO this is not necessary. I think this change is a
cleanup rather than a fix.

> >
> > > 2. Uses switch casing to improve readability + efficiency.
> >
> > > Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> > > ---
[...]
> >
Alexei Starovoitov July 13, 2022, 1:25 a.m. UTC | #4
On Tue, Jul 12, 2022 at 6:20 PM Hao Luo <haoluo@google.com> wrote:
>
> On Tue, Jul 12, 2022 at 6:10 PM Joanne Koong <joannelkoong@gmail.com> wrote:
> >
> > On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
> > >
> > > On 07/12, Joanne Koong wrote:
> > > > 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.
> > >
> > > Does this need a fixes tag? Something around the following maybe:
> > >
> > > Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
> > >
> > > ?
> > I will add that tag. Thanks!
>
> Joanne and Stan, IMO this is not necessary. I think this change is a
> cleanup rather than a fix.

I don't see the bug easier.
The helper types that are compared directly as arg_type
instead of base_type(arg_type) were all without flags so far.
So I don't think the patch changes behavior or fixes anything today.
It looks like a good future proofing change though.
Am I missing something?
Hao Luo July 13, 2022, 1:38 a.m. UTC | #5
On Tue, Jul 12, 2022 at 6:26 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Tue, Jul 12, 2022 at 6:20 PM Hao Luo <haoluo@google.com> wrote:
> >
> > On Tue, Jul 12, 2022 at 6:10 PM Joanne Koong <joannelkoong@gmail.com> wrote:
> > >
> > > On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
> > > >
> > > > On 07/12, Joanne Koong wrote:
> > > > > 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.
> > > >
> > > > Does this need a fixes tag? Something around the following maybe:
> > > >
> > > > Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
> > > >
> > > > ?
> > > I will add that tag. Thanks!
> >
> > Joanne and Stan, IMO this is not necessary. I think this change is a
> > cleanup rather than a fix.
>
> I don't see the bug easier.
> The helper types that are compared directly as arg_type
> instead of base_type(arg_type) were all without flags so far.
> So I don't think the patch changes behavior or fixes anything today.
> It looks like a good future proofing change though.
> Am I missing something?

Agree, I mean adding a fixes tag isn't necessary and the patch is
toward a good direction. As long as the selftests pass on this patch,
it looks good to me.

Acked-by: Hao Luo <haoluo@google.com>
Stanislav Fomichev July 13, 2022, 2:10 a.m. UTC | #6
On Tue, Jul 12, 2022 at 6:39 PM Hao Luo <haoluo@google.com> wrote:
>
> On Tue, Jul 12, 2022 at 6:26 PM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Tue, Jul 12, 2022 at 6:20 PM Hao Luo <haoluo@google.com> wrote:
> > >
> > > On Tue, Jul 12, 2022 at 6:10 PM Joanne Koong <joannelkoong@gmail.com> wrote:
> > > >
> > > > On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
> > > > >
> > > > > On 07/12, Joanne Koong wrote:
> > > > > > 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.
> > > > >
> > > > > Does this need a fixes tag? Something around the following maybe:
> > > > >
> > > > > Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
> > > > >
> > > > > ?
> > > > I will add that tag. Thanks!
> > >
> > > Joanne and Stan, IMO this is not necessary. I think this change is a
> > > cleanup rather than a fix.
> >
> > I don't see the bug easier.
> > The helper types that are compared directly as arg_type
> > instead of base_type(arg_type) were all without flags so far.
> > So I don't think the patch changes behavior or fixes anything today.
> > It looks like a good future proofing change though.
> > Am I missing something?
>
> Agree, I mean adding a fixes tag isn't necessary and the patch is
> toward a good direction. As long as the selftests pass on this patch,
> it looks good to me.
>
> Acked-by: Hao Luo <haoluo@google.com>

Perfect, thanks for clarifying! It wasn't clear from the description
so I started looking for where that base_type() came from.
Joanne Koong July 13, 2022, 8:09 p.m. UTC | #7
On Tue, Jul 12, 2022 at 7:10 PM Stanislav Fomichev <sdf@google.com> wrote:
>
> On Tue, Jul 12, 2022 at 6:39 PM Hao Luo <haoluo@google.com> wrote:
> >
> > On Tue, Jul 12, 2022 at 6:26 PM Alexei Starovoitov
> > <alexei.starovoitov@gmail.com> wrote:
> > >
> > > On Tue, Jul 12, 2022 at 6:20 PM Hao Luo <haoluo@google.com> wrote:
> > > >
> > > > On Tue, Jul 12, 2022 at 6:10 PM Joanne Koong <joannelkoong@gmail.com> wrote:
> > > > >
> > > > > On Tue, Jul 12, 2022 at 3:44 PM <sdf@google.com> wrote:
> > > > > >
> > > > > > On 07/12, Joanne Koong wrote:
> > > > > > > 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.
> > > > > >
> > > > > > Does this need a fixes tag? Something around the following maybe:
> > > > > >
> > > > > > Fixes: d639b9d13a39 ("bpf: Introduce composable reg, ret and arg types.")
> > > > > >
> > > > > > ?
> > > > > I will add that tag. Thanks!
> > > >
> > > > Joanne and Stan, IMO this is not necessary. I think this change is a
> > > > cleanup rather than a fix.
> > >
> > > I don't see the bug easier.
> > > The helper types that are compared directly as arg_type
> > > instead of base_type(arg_type) were all without flags so far.
> > > So I don't think the patch changes behavior or fixes anything today.
> > > It looks like a good future proofing change though.
> > > Am I missing something?
> >
> > Agree, I mean adding a fixes tag isn't necessary and the patch is
> > toward a good direction. As long as the selftests pass on this patch,
> > it looks good to me.
> >
> > Acked-by: Hao Luo <haoluo@google.com>
>
> Perfect, thanks for clarifying! It wasn't clear from the description
> so I started looking for where that base_type() came from.
Great, I will leave it as is then. Thanks for the feedback.
patchwork-bot+netdevbpf@kernel.org July 13, 2022, 9:50 p.m. UTC | #8
Hello:

This patch was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Tue, 12 Jul 2022 14:06:03 -0700 you wrote:
> 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.
> 
> [...]

Here is the summary with links:
  - [bpf-next,v1] bpf: Tidy up verifier check_func_arg()
    https://git.kernel.org/bpf/bpf-next/c/8ab4cdcf03d0

You are awesome, thank you!
diff mbox series

Patch

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 328cfab3af60..26e7e787c20a 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;