lkml.org 
[lkml]   [2021]   [Mar]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    Date
    SubjectRe: [PATCH bpf-next 1/5] bpf: Add a ARG_PTR_TO_CONST_STR argument type
    On Wed, Mar 10, 2021 at 2:02 PM Florent Revest <revest@chromium.org> wrote:
    >
    > This type provides the guarantee that an argument is going to be a const
    > pointer to somewhere in a read-only map value. It also checks that this
    > pointer is followed by a NULL character before the end of the map value.
    >
    > Signed-off-by: Florent Revest <revest@chromium.org>
    > ---
    > include/linux/bpf.h | 1 +
    > kernel/bpf/verifier.c | 41 +++++++++++++++++++++++++++++++++++++++++
    > 2 files changed, 42 insertions(+)
    >
    > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    > index a25730eaa148..7b5319d75b3e 100644
    > --- a/include/linux/bpf.h
    > +++ b/include/linux/bpf.h
    > @@ -308,6 +308,7 @@ enum bpf_arg_type {
    > ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */
    > ARG_PTR_TO_FUNC, /* pointer to a bpf program function */
    > ARG_PTR_TO_STACK_OR_NULL, /* pointer to stack or NULL */
    > + ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */
    > __BPF_ARG_TYPE_MAX,
    > };
    >
    > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
    > index f9096b049cd6..c99b2b67dc8d 100644
    > --- a/kernel/bpf/verifier.c
    > +++ b/kernel/bpf/verifier.c
    > @@ -4601,6 +4601,7 @@ static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALU
    > static const struct bpf_reg_types percpu_btf_ptr_types = { .types = { PTR_TO_PERCPU_BTF_ID } };
    > static const struct bpf_reg_types func_ptr_types = { .types = { PTR_TO_FUNC } };
    > static const struct bpf_reg_types stack_ptr_types = { .types = { PTR_TO_STACK } };
    > +static const struct bpf_reg_types const_str_ptr_types = { .types = { PTR_TO_MAP_VALUE } };
    >
    > static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
    > [ARG_PTR_TO_MAP_KEY] = &map_key_value_types,
    > @@ -4631,6 +4632,7 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
    > [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types,
    > [ARG_PTR_TO_FUNC] = &func_ptr_types,
    > [ARG_PTR_TO_STACK_OR_NULL] = &stack_ptr_types,
    > + [ARG_PTR_TO_CONST_STR] = &const_str_ptr_types,
    > };
    >
    > static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
    > @@ -4881,6 +4883,45 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
    > if (err)
    > return err;
    > err = check_ptr_alignment(env, reg, 0, size, true);
    > + } else if (arg_type == ARG_PTR_TO_CONST_STR) {
    > + struct bpf_map *map = reg->map_ptr;
    > + int map_off, i;
    > + u64 map_addr;
    > + char *map_ptr;
    > +
    > + if (!map || !bpf_map_is_rdonly(map)) {
    > + verbose(env, "R%d does not point to a readonly map'\n", regno);
    > + return -EACCES;
    > + }
    > +
    > + if (!tnum_is_const(reg->var_off)) {
    > + verbose(env, "R%d is not a constant address'\n", regno);
    > + return -EACCES;
    > + }
    > +
    > + if (!map->ops->map_direct_value_addr) {
    > + verbose(env, "no direct value access support for this map type\n");
    > + return -EACCES;
    > + }
    > +
    > + err = check_helper_mem_access(env, regno,
    > + map->value_size - reg->off,
    > + false, meta);

    you expect reg to be PTR_TO_MAP_VALUE, so probably better to directly
    use check_map_access(). And double-check that register is of expected
    type. just the presence of ref->map_ptr might not be sufficient?

    > + if (err)
    > + return err;
    > +
    > + map_off = reg->off + reg->var_off.value;
    > + err = map->ops->map_direct_value_addr(map, &map_addr, map_off);
    > + if (err)
    > + return err;
    > +
    > + map_ptr = (char *)(map_addr);

    map_ptr is a very confusing name. str_ptr or value ptr?

    > + for (i = map_off; map_ptr[i] != '\0'; i++) {
    > + if (i == map->value_size - 1) {

    use strnchr()?

    > + verbose(env, "map does not contain a NULL-terminated string\n");

    map in the user-visible message is quite confusing, given that users
    will probably use this through static variables, so maybe just "string
    is not zero-terminated?" And it's not really a NULL, it's zero
    character.

    > + return -EACCES;
    > + }
    > + }
    > }
    >
    > return err;
    > --
    > 2.30.1.766.gb4fecdf3b7-goog
    >

    \
     
     \ /
      Last update: 2021-03-16 02:04    [W:4.253 / U:0.356 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site