From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Martin KaFai Lau <martin.lau@kernel.org>,
Dave Marchevsky <davemarchevsky@meta.com>,
Delyan Kratunov <delyank@meta.com>
Subject: [PATCH bpf-next v4 13/24] bpf: Support locking bpf_spin_lock in local kptr
Date: Fri, 4 Nov 2022 00:40:02 +0530 [thread overview]
Message-ID: <20221103191013.1236066-14-memxor@gmail.com> (raw)
In-Reply-To: <20221103191013.1236066-1-memxor@gmail.com>
Allow locking a bpf_spin_lock embedded in local kptr, in addition to
already support map value pointers. The handling is similar to that of
map values, by just preserving the reg->id of local kptrs as well, and
adjusting process_spin_lock to work with non-PTR_TO_MAP_VALUE and
remember the id in verifier state.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
kernel/bpf/helpers.c | 2 ++
kernel/bpf/verifier.c | 70 ++++++++++++++++++++++++++++++++-----------
2 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 339cce94b408..207f622ec70d 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -336,6 +336,7 @@ const struct bpf_func_proto bpf_spin_lock_proto = {
.gpl_only = false,
.ret_type = RET_VOID,
.arg1_type = ARG_PTR_TO_SPIN_LOCK,
+ .arg1_btf_id = BPF_PTR_POISON,
};
static inline void __bpf_spin_unlock_irqrestore(struct bpf_spin_lock *lock)
@@ -358,6 +359,7 @@ const struct bpf_func_proto bpf_spin_unlock_proto = {
.gpl_only = false,
.ret_type = RET_VOID,
.arg1_type = ARG_PTR_TO_SPIN_LOCK,
+ .arg1_btf_id = BPF_PTR_POISON,
};
void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 4de72a4a39bb..c31f20aed30c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -453,8 +453,16 @@ static bool reg_type_not_null(enum bpf_reg_type type)
static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
{
- return reg->type == PTR_TO_MAP_VALUE &&
- btf_record_has_field(reg->map_ptr->record, BPF_SPIN_LOCK);
+ struct btf_record *rec = NULL;
+
+ if (reg->type == PTR_TO_MAP_VALUE) {
+ rec = reg->map_ptr->record;
+ } else if (reg->type == (PTR_TO_BTF_ID | MEM_TYPE_LOCAL)) {
+ struct btf_struct_meta *meta = btf_find_struct_meta(reg->btf, reg->btf_id);
+ if (meta)
+ rec = meta->record;
+ }
+ return btf_record_has_field(rec, BPF_SPIN_LOCK);
}
static bool type_is_rdonly_mem(u32 type)
@@ -5422,8 +5430,10 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno];
struct bpf_verifier_state *cur = env->cur_state;
bool is_const = tnum_is_const(reg->var_off);
- struct bpf_map *map = reg->map_ptr;
u64 val = reg->var_off.value;
+ struct bpf_map *map = NULL;
+ struct btf_record *rec;
+ struct btf *btf = NULL;
if (!is_const) {
verbose(env,
@@ -5431,19 +5441,32 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno,
regno);
return -EINVAL;
}
- if (!map->btf) {
- verbose(env,
- "map '%s' has to have BTF in order to use bpf_spin_lock\n",
- map->name);
- return -EINVAL;
+ if (reg->type == PTR_TO_MAP_VALUE) {
+ map = reg->map_ptr;
+ if (!map->btf) {
+ verbose(env,
+ "map '%s' has to have BTF in order to use bpf_spin_lock\n",
+ map->name);
+ return -EINVAL;
+ }
+ rec = map->record;
+ } else {
+ struct btf_struct_meta *meta;
+
+ btf = reg->btf;
+ meta = btf_find_struct_meta(reg->btf, reg->btf_id);
+ if (meta)
+ rec = meta->record;
}
- if (!btf_record_has_field(map->record, BPF_SPIN_LOCK)) {
- verbose(env, "map '%s' has no valid bpf_spin_lock\n", map->name);
+
+ if (!btf_record_has_field(rec, BPF_SPIN_LOCK)) {
+ verbose(env, "%s '%s' has no valid bpf_spin_lock\n", map ? "map" : "local",
+ map ? map->name : "kptr");
return -EINVAL;
}
- if (map->record->spin_lock_off != val + reg->off) {
+ if (rec->spin_lock_off != val + reg->off) {
verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock' that is at %d\n",
- val + reg->off, map->record->spin_lock_off);
+ val + reg->off, rec->spin_lock_off);
return -EINVAL;
}
if (is_lock) {
@@ -5649,13 +5672,19 @@ static const struct bpf_reg_types int_ptr_types = {
},
};
+static const struct bpf_reg_types spin_lock_types = {
+ .types = {
+ PTR_TO_MAP_VALUE,
+ PTR_TO_BTF_ID | MEM_TYPE_LOCAL,
+ }
+};
+
static const struct bpf_reg_types fullsock_types = { .types = { PTR_TO_SOCKET } };
static const struct bpf_reg_types scalar_types = { .types = { SCALAR_VALUE } };
static const struct bpf_reg_types context_types = { .types = { PTR_TO_CTX } };
static const struct bpf_reg_types alloc_mem_types = { .types = { PTR_TO_MEM | MEM_ALLOC } };
static const struct bpf_reg_types const_map_ptr_types = { .types = { CONST_PTR_TO_MAP } };
static const struct bpf_reg_types btf_ptr_types = { .types = { PTR_TO_BTF_ID } };
-static const struct bpf_reg_types spin_lock_types = { .types = { PTR_TO_MAP_VALUE } };
static const struct bpf_reg_types percpu_btf_ptr_types = { .types = { PTR_TO_BTF_ID | MEM_PERCPU } };
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 } };
@@ -5780,6 +5809,11 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
return -EACCES;
}
}
+ } else if (reg->type == (PTR_TO_BTF_ID | MEM_TYPE_LOCAL)) {
+ if (meta->func_id != BPF_FUNC_spin_lock && meta->func_id != BPF_FUNC_spin_unlock) {
+ verbose(env, "verifier internal error: unimplemented handling of local kptr\n");
+ return -EFAULT;
+ }
}
return 0;
@@ -5896,7 +5930,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
goto skip_type_check;
/* arg_btf_id and arg_size are in a union. */
- if (base_type(arg_type) == ARG_PTR_TO_BTF_ID)
+ if (base_type(arg_type) == ARG_PTR_TO_BTF_ID ||
+ base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK)
arg_btf_id = fn->arg_btf_id[arg];
err = check_reg_type(env, regno, arg_type, arg_btf_id, meta);
@@ -6514,9 +6549,10 @@ static bool check_btf_id_ok(const struct bpf_func_proto *fn)
int i;
for (i = 0; i < ARRAY_SIZE(fn->arg_type); i++) {
- if (base_type(fn->arg_type[i]) == ARG_PTR_TO_BTF_ID && !fn->arg_btf_id[i])
- return false;
-
+ if (base_type(fn->arg_type[i]) == ARG_PTR_TO_BTF_ID)
+ return !!fn->arg_btf_id[i];
+ if (base_type(fn->arg_type[i]) == ARG_PTR_TO_SPIN_LOCK)
+ return fn->arg_btf_id[i] == BPF_PTR_POISON;
if (base_type(fn->arg_type[i]) != ARG_PTR_TO_BTF_ID && fn->arg_btf_id[i] &&
/* arg_btf_id and arg_size are in a union. */
(base_type(fn->arg_type[i]) != ARG_PTR_TO_MEM ||
--
2.38.1
next prev parent reply other threads:[~2022-11-03 19:11 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-03 19:09 [PATCH bpf-next v4 00/24] Local kptrs, BPF linked lists Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 01/24] bpf: Document UAPI details for special BPF types Kumar Kartikeya Dwivedi
2022-11-03 20:38 ` David Vernet
2022-11-03 19:09 ` [PATCH bpf-next v4 02/24] bpf: Allow specifying volatile type modifier for kptrs Kumar Kartikeya Dwivedi
2022-11-03 20:45 ` David Vernet
2022-11-03 19:09 ` [PATCH bpf-next v4 03/24] bpf: Clobber stack slot when writing over spilled PTR_TO_BTF_ID Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 04/24] bpf: Fix slot type check in check_stack_write_var_off Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 05/24] bpf: Drop reg_type_may_be_refcounted_or_null Kumar Kartikeya Dwivedi
2022-11-03 21:55 ` David Vernet
2022-11-03 19:09 ` [PATCH bpf-next v4 06/24] bpf: Refactor kptr_off_tab into btf_record Kumar Kartikeya Dwivedi
2022-11-04 2:44 ` Alexei Starovoitov
2022-11-04 3:00 ` Alexei Starovoitov
2022-11-04 7:02 ` Kumar Kartikeya Dwivedi
2022-11-04 7:27 ` Kumar Kartikeya Dwivedi
2022-11-04 3:16 ` Alexei Starovoitov
2022-11-04 4:00 ` Alexei Starovoitov
2022-11-04 4:09 ` Alexei Starovoitov
2022-11-04 7:34 ` Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 07/24] bpf: Consolidate spin_lock, timer management " Kumar Kartikeya Dwivedi
2022-11-04 4:52 ` Alexei Starovoitov
2022-11-04 5:30 ` Alexei Starovoitov
2022-11-04 6:43 ` Kumar Kartikeya Dwivedi
2022-11-04 6:47 ` Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 08/24] bpf: Refactor map->off_arr handling Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 09/24] bpf: Support bpf_list_head in map values Kumar Kartikeya Dwivedi
2022-11-03 19:09 ` [PATCH bpf-next v4 10/24] bpf: Introduce local kptrs Kumar Kartikeya Dwivedi
2022-11-04 5:57 ` Alexei Starovoitov
2022-11-04 7:51 ` Kumar Kartikeya Dwivedi
2022-11-04 15:38 ` Alexei Starovoitov
2022-11-05 2:19 ` Dave Marchevsky
2022-11-03 19:10 ` [PATCH bpf-next v4 11/24] bpf: Recognize bpf_{spin_lock,list_head,list_node} in " Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 12/24] bpf: Verify ownership relationships for user BTF types Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` Kumar Kartikeya Dwivedi [this message]
2022-11-03 19:10 ` [PATCH bpf-next v4 14/24] bpf: Allow locking bpf_spin_lock global variables Kumar Kartikeya Dwivedi
2022-11-04 2:54 ` Dave Marchevsky
2022-11-04 7:56 ` Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 15/24] bpf: Rewrite kfunc argument handling Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 16/24] bpf: Drop kfunc bits from btf_check_func_arg_match Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 17/24] bpf: Support constant scalar arguments for kfuncs Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 18/24] bpf: Teach verifier about non-size constant arguments Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 19/24] bpf: Introduce bpf_obj_new Kumar Kartikeya Dwivedi
2022-11-04 2:37 ` Dave Marchevsky
2022-11-04 8:09 ` Kumar Kartikeya Dwivedi
2022-11-04 15:39 ` Alexei Starovoitov
2022-11-03 19:10 ` [PATCH bpf-next v4 20/24] bpf: Introduce bpf_obj_drop Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 21/24] bpf: Permit NULL checking pointer with non-zero fixed offset Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 22/24] bpf: Introduce single ownership BPF linked list API Kumar Kartikeya Dwivedi
2022-11-04 5:56 ` Dave Marchevsky
2022-11-04 7:42 ` Kumar Kartikeya Dwivedi
2022-11-05 2:15 ` Dave Marchevsky
2022-11-05 18:16 ` Alexei Starovoitov
2022-11-06 1:53 ` Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 23/24] selftests/bpf: Add __contains macro to bpf_experimental.h Kumar Kartikeya Dwivedi
2022-11-03 19:10 ` [PATCH bpf-next v4 24/24] selftests/bpf: Add BPF linked list API tests Kumar Kartikeya Dwivedi
2022-11-04 7:03 ` Dave Marchevsky
2022-11-04 7:14 ` Kumar Kartikeya Dwivedi
2022-11-04 5:00 ` [PATCH bpf-next v4 00/24] Local kptrs, BPF linked lists patchwork-bot+netdevbpf
2022-11-04 5:30 ` patchwork-bot+netdevbpf
2022-11-04 6:30 ` patchwork-bot+netdevbpf
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=20221103191013.1236066-14-memxor@gmail.com \
--to=memxor@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davemarchevsky@meta.com \
--cc=delyank@meta.com \
--cc=martin.lau@kernel.org \
/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