Message ID | 20231104001313.3538201-4-song@kernel.org (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | bpf: File verification with LSM and fsverity | expand |
On 04/11/2023 00:13, Song Liu wrote: > Similar to ARG_PTR_TO_CONST_STR for BPF helpers, KF_ARG_PTR_TO_CONST_STR > specifies kfunc args that point to const strings. Annotation "__str" is > used to specify kfunc arg of type KF_ARG_PTR_TO_CONST_STR. Also, add > documentation for the "__str" annotation. > > bpf_get_file_xattr() will be the first kfunc that uses this type. > > Signed-off-by: Song Liu <song@kernel.org> > Acked-by: Andrii Nakryiko <andrii@kernel.org> > --- > Documentation/bpf/kfuncs.rst | 24 ++++++++++++++++++++++++ > kernel/bpf/verifier.c | 19 +++++++++++++++++++ > 2 files changed, 43 insertions(+) > > diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst > index 0d2647fb358d..bfe065f7e23c 100644 > --- a/Documentation/bpf/kfuncs.rst > +++ b/Documentation/bpf/kfuncs.rst > @@ -137,6 +137,30 @@ Either way, the returned buffer is either NULL, or of size buffer_szk. Without t > annotation, the verifier will reject the program if a null pointer is passed in with > a nonzero size. > > +2.2.5 __str Annotation > +---------------------------- > +This annotation is used to indicate that the argument is a constant string. > + > +An example is given below:: > + > + __bpf_kfunc bpf_get_file_xattr(..., const char *name__str, ...) > + { > + ... > + } > + > +In this case, ``bpf_get_file_xattr()`` can be called as:: > + > + bpf_get_file_xattr(..., "xattr_name", ...); > + > +Or:: > + > + const char name[] = "xattr_name"; /* This need to be global */ > + int BPF_PROG(...) > + { > + ... > + bpf_get_file_xattr(..., name, ...); > + ... > + } > > .. _BPF_kfunc_nodef: > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 618446006d5a..bf94ba50c6ee 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -10803,6 +10803,11 @@ static bool is_kfunc_arg_nullable(const struct btf *btf, const struct btf_param > return __kfunc_param_match_suffix(btf, arg, "__nullable"); > } > > +static bool is_kfunc_arg_const_str(const struct btf *btf, const struct btf_param *arg) > +{ > + return __kfunc_param_match_suffix(btf, arg, "__str"); > +} > + > static bool is_kfunc_arg_scalar_with_name(const struct btf *btf, > const struct btf_param *arg, > const char *name) > @@ -10946,6 +10951,7 @@ enum kfunc_ptr_arg_type { > KF_ARG_PTR_TO_RB_ROOT, > KF_ARG_PTR_TO_RB_NODE, > KF_ARG_PTR_TO_NULL, > + KF_ARG_PTR_TO_CONST_STR, > }; > > enum special_kfunc_type { > @@ -11090,6 +11096,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, > if (is_kfunc_arg_rbtree_node(meta->btf, &args[argno])) > return KF_ARG_PTR_TO_RB_NODE; > > + if (is_kfunc_arg_const_str(meta->btf, &args[argno])) > + return KF_ARG_PTR_TO_CONST_STR; > + > if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) { > if (!btf_type_is_struct(ref_t)) { > verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n", > @@ -11713,6 +11722,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ > case KF_ARG_PTR_TO_MEM_SIZE: > case KF_ARG_PTR_TO_CALLBACK: > case KF_ARG_PTR_TO_REFCOUNTED_KPTR: > + case KF_ARG_PTR_TO_CONST_STR: > /* Trusted by default */ > break; > default: > @@ -11984,6 +11994,15 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ > meta->arg_btf = reg->btf; > meta->arg_btf_id = reg->btf_id; > break; > + case KF_ARG_PTR_TO_CONST_STR: > + if (reg->type != PTR_TO_MAP_VALUE) { > + verbose(env, "arg#%d doesn't point to a const string\n", i); > + return -EINVAL; > + } > + ret = check_reg_const_str(env, reg, regno); > + if (ret) > + return ret; > + break; > } > } > Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> Alexei, Andrii, is it possible to apply patches 1-3? Looks like they are ready to go and can unblock other work.
diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst index 0d2647fb358d..bfe065f7e23c 100644 --- a/Documentation/bpf/kfuncs.rst +++ b/Documentation/bpf/kfuncs.rst @@ -137,6 +137,30 @@ Either way, the returned buffer is either NULL, or of size buffer_szk. Without t annotation, the verifier will reject the program if a null pointer is passed in with a nonzero size. +2.2.5 __str Annotation +---------------------------- +This annotation is used to indicate that the argument is a constant string. + +An example is given below:: + + __bpf_kfunc bpf_get_file_xattr(..., const char *name__str, ...) + { + ... + } + +In this case, ``bpf_get_file_xattr()`` can be called as:: + + bpf_get_file_xattr(..., "xattr_name", ...); + +Or:: + + const char name[] = "xattr_name"; /* This need to be global */ + int BPF_PROG(...) + { + ... + bpf_get_file_xattr(..., name, ...); + ... + } .. _BPF_kfunc_nodef: diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 618446006d5a..bf94ba50c6ee 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10803,6 +10803,11 @@ static bool is_kfunc_arg_nullable(const struct btf *btf, const struct btf_param return __kfunc_param_match_suffix(btf, arg, "__nullable"); } +static bool is_kfunc_arg_const_str(const struct btf *btf, const struct btf_param *arg) +{ + return __kfunc_param_match_suffix(btf, arg, "__str"); +} + static bool is_kfunc_arg_scalar_with_name(const struct btf *btf, const struct btf_param *arg, const char *name) @@ -10946,6 +10951,7 @@ enum kfunc_ptr_arg_type { KF_ARG_PTR_TO_RB_ROOT, KF_ARG_PTR_TO_RB_NODE, KF_ARG_PTR_TO_NULL, + KF_ARG_PTR_TO_CONST_STR, }; enum special_kfunc_type { @@ -11090,6 +11096,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env, if (is_kfunc_arg_rbtree_node(meta->btf, &args[argno])) return KF_ARG_PTR_TO_RB_NODE; + if (is_kfunc_arg_const_str(meta->btf, &args[argno])) + return KF_ARG_PTR_TO_CONST_STR; + if ((base_type(reg->type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) { if (!btf_type_is_struct(ref_t)) { verbose(env, "kernel function %s args#%d pointer type %s %s is not supported\n", @@ -11713,6 +11722,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ case KF_ARG_PTR_TO_MEM_SIZE: case KF_ARG_PTR_TO_CALLBACK: case KF_ARG_PTR_TO_REFCOUNTED_KPTR: + case KF_ARG_PTR_TO_CONST_STR: /* Trusted by default */ break; default: @@ -11984,6 +11994,15 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ meta->arg_btf = reg->btf; meta->arg_btf_id = reg->btf_id; break; + case KF_ARG_PTR_TO_CONST_STR: + if (reg->type != PTR_TO_MAP_VALUE) { + verbose(env, "arg#%d doesn't point to a const string\n", i); + return -EINVAL; + } + ret = check_reg_const_str(env, reg, regno); + if (ret) + return ret; + break; } }