Skip to content

Commit 5eab266

Browse files
mykyta5Alexei Starovoitov
authored andcommitted
bpf: extract generic helper from process_timer_func()
Refactor the verifier by pulling the common logic from process_timer_func() into a dedicated helper. This allows reusing process_async_func() helper for verifying bpf_task_work struct in the next patch. Signed-off-by: Mykyta Yatsenko <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Tested-by: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent f902132 commit 5eab266

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

kernel/bpf/verifier.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8431,34 +8431,59 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
84318431
return 0;
84328432
}
84338433

8434-
static int process_timer_func(struct bpf_verifier_env *env, int regno,
8435-
struct bpf_call_arg_meta *meta)
8434+
/* Check if @regno is a pointer to a specific field in a map value */
8435+
static int check_map_field_pointer(struct bpf_verifier_env *env, u32 regno,
8436+
enum btf_field_type field_type)
84368437
{
84378438
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
84388439
bool is_const = tnum_is_const(reg->var_off);
84398440
struct bpf_map *map = reg->map_ptr;
84408441
u64 val = reg->var_off.value;
8442+
const char *struct_name = btf_field_type_name(field_type);
8443+
int field_off = -1;
84418444

84428445
if (!is_const) {
84438446
verbose(env,
8444-
"R%d doesn't have constant offset. bpf_timer has to be at the constant offset\n",
8445-
regno);
8447+
"R%d doesn't have constant offset. %s has to be at the constant offset\n",
8448+
regno, struct_name);
84468449
return -EINVAL;
84478450
}
84488451
if (!map->btf) {
8449-
verbose(env, "map '%s' has to have BTF in order to use bpf_timer\n",
8450-
map->name);
8452+
verbose(env, "map '%s' has to have BTF in order to use %s\n", map->name,
8453+
struct_name);
84518454
return -EINVAL;
84528455
}
8453-
if (!btf_record_has_field(map->record, BPF_TIMER)) {
8454-
verbose(env, "map '%s' has no valid bpf_timer\n", map->name);
8456+
if (!btf_record_has_field(map->record, field_type)) {
8457+
verbose(env, "map '%s' has no valid %s\n", map->name, struct_name);
84558458
return -EINVAL;
84568459
}
8457-
if (map->record->timer_off != val + reg->off) {
8458-
verbose(env, "off %lld doesn't point to 'struct bpf_timer' that is at %d\n",
8459-
val + reg->off, map->record->timer_off);
8460+
switch (field_type) {
8461+
case BPF_TIMER:
8462+
field_off = map->record->timer_off;
8463+
break;
8464+
default:
8465+
verifier_bug(env, "unsupported BTF field type: %s\n", struct_name);
84608466
return -EINVAL;
84618467
}
8468+
if (field_off != val + reg->off) {
8469+
verbose(env, "off %lld doesn't point to 'struct %s' that is at %d\n",
8470+
val + reg->off, struct_name, field_off);
8471+
return -EINVAL;
8472+
}
8473+
return 0;
8474+
}
8475+
8476+
static int process_timer_func(struct bpf_verifier_env *env, int regno,
8477+
struct bpf_call_arg_meta *meta)
8478+
{
8479+
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
8480+
struct bpf_map *map = reg->map_ptr;
8481+
int err;
8482+
8483+
err = check_map_field_pointer(env, regno, BPF_TIMER);
8484+
if (err)
8485+
return err;
8486+
84628487
if (meta->map_ptr) {
84638488
verifier_bug(env, "Two map pointers in a timer helper");
84648489
return -EFAULT;

0 commit comments

Comments
 (0)