From: Jiri Olsa <jolsa@kernel.org>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andriin@fb.com>
Cc: netdev@vger.kernel.org, bpf@vger.kernel.org,
Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
Martin KaFai Lau <kafai@fb.com>, David Miller <davem@redhat.com>,
John Fastabend <john.fastabend@gmail.com>,
Wenbo Zhang <ethercflow@gmail.com>,
KP Singh <kpsingh@chromium.org>,
Brendan Gregg <bgregg@netflix.com>,
Florent Revest <revest@chromium.org>,
Al Viro <viro@zeniv.linux.org.uk>
Subject: [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function
Date: Sat, 1 Aug 2020 19:03:16 +0200 [thread overview]
Message-ID: <20200801170322.75218-9-jolsa@kernel.org> (raw)
In-Reply-To: <20200801170322.75218-1-jolsa@kernel.org>
Adding btf_struct_ids_match function to check if given address provided
by BTF object + offset is also address of another nested BTF object.
This allows to pass an argument to helper, which is defined via parent
BTF object + offset, like for bpf_d_path (added in following changes):
SEC("fentry/filp_close")
int BPF_PROG(prog_close, struct file *file, void *id)
{
...
ret = bpf_d_path(&file->f_path, ...
The first bpf_d_path argument is hold by verifier as BTF file object
plus offset of f_path member.
The btf_struct_ids_match function will walk the struct file object and
check if there's nested struct path object on the given offset.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
include/linux/bpf.h | 2 ++
kernel/bpf/btf.c | 31 +++++++++++++++++++++++++++++++
kernel/bpf/verifier.c | 20 +++++++++++++-------
3 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 40c5e206ecf2..8206d5e324be 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1337,6 +1337,8 @@ int btf_struct_access(struct bpf_verifier_log *log,
const struct btf_type *t, int off, int size,
enum bpf_access_type atype,
u32 *next_btf_id);
+bool btf_struct_ids_match(struct bpf_verifier_log *log,
+ int off, u32 id, u32 need_type_id);
int btf_resolve_helper_id(struct bpf_verifier_log *log,
const struct bpf_func_proto *fn, int);
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7bacc2f56061..ba05b15ad599 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4160,6 +4160,37 @@ int btf_struct_access(struct bpf_verifier_log *log,
return -EINVAL;
}
+bool btf_struct_ids_match(struct bpf_verifier_log *log,
+ int off, u32 id, u32 need_type_id)
+{
+ const struct btf_type *type;
+ int err;
+
+ /* Are we already done? */
+ if (need_type_id == id && off == 0)
+ return true;
+
+again:
+ type = btf_type_by_id(btf_vmlinux, id);
+ if (!type)
+ return false;
+ err = btf_struct_walk(log, type, off, 1, &id);
+ if (err != WALK_STRUCT)
+ return false;
+
+ /* We found nested struct object. If it matches
+ * the requested ID, we're done. Otherwise let's
+ * continue the search with offset 0 in the new
+ * type.
+ */
+ if (need_type_id != id) {
+ off = 0;
+ goto again;
+ }
+
+ return true;
+}
+
int btf_resolve_helper_id(struct bpf_verifier_log *log,
const struct bpf_func_proto *fn, int arg)
{
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b6ccfce3bf4c..bb6ca19f282d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3960,16 +3960,21 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
goto err_type;
}
} else if (arg_type == ARG_PTR_TO_BTF_ID) {
+ bool ids_match = false;
+
expected_type = PTR_TO_BTF_ID;
if (type != expected_type)
goto err_type;
if (!fn->check_btf_id) {
- if (reg->btf_id != meta->btf_id) {
- verbose(env, "Helper has type %s got %s in R%d\n",
- kernel_type_name(meta->btf_id),
- kernel_type_name(reg->btf_id), regno);
-
- return -EACCES;
+ if (reg->btf_id != meta->btf_id || reg->off) {
+ ids_match = btf_struct_ids_match(&env->log, reg->off, reg->btf_id,
+ meta->btf_id);
+ if (!ids_match) {
+ verbose(env, "Helper has type %s got %s in R%d\n",
+ kernel_type_name(meta->btf_id),
+ kernel_type_name(reg->btf_id), regno);
+ return -EACCES;
+ }
}
} else if (!fn->check_btf_id(reg->btf_id, arg)) {
verbose(env, "Helper does not support %s in R%d\n",
@@ -3977,7 +3982,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
return -EACCES;
}
- if (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off) {
+ if (!ids_match &&
+ (!tnum_is_const(reg->var_off) || reg->var_off.value || reg->off)) {
verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
regno);
return -EACCES;
--
2.25.4
next prev parent reply other threads:[~2020-08-01 17:04 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-01 17:03 [PATCH v9 bpf-next 00/14] bpf: Add d_path helper Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 01/14] tools resolve_btfids: Add size check to get_id function Jiri Olsa
2020-08-05 6:00 ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 02/14] tools resolve_btfids: Add support for set symbols Jiri Olsa
2020-08-05 6:04 ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 03/14] bpf: Move btf_resolve_size into __btf_resolve_size Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 04/14] bpf: Add elem_id pointer as argument to __btf_resolve_size Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 05/14] bpf: Add type_id " Jiri Olsa
2020-08-05 6:05 ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 06/14] bpf: Remove recursion call in btf_struct_access Jiri Olsa
2020-08-05 6:12 ` Andrii Nakryiko
2020-08-05 17:36 ` Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 07/14] bpf: Factor btf_struct_access function Jiri Olsa
2020-08-05 6:18 ` Andrii Nakryiko
2020-08-01 17:03 ` Jiri Olsa [this message]
2020-08-05 6:27 ` [PATCH v9 bpf-next 08/14] bpf: Add btf_struct_ids_match function Andrii Nakryiko
2020-08-05 17:56 ` Jiri Olsa
2020-08-05 21:31 ` Jiri Olsa
2020-08-05 21:57 ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 09/14] bpf: Add BTF_SET_START/END macros Jiri Olsa
2020-08-05 6:29 ` Andrii Nakryiko
2020-08-01 17:03 ` [PATCH v9 bpf-next 10/14] bpf: Add d_path helper Jiri Olsa
2020-08-02 3:13 ` Alexei Starovoitov
2020-08-02 18:26 ` Jiri Olsa
2020-08-05 6:35 ` Andrii Nakryiko
2020-08-05 17:58 ` Jiri Olsa
2020-08-05 21:01 ` Jiri Olsa
2020-08-05 21:09 ` Andrii Nakryiko
2020-08-07 0:31 ` KP Singh
2020-08-07 8:35 ` Jiri Olsa
2020-08-07 9:42 ` KP Singh
2020-08-01 17:03 ` [PATCH v9 bpf-next 11/14] bpf: Update .BTF_ids section in btf.rst with sets info Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 12/14] selftests/bpf: Add verifier test for d_path helper Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 13/14] selftests/bpf: Add " Jiri Olsa
2020-08-05 6:40 ` Andrii Nakryiko
2020-08-05 18:00 ` Jiri Olsa
2020-08-01 17:03 ` [PATCH v9 bpf-next 14/14] selftests/bpf: Add set test to resolve_btfids Jiri Olsa
2020-08-05 6:41 ` 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=20200801170322.75218-9-jolsa@kernel.org \
--to=jolsa@kernel.org \
--cc=andriin@fb.com \
--cc=ast@kernel.org \
--cc=bgregg@netflix.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@redhat.com \
--cc=ethercflow@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=netdev@vger.kernel.org \
--cc=revest@chromium.org \
--cc=songliubraving@fb.com \
--cc=viro@zeniv.linux.org.uk \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.