From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Florent Revest <revest@chromium.org>
Cc: bpf <bpf@vger.kernel.org>, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>, Yonghong Song <yhs@fb.com>,
KP Singh <kpsingh@kernel.org>,
Brendan Jackman <jackmanb@chromium.org>,
open list <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH bpf-next 1/5] bpf: Add a ARG_PTR_TO_CONST_STR argument type
Date: Mon, 15 Mar 2021 18:03:11 -0700 [thread overview]
Message-ID: <CAEf4BzZ6Lfmn9pEJSLVhROjkPGJO_mT4nHot8AOjZ_9HTC1rEQ@mail.gmail.com> (raw)
In-Reply-To: <20210310220211.1454516-2-revest@chromium.org>
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
>
next prev parent reply other threads:[~2021-03-16 1:04 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-10 22:02 [PATCH bpf-next 0/5] Add a snprintf eBPF helper Florent Revest
2021-03-10 22:02 ` [PATCH bpf-next 1/5] bpf: Add a ARG_PTR_TO_CONST_STR argument type Florent Revest
2021-03-11 0:04 ` kernel test robot
2021-03-11 1:00 ` kernel test robot
2021-03-16 1:03 ` Andrii Nakryiko [this message]
2021-03-16 23:58 ` Florent Revest
2021-03-17 0:35 ` Andrii Nakryiko
2021-03-17 0:45 ` Florent Revest
2021-03-17 1:02 ` Andrii Nakryiko
2021-03-17 10:32 ` Florent Revest
2021-03-10 22:02 ` [PATCH bpf-next 2/5] bpf: Add a bpf_snprintf helper Florent Revest
2021-03-11 0:14 ` kernel test robot
2021-03-11 3:12 ` kernel test robot
2021-03-11 3:12 ` [RFC PATCH] bpf: check_bpf_snprintf_call() can be static kernel test robot
2021-03-16 1:25 ` [PATCH bpf-next 2/5] bpf: Add a bpf_snprintf helper Andrii Nakryiko
2021-03-16 13:18 ` Florent Revest
2021-03-23 3:21 ` Alexei Starovoitov
2021-03-23 14:04 ` Florent Revest
2021-03-10 22:02 ` [PATCH bpf-next 3/5] libbpf: Initialize the bpf_seq_printf parameters array field by field Florent Revest
2021-03-16 4:36 ` Andrii Nakryiko
2021-03-16 4:41 ` Andrii Nakryiko
2021-03-16 22:43 ` Florent Revest
2021-03-16 23:06 ` Andrii Nakryiko
2021-03-10 22:02 ` [PATCH bpf-next 4/5] libbpf: Introduce a BPF_SNPRINTF helper macro Florent Revest
2021-03-16 4:39 ` Andrii Nakryiko
2021-03-10 22:02 ` [PATCH bpf-next 5/5] selftests/bpf: Add a series of tests for bpf_snprintf Florent Revest
2021-03-16 4:49 ` Andrii Nakryiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAEf4BzZ6Lfmn9pEJSLVhROjkPGJO_mT4nHot8AOjZ_9HTC1rEQ@mail.gmail.com \
--to=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=jackmanb@chromium.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=revest@chromium.org \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).