@@ -8431,34 +8431,59 @@ static int process_spin_lock(struct bpf_verifier_env *env, int regno, int flags)
8431
8431
return 0;
8432
8432
}
8433
8433
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)
8436
8437
{
8437
8438
struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno];
8438
8439
bool is_const = tnum_is_const(reg->var_off);
8439
8440
struct bpf_map *map = reg->map_ptr;
8440
8441
u64 val = reg->var_off.value;
8442
+ const char *struct_name = btf_field_type_name(field_type);
8443
+ int field_off = -1;
8441
8444
8442
8445
if (!is_const) {
8443
8446
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 );
8446
8449
return -EINVAL;
8447
8450
}
8448
8451
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 );
8451
8454
return -EINVAL;
8452
8455
}
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 );
8455
8458
return -EINVAL;
8456
8459
}
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);
8460
8466
return -EINVAL;
8461
8467
}
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 = ®s[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
+
8462
8487
if (meta->map_ptr) {
8463
8488
verifier_bug(env, "Two map pointers in a timer helper");
8464
8489
return -EFAULT;
0 commit comments