Skip to content

Commit a808097

Browse files
mykyta5Kernel Patches Daemon
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]
1 parent 037bce3 commit a808097

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

kernel/bpf/verifier.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8520,34 +8520,54 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
85208520
return 0;
85218521
}
85228522

8523-
static int process_timer_func(struct bpf_verifier_env *env, int regno,
8524-
struct bpf_call_arg_meta *meta)
8523+
/* Check if @regno is a pointer to a specific field in a map value */
8524+
static int check_map_field_pointer(struct bpf_verifier_env *env, u32 regno,
8525+
enum btf_field_type field_type, u32 rec_off)
85258526
{
85268527
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
85278528
bool is_const = tnum_is_const(reg->var_off);
85288529
struct bpf_map *map = reg->map_ptr;
85298530
u64 val = reg->var_off.value;
8531+
const char *struct_name = btf_field_type_name(field_type);
8532+
int field_off;
85308533

85318534
if (!is_const) {
85328535
verbose(env,
8533-
"R%d doesn't have constant offset. bpf_timer has to be at the constant offset\n",
8534-
regno);
8536+
"R%d doesn't have constant offset. %s has to be at the constant offset\n",
8537+
regno, struct_name);
85358538
return -EINVAL;
85368539
}
85378540
if (!map->btf) {
8538-
verbose(env, "map '%s' has to have BTF in order to use bpf_timer\n",
8539-
map->name);
8541+
verbose(env, "map '%s' has to have BTF in order to use %s\n", map->name,
8542+
struct_name);
85408543
return -EINVAL;
85418544
}
8542-
if (!btf_record_has_field(map->record, BPF_TIMER)) {
8543-
verbose(env, "map '%s' has no valid bpf_timer\n", map->name);
8545+
if (!btf_record_has_field(map->record, field_type)) {
8546+
verbose(env, "map '%s' has no valid %s\n", map->name, struct_name);
85448547
return -EINVAL;
85458548
}
8546-
if (map->record->timer_off != val + reg->off) {
8547-
verbose(env, "off %lld doesn't point to 'struct bpf_timer' that is at %d\n",
8548-
val + reg->off, map->record->timer_off);
8549+
/* Now it's safe to dereference map->record */
8550+
field_off = *(int *)((void *)map->record + rec_off);
8551+
if (field_off != val + reg->off) {
8552+
verbose(env, "off %lld doesn't point to 'struct %s' that is at %d\n",
8553+
val + reg->off, struct_name, field_off);
85498554
return -EINVAL;
85508555
}
8556+
return 0;
8557+
}
8558+
8559+
static int process_timer_func(struct bpf_verifier_env *env, int regno,
8560+
struct bpf_call_arg_meta *meta)
8561+
{
8562+
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
8563+
struct bpf_map *map = reg->map_ptr;
8564+
int err;
8565+
8566+
err = check_map_field_pointer(env, regno, BPF_TIMER,
8567+
offsetof(struct btf_record, timer_off));
8568+
if (err)
8569+
return err;
8570+
85518571
if (meta->map_ptr) {
85528572
verifier_bug(env, "Two map pointers in a timer helper");
85538573
return -EFAULT;

0 commit comments

Comments
 (0)