Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Consolidate spin_lock, timer management into btf_record

Now that kptr_off_tab has been refactored into btf_record, and can hold
more than one specific field type, accomodate bpf_spin_lock and
bpf_timer as well.

While they don't require any more metadata than offset, having all
special fields in one place allows us to share the same code for
allocated user defined types and handle both map values and these
allocated objects in a similar fashion.

As an optimization, we still keep spin_lock_off and timer_off offsets in
the btf_record structure, just to avoid having to find the btf_field
struct each time their offset is needed. This is mostly needed to
manipulate such objects in a map value at runtime. It's ok to hardcode
just one offset as more than one field is disallowed.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20221103191013.1236066-8-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Kumar Kartikeya Dwivedi and committed by
Alexei Starovoitov
db559117 af085f55

+316 -346
+32 -21
include/linux/bpf.h
··· 166 166 167 167 enum { 168 168 /* Support at most 8 pointers in a BTF type */ 169 - BTF_FIELDS_MAX = 8, 170 - BPF_MAP_OFF_ARR_MAX = BTF_FIELDS_MAX + 171 - 1 + /* for bpf_spin_lock */ 172 - 1, /* for bpf_timer */ 169 + BTF_FIELDS_MAX = 10, 170 + BPF_MAP_OFF_ARR_MAX = BTF_FIELDS_MAX, 173 171 }; 174 172 175 173 enum btf_field_type { 174 + BPF_SPIN_LOCK = (1 << 0), 175 + BPF_TIMER = (1 << 1), 176 176 BPF_KPTR_UNREF = (1 << 2), 177 177 BPF_KPTR_REF = (1 << 3), 178 178 BPF_KPTR = BPF_KPTR_UNREF | BPF_KPTR_REF, ··· 196 196 struct btf_record { 197 197 u32 cnt; 198 198 u32 field_mask; 199 + int spin_lock_off; 200 + int timer_off; 199 201 struct btf_field fields[]; 200 202 }; 201 203 ··· 222 220 u32 max_entries; 223 221 u64 map_extra; /* any per-map-type extra fields */ 224 222 u32 map_flags; 225 - int spin_lock_off; /* >=0 valid offset, <0 error */ 226 - struct btf_record *record; 227 - int timer_off; /* >=0 valid offset, <0 error */ 228 223 u32 id; 224 + struct btf_record *record; 229 225 int numa_node; 230 226 u32 btf_key_type_id; 231 227 u32 btf_value_type_id; ··· 257 257 bool frozen; /* write-once; write-protected by freeze_mutex */ 258 258 }; 259 259 260 + static inline const char *btf_field_type_name(enum btf_field_type type) 261 + { 262 + switch (type) { 263 + case BPF_SPIN_LOCK: 264 + return "bpf_spin_lock"; 265 + case BPF_TIMER: 266 + return "bpf_timer"; 267 + case BPF_KPTR_UNREF: 268 + case BPF_KPTR_REF: 269 + return "kptr"; 270 + default: 271 + WARN_ON_ONCE(1); 272 + return "unknown"; 273 + } 274 + } 275 + 260 276 static inline u32 btf_field_type_size(enum btf_field_type type) 261 277 { 262 278 switch (type) { 279 + case BPF_SPIN_LOCK: 280 + return sizeof(struct bpf_spin_lock); 281 + case BPF_TIMER: 282 + return sizeof(struct bpf_timer); 263 283 case BPF_KPTR_UNREF: 264 284 case BPF_KPTR_REF: 265 285 return sizeof(u64); ··· 292 272 static inline u32 btf_field_type_align(enum btf_field_type type) 293 273 { 294 274 switch (type) { 275 + case BPF_SPIN_LOCK: 276 + return __alignof__(struct bpf_spin_lock); 277 + case BPF_TIMER: 278 + return __alignof__(struct bpf_timer); 295 279 case BPF_KPTR_UNREF: 296 280 case BPF_KPTR_REF: 297 281 return __alignof__(u64); ··· 312 288 return rec->field_mask & type; 313 289 } 314 290 315 - static inline bool map_value_has_spin_lock(const struct bpf_map *map) 316 - { 317 - return map->spin_lock_off >= 0; 318 - } 319 - 320 - static inline bool map_value_has_timer(const struct bpf_map *map) 321 - { 322 - return map->timer_off >= 0; 323 - } 324 - 325 291 static inline void check_and_init_map_value(struct bpf_map *map, void *dst) 326 292 { 327 - if (unlikely(map_value_has_spin_lock(map))) 328 - memset(dst + map->spin_lock_off, 0, sizeof(struct bpf_spin_lock)); 329 - if (unlikely(map_value_has_timer(map))) 330 - memset(dst + map->timer_off, 0, sizeof(struct bpf_timer)); 331 293 if (!IS_ERR_OR_NULL(map->record)) { 332 294 struct btf_field *fields = map->record->fields; 333 295 u32 cnt = map->record->cnt; ··· 1750 1740 void bpf_map_free_record(struct bpf_map *map); 1751 1741 struct btf_record *btf_record_dup(const struct btf_record *rec); 1752 1742 bool btf_record_equal(const struct btf_record *rec_a, const struct btf_record *rec_b); 1743 + void bpf_obj_free_timer(const struct btf_record *rec, void *obj); 1753 1744 void bpf_obj_free_fields(const struct btf_record *rec, void *obj); 1754 1745 1755 1746 struct bpf_map *bpf_map_get(u32 ufd);
+2 -1
include/linux/btf.h
··· 163 163 u32 expected_offset, u32 expected_size); 164 164 int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t); 165 165 int btf_find_timer(const struct btf *btf, const struct btf_type *t); 166 - struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t); 166 + struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t, 167 + u32 field_mask, u32 value_size); 167 168 bool btf_type_is_void(const struct btf_type *t); 168 169 s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind); 169 170 const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
+6 -13
kernel/bpf/arraymap.c
··· 306 306 return 0; 307 307 } 308 308 309 - static void check_and_free_fields(struct bpf_array *arr, void *val) 310 - { 311 - if (map_value_has_timer(&arr->map)) 312 - bpf_timer_cancel_and_free(val + arr->map.timer_off); 313 - bpf_obj_free_fields(arr->map.record, val); 314 - } 315 - 316 309 /* Called from syscall or from eBPF program */ 317 310 static int array_map_update_elem(struct bpf_map *map, void *key, void *value, 318 311 u64 map_flags) ··· 327 334 return -EEXIST; 328 335 329 336 if (unlikely((map_flags & BPF_F_LOCK) && 330 - !map_value_has_spin_lock(map))) 337 + !btf_record_has_field(map->record, BPF_SPIN_LOCK))) 331 338 return -EINVAL; 332 339 333 340 if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { 334 341 val = this_cpu_ptr(array->pptrs[index & array->index_mask]); 335 342 copy_map_value(map, val, value); 336 - check_and_free_fields(array, val); 343 + bpf_obj_free_fields(array->map.record, val); 337 344 } else { 338 345 val = array->value + 339 346 (u64)array->elem_size * (index & array->index_mask); ··· 341 348 copy_map_value_locked(map, val, value, false); 342 349 else 343 350 copy_map_value(map, val, value); 344 - check_and_free_fields(array, val); 351 + bpf_obj_free_fields(array->map.record, val); 345 352 } 346 353 return 0; 347 354 } ··· 378 385 pptr = array->pptrs[index & array->index_mask]; 379 386 for_each_possible_cpu(cpu) { 380 387 copy_map_value_long(map, per_cpu_ptr(pptr, cpu), value + off); 381 - check_and_free_fields(array, per_cpu_ptr(pptr, cpu)); 388 + bpf_obj_free_fields(array->map.record, per_cpu_ptr(pptr, cpu)); 382 389 off += size; 383 390 } 384 391 rcu_read_unlock(); ··· 402 409 int i; 403 410 404 411 /* We don't reset or free fields other than timer on uref dropping to zero. */ 405 - if (!map_value_has_timer(map)) 412 + if (!btf_record_has_field(map->record, BPF_TIMER)) 406 413 return; 407 414 408 415 for (i = 0; i < array->map.max_entries; i++) 409 - bpf_timer_cancel_and_free(array_map_elem_ptr(array, i) + map->timer_off); 416 + bpf_obj_free_timer(map->record, array_map_elem_ptr(array, i)); 410 417 } 411 418 412 419 /* Called when map->refcnt goes to zero, either from workqueue or from syscall */
+1 -1
kernel/bpf/bpf_local_storage.c
··· 382 382 if (unlikely((map_flags & ~BPF_F_LOCK) > BPF_EXIST) || 383 383 /* BPF_F_LOCK can only be used in a value with spin_lock */ 384 384 unlikely((map_flags & BPF_F_LOCK) && 385 - !map_value_has_spin_lock(&smap->map))) 385 + !btf_record_has_field(smap->map.record, BPF_SPIN_LOCK))) 386 386 return ERR_PTR(-EINVAL); 387 387 388 388 if (gfp_flags == GFP_KERNEL && (map_flags & ~BPF_F_LOCK) != BPF_NOEXIST)
+179 -148
kernel/bpf/btf.c
··· 3205 3205 struct btf_field_info { 3206 3206 enum btf_field_type type; 3207 3207 u32 off; 3208 - u32 type_id; 3208 + struct { 3209 + u32 type_id; 3210 + } kptr; 3209 3211 }; 3210 3212 3211 3213 static int btf_find_struct(const struct btf *btf, const struct btf_type *t, 3212 - u32 off, int sz, struct btf_field_info *info) 3214 + u32 off, int sz, enum btf_field_type field_type, 3215 + struct btf_field_info *info) 3213 3216 { 3214 3217 if (!__btf_type_is_struct(t)) 3215 3218 return BTF_FIELD_IGNORE; 3216 3219 if (t->size != sz) 3217 3220 return BTF_FIELD_IGNORE; 3221 + info->type = field_type; 3218 3222 info->off = off; 3219 3223 return BTF_FIELD_FOUND; 3220 3224 } ··· 3255 3251 if (!__btf_type_is_struct(t)) 3256 3252 return -EINVAL; 3257 3253 3258 - info->type_id = res_id; 3259 - info->off = off; 3260 3254 info->type = type; 3255 + info->off = off; 3256 + info->kptr.type_id = res_id; 3261 3257 return BTF_FIELD_FOUND; 3262 3258 } 3263 3259 3264 - static int btf_find_struct_field(const struct btf *btf, const struct btf_type *t, 3265 - const char *name, int sz, int align, 3266 - enum btf_field_info_type field_type, 3260 + static int btf_get_field_type(const char *name, u32 field_mask, u32 *seen_mask, 3261 + int *align, int *sz) 3262 + { 3263 + int type = 0; 3264 + 3265 + if (field_mask & BPF_SPIN_LOCK) { 3266 + if (!strcmp(name, "bpf_spin_lock")) { 3267 + if (*seen_mask & BPF_SPIN_LOCK) 3268 + return -E2BIG; 3269 + *seen_mask |= BPF_SPIN_LOCK; 3270 + type = BPF_SPIN_LOCK; 3271 + goto end; 3272 + } 3273 + } 3274 + if (field_mask & BPF_TIMER) { 3275 + if (!strcmp(name, "bpf_timer")) { 3276 + if (*seen_mask & BPF_TIMER) 3277 + return -E2BIG; 3278 + *seen_mask |= BPF_TIMER; 3279 + type = BPF_TIMER; 3280 + goto end; 3281 + } 3282 + } 3283 + /* Only return BPF_KPTR when all other types with matchable names fail */ 3284 + if (field_mask & BPF_KPTR) { 3285 + type = BPF_KPTR_REF; 3286 + goto end; 3287 + } 3288 + return 0; 3289 + end: 3290 + *sz = btf_field_type_size(type); 3291 + *align = btf_field_type_align(type); 3292 + return type; 3293 + } 3294 + 3295 + static int btf_find_struct_field(const struct btf *btf, 3296 + const struct btf_type *t, u32 field_mask, 3267 3297 struct btf_field_info *info, int info_cnt) 3268 3298 { 3299 + int ret, idx = 0, align, sz, field_type; 3269 3300 const struct btf_member *member; 3270 3301 struct btf_field_info tmp; 3271 - int ret, idx = 0; 3272 - u32 i, off; 3302 + u32 i, off, seen_mask = 0; 3273 3303 3274 3304 for_each_member(i, t, member) { 3275 3305 const struct btf_type *member_type = btf_type_by_id(btf, 3276 3306 member->type); 3277 3307 3278 - if (name && strcmp(__btf_name_by_offset(btf, member_type->name_off), name)) 3308 + field_type = btf_get_field_type(__btf_name_by_offset(btf, member_type->name_off), 3309 + field_mask, &seen_mask, &align, &sz); 3310 + if (field_type == 0) 3279 3311 continue; 3312 + if (field_type < 0) 3313 + return field_type; 3280 3314 3281 3315 off = __btf_member_bit_offset(t, member); 3282 3316 if (off % 8) ··· 3322 3280 return -EINVAL; 3323 3281 off /= 8; 3324 3282 if (off % align) 3325 - return -EINVAL; 3283 + continue; 3326 3284 3327 3285 switch (field_type) { 3328 - case BTF_FIELD_SPIN_LOCK: 3329 - case BTF_FIELD_TIMER: 3330 - ret = btf_find_struct(btf, member_type, off, sz, 3286 + case BPF_SPIN_LOCK: 3287 + case BPF_TIMER: 3288 + ret = btf_find_struct(btf, member_type, off, sz, field_type, 3331 3289 idx < info_cnt ? &info[idx] : &tmp); 3332 3290 if (ret < 0) 3333 3291 return ret; 3334 3292 break; 3335 - case BTF_FIELD_KPTR: 3293 + case BPF_KPTR_UNREF: 3294 + case BPF_KPTR_REF: 3336 3295 ret = btf_find_kptr(btf, member_type, off, sz, 3337 3296 idx < info_cnt ? &info[idx] : &tmp); 3338 3297 if (ret < 0) ··· 3353 3310 } 3354 3311 3355 3312 static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t, 3356 - const char *name, int sz, int align, 3357 - enum btf_field_info_type field_type, 3358 - struct btf_field_info *info, int info_cnt) 3313 + u32 field_mask, struct btf_field_info *info, 3314 + int info_cnt) 3359 3315 { 3316 + int ret, idx = 0, align, sz, field_type; 3360 3317 const struct btf_var_secinfo *vsi; 3361 3318 struct btf_field_info tmp; 3362 - int ret, idx = 0; 3363 - u32 i, off; 3319 + u32 i, off, seen_mask = 0; 3364 3320 3365 3321 for_each_vsi(i, t, vsi) { 3366 3322 const struct btf_type *var = btf_type_by_id(btf, vsi->type); 3367 3323 const struct btf_type *var_type = btf_type_by_id(btf, var->type); 3368 3324 3369 - off = vsi->offset; 3370 - 3371 - if (name && strcmp(__btf_name_by_offset(btf, var_type->name_off), name)) 3325 + field_type = btf_get_field_type(__btf_name_by_offset(btf, var_type->name_off), 3326 + field_mask, &seen_mask, &align, &sz); 3327 + if (field_type == 0) 3372 3328 continue; 3329 + if (field_type < 0) 3330 + return field_type; 3331 + 3332 + off = vsi->offset; 3373 3333 if (vsi->size != sz) 3374 3334 continue; 3375 3335 if (off % align) 3376 - return -EINVAL; 3336 + continue; 3377 3337 3378 3338 switch (field_type) { 3379 - case BTF_FIELD_SPIN_LOCK: 3380 - case BTF_FIELD_TIMER: 3381 - ret = btf_find_struct(btf, var_type, off, sz, 3339 + case BPF_SPIN_LOCK: 3340 + case BPF_TIMER: 3341 + ret = btf_find_struct(btf, var_type, off, sz, field_type, 3382 3342 idx < info_cnt ? &info[idx] : &tmp); 3383 3343 if (ret < 0) 3384 3344 return ret; 3385 3345 break; 3386 - case BTF_FIELD_KPTR: 3346 + case BPF_KPTR_UNREF: 3347 + case BPF_KPTR_REF: 3387 3348 ret = btf_find_kptr(btf, var_type, off, sz, 3388 3349 idx < info_cnt ? &info[idx] : &tmp); 3389 3350 if (ret < 0) ··· 3407 3360 } 3408 3361 3409 3362 static int btf_find_field(const struct btf *btf, const struct btf_type *t, 3410 - enum btf_field_info_type field_type, 3411 - struct btf_field_info *info, int info_cnt) 3363 + u32 field_mask, struct btf_field_info *info, 3364 + int info_cnt) 3412 3365 { 3413 - const char *name; 3414 - int sz, align; 3415 - 3416 - switch (field_type) { 3417 - case BTF_FIELD_SPIN_LOCK: 3418 - name = "bpf_spin_lock"; 3419 - sz = sizeof(struct bpf_spin_lock); 3420 - align = __alignof__(struct bpf_spin_lock); 3421 - break; 3422 - case BTF_FIELD_TIMER: 3423 - name = "bpf_timer"; 3424 - sz = sizeof(struct bpf_timer); 3425 - align = __alignof__(struct bpf_timer); 3426 - break; 3427 - case BTF_FIELD_KPTR: 3428 - name = NULL; 3429 - sz = sizeof(u64); 3430 - align = 8; 3431 - break; 3432 - default: 3433 - return -EFAULT; 3434 - } 3435 - 3436 3366 if (__btf_type_is_struct(t)) 3437 - return btf_find_struct_field(btf, t, name, sz, align, field_type, info, info_cnt); 3367 + return btf_find_struct_field(btf, t, field_mask, info, info_cnt); 3438 3368 else if (btf_type_is_datasec(t)) 3439 - return btf_find_datasec_var(btf, t, name, sz, align, field_type, info, info_cnt); 3369 + return btf_find_datasec_var(btf, t, field_mask, info, info_cnt); 3440 3370 return -EINVAL; 3441 3371 } 3442 3372 3443 - /* find 'struct bpf_spin_lock' in map value. 3444 - * return >= 0 offset if found 3445 - * and < 0 in case of error 3446 - */ 3447 - int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t) 3373 + static int btf_parse_kptr(const struct btf *btf, struct btf_field *field, 3374 + struct btf_field_info *info) 3448 3375 { 3449 - struct btf_field_info info; 3376 + struct module *mod = NULL; 3377 + const struct btf_type *t; 3378 + struct btf *kernel_btf; 3450 3379 int ret; 3380 + s32 id; 3451 3381 3452 - ret = btf_find_field(btf, t, BTF_FIELD_SPIN_LOCK, &info, 1); 3453 - if (ret < 0) 3454 - return ret; 3455 - if (!ret) 3456 - return -ENOENT; 3457 - return info.off; 3382 + /* Find type in map BTF, and use it to look up the matching type 3383 + * in vmlinux or module BTFs, by name and kind. 3384 + */ 3385 + t = btf_type_by_id(btf, info->kptr.type_id); 3386 + id = bpf_find_btf_id(__btf_name_by_offset(btf, t->name_off), BTF_INFO_KIND(t->info), 3387 + &kernel_btf); 3388 + if (id < 0) 3389 + return id; 3390 + 3391 + /* Find and stash the function pointer for the destruction function that 3392 + * needs to be eventually invoked from the map free path. 3393 + */ 3394 + if (info->type == BPF_KPTR_REF) { 3395 + const struct btf_type *dtor_func; 3396 + const char *dtor_func_name; 3397 + unsigned long addr; 3398 + s32 dtor_btf_id; 3399 + 3400 + /* This call also serves as a whitelist of allowed objects that 3401 + * can be used as a referenced pointer and be stored in a map at 3402 + * the same time. 3403 + */ 3404 + dtor_btf_id = btf_find_dtor_kfunc(kernel_btf, id); 3405 + if (dtor_btf_id < 0) { 3406 + ret = dtor_btf_id; 3407 + goto end_btf; 3408 + } 3409 + 3410 + dtor_func = btf_type_by_id(kernel_btf, dtor_btf_id); 3411 + if (!dtor_func) { 3412 + ret = -ENOENT; 3413 + goto end_btf; 3414 + } 3415 + 3416 + if (btf_is_module(kernel_btf)) { 3417 + mod = btf_try_get_module(kernel_btf); 3418 + if (!mod) { 3419 + ret = -ENXIO; 3420 + goto end_btf; 3421 + } 3422 + } 3423 + 3424 + /* We already verified dtor_func to be btf_type_is_func 3425 + * in register_btf_id_dtor_kfuncs. 3426 + */ 3427 + dtor_func_name = __btf_name_by_offset(kernel_btf, dtor_func->name_off); 3428 + addr = kallsyms_lookup_name(dtor_func_name); 3429 + if (!addr) { 3430 + ret = -EINVAL; 3431 + goto end_mod; 3432 + } 3433 + field->kptr.dtor = (void *)addr; 3434 + } 3435 + 3436 + field->kptr.btf_id = id; 3437 + field->kptr.btf = kernel_btf; 3438 + field->kptr.module = mod; 3439 + return 0; 3440 + end_mod: 3441 + module_put(mod); 3442 + end_btf: 3443 + btf_put(kernel_btf); 3444 + return ret; 3458 3445 } 3459 3446 3460 - int btf_find_timer(const struct btf *btf, const struct btf_type *t) 3461 - { 3462 - struct btf_field_info info; 3463 - int ret; 3464 - 3465 - ret = btf_find_field(btf, t, BTF_FIELD_TIMER, &info, 1); 3466 - if (ret < 0) 3467 - return ret; 3468 - if (!ret) 3469 - return -ENOENT; 3470 - return info.off; 3471 - } 3472 - 3473 - struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t) 3447 + struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t, 3448 + u32 field_mask, u32 value_size) 3474 3449 { 3475 3450 struct btf_field_info info_arr[BTF_FIELDS_MAX]; 3476 - struct btf *kernel_btf = NULL; 3477 - struct module *mod = NULL; 3478 3451 struct btf_record *rec; 3479 3452 int ret, i, cnt; 3480 3453 3481 - ret = btf_find_field(btf, t, BTF_FIELD_KPTR, info_arr, ARRAY_SIZE(info_arr)); 3454 + ret = btf_find_field(btf, t, field_mask, info_arr, ARRAY_SIZE(info_arr)); 3482 3455 if (ret < 0) 3483 3456 return ERR_PTR(ret); 3484 3457 if (!ret) ··· 3508 3441 rec = kzalloc(offsetof(struct btf_record, fields[cnt]), GFP_KERNEL | __GFP_NOWARN); 3509 3442 if (!rec) 3510 3443 return ERR_PTR(-ENOMEM); 3511 - rec->cnt = 0; 3444 + 3445 + rec->spin_lock_off = -EINVAL; 3446 + rec->timer_off = -EINVAL; 3512 3447 for (i = 0; i < cnt; i++) { 3513 - const struct btf_type *t; 3514 - s32 id; 3515 - 3516 - /* Find type in map BTF, and use it to look up the matching type 3517 - * in vmlinux or module BTFs, by name and kind. 3518 - */ 3519 - t = btf_type_by_id(btf, info_arr[i].type_id); 3520 - id = bpf_find_btf_id(__btf_name_by_offset(btf, t->name_off), BTF_INFO_KIND(t->info), 3521 - &kernel_btf); 3522 - if (id < 0) { 3523 - ret = id; 3448 + if (info_arr[i].off + btf_field_type_size(info_arr[i].type) > value_size) { 3449 + WARN_ONCE(1, "verifier bug off %d size %d", info_arr[i].off, value_size); 3450 + ret = -EFAULT; 3524 3451 goto end; 3525 - } 3526 - 3527 - /* Find and stash the function pointer for the destruction function that 3528 - * needs to be eventually invoked from the map free path. 3529 - */ 3530 - if (info_arr[i].type == BPF_KPTR_REF) { 3531 - const struct btf_type *dtor_func; 3532 - const char *dtor_func_name; 3533 - unsigned long addr; 3534 - s32 dtor_btf_id; 3535 - 3536 - /* This call also serves as a whitelist of allowed objects that 3537 - * can be used as a referenced pointer and be stored in a map at 3538 - * the same time. 3539 - */ 3540 - dtor_btf_id = btf_find_dtor_kfunc(kernel_btf, id); 3541 - if (dtor_btf_id < 0) { 3542 - ret = dtor_btf_id; 3543 - goto end_btf; 3544 - } 3545 - 3546 - dtor_func = btf_type_by_id(kernel_btf, dtor_btf_id); 3547 - if (!dtor_func) { 3548 - ret = -ENOENT; 3549 - goto end_btf; 3550 - } 3551 - 3552 - if (btf_is_module(kernel_btf)) { 3553 - mod = btf_try_get_module(kernel_btf); 3554 - if (!mod) { 3555 - ret = -ENXIO; 3556 - goto end_btf; 3557 - } 3558 - } 3559 - 3560 - /* We already verified dtor_func to be btf_type_is_func 3561 - * in register_btf_id_dtor_kfuncs. 3562 - */ 3563 - dtor_func_name = __btf_name_by_offset(kernel_btf, dtor_func->name_off); 3564 - addr = kallsyms_lookup_name(dtor_func_name); 3565 - if (!addr) { 3566 - ret = -EINVAL; 3567 - goto end_mod; 3568 - } 3569 - rec->fields[i].kptr.dtor = (void *)addr; 3570 3452 } 3571 3453 3572 3454 rec->field_mask |= info_arr[i].type; 3573 3455 rec->fields[i].offset = info_arr[i].off; 3574 3456 rec->fields[i].type = info_arr[i].type; 3575 - rec->fields[i].kptr.btf_id = id; 3576 - rec->fields[i].kptr.btf = kernel_btf; 3577 - rec->fields[i].kptr.module = mod; 3457 + 3458 + switch (info_arr[i].type) { 3459 + case BPF_SPIN_LOCK: 3460 + WARN_ON_ONCE(rec->spin_lock_off >= 0); 3461 + /* Cache offset for faster lookup at runtime */ 3462 + rec->spin_lock_off = rec->fields[i].offset; 3463 + break; 3464 + case BPF_TIMER: 3465 + WARN_ON_ONCE(rec->timer_off >= 0); 3466 + /* Cache offset for faster lookup at runtime */ 3467 + rec->timer_off = rec->fields[i].offset; 3468 + break; 3469 + case BPF_KPTR_UNREF: 3470 + case BPF_KPTR_REF: 3471 + ret = btf_parse_kptr(btf, &rec->fields[i], &info_arr[i]); 3472 + if (ret < 0) 3473 + goto end; 3474 + break; 3475 + default: 3476 + ret = -EFAULT; 3477 + goto end; 3478 + } 3578 3479 rec->cnt++; 3579 3480 } 3580 3481 return rec; 3581 - end_mod: 3582 - module_put(mod); 3583 - end_btf: 3584 - btf_put(kernel_btf); 3585 3482 end: 3586 3483 btf_record_free(rec); 3587 3484 return ERR_PTR(ret);
+8 -16
kernel/bpf/hashtab.c
··· 222 222 u32 num_entries = htab->map.max_entries; 223 223 int i; 224 224 225 - if (!map_value_has_timer(&htab->map)) 225 + if (!btf_record_has_field(htab->map.record, BPF_TIMER)) 226 226 return; 227 227 if (htab_has_extra_elems(htab)) 228 228 num_entries += num_possible_cpus(); ··· 231 231 struct htab_elem *elem; 232 232 233 233 elem = get_htab_elem(htab, i); 234 - bpf_timer_cancel_and_free(elem->key + 235 - round_up(htab->map.key_size, 8) + 236 - htab->map.timer_off); 234 + bpf_obj_free_timer(htab->map.record, elem->key + round_up(htab->map.key_size, 8)); 237 235 cond_resched(); 238 236 } 239 237 } ··· 761 763 { 762 764 void *map_value = elem->key + round_up(htab->map.key_size, 8); 763 765 764 - if (map_value_has_timer(&htab->map)) 765 - bpf_timer_cancel_and_free(map_value + htab->map.timer_off); 766 766 bpf_obj_free_fields(htab->map.record, map_value); 767 767 } 768 768 ··· 1085 1089 head = &b->head; 1086 1090 1087 1091 if (unlikely(map_flags & BPF_F_LOCK)) { 1088 - if (unlikely(!map_value_has_spin_lock(map))) 1092 + if (unlikely(!btf_record_has_field(map->record, BPF_SPIN_LOCK))) 1089 1093 return -EINVAL; 1090 1094 /* find an element without taking the bucket lock */ 1091 1095 l_old = lookup_nulls_elem_raw(head, hash, key, key_size, ··· 1468 1472 struct htab_elem *l; 1469 1473 1470 1474 hlist_nulls_for_each_entry(l, n, head, hash_node) { 1471 - /* We don't reset or free kptr on uref dropping to zero, 1472 - * hence just free timer. 1473 - */ 1474 - bpf_timer_cancel_and_free(l->key + 1475 - round_up(htab->map.key_size, 8) + 1476 - htab->map.timer_off); 1475 + /* We only free timer on uref dropping to zero */ 1476 + bpf_obj_free_timer(htab->map.record, l->key + round_up(htab->map.key_size, 8)); 1477 1477 } 1478 1478 cond_resched_rcu(); 1479 1479 } ··· 1480 1488 { 1481 1489 struct bpf_htab *htab = container_of(map, struct bpf_htab, map); 1482 1490 1483 - /* We don't reset or free kptr on uref dropping to zero. */ 1484 - if (!map_value_has_timer(&htab->map)) 1491 + /* We only free timer on uref dropping to zero */ 1492 + if (!btf_record_has_field(htab->map.record, BPF_TIMER)) 1485 1493 return; 1486 1494 if (!htab_is_prealloc(htab)) 1487 1495 htab_free_malloced_timers(htab); ··· 1665 1673 1666 1674 elem_map_flags = attr->batch.elem_flags; 1667 1675 if ((elem_map_flags & ~BPF_F_LOCK) || 1668 - ((elem_map_flags & BPF_F_LOCK) && !map_value_has_spin_lock(map))) 1676 + ((elem_map_flags & BPF_F_LOCK) && !btf_record_has_field(map->record, BPF_SPIN_LOCK))) 1669 1677 return -EINVAL; 1670 1678 1671 1679 map_flags = attr->batch.flags;
+3 -3
kernel/bpf/helpers.c
··· 366 366 struct bpf_spin_lock *lock; 367 367 368 368 if (lock_src) 369 - lock = src + map->spin_lock_off; 369 + lock = src + map->record->spin_lock_off; 370 370 else 371 - lock = dst + map->spin_lock_off; 371 + lock = dst + map->record->spin_lock_off; 372 372 preempt_disable(); 373 373 __bpf_spin_lock_irqsave(lock); 374 374 copy_map_value(map, dst, src); ··· 1169 1169 ret = -ENOMEM; 1170 1170 goto out; 1171 1171 } 1172 - t->value = (void *)timer - map->timer_off; 1172 + t->value = (void *)timer - map->record->timer_off; 1173 1173 t->map = map; 1174 1174 t->prog = NULL; 1175 1175 rcu_assign_pointer(t->callback_fn, NULL);
+1 -1
kernel/bpf/local_storage.c
··· 151 151 return -EINVAL; 152 152 153 153 if (unlikely((flags & BPF_F_LOCK) && 154 - !map_value_has_spin_lock(map))) 154 + !btf_record_has_field(map->record, BPF_SPIN_LOCK))) 155 155 return -EINVAL; 156 156 157 157 storage = cgroup_storage_lookup((struct bpf_cgroup_storage_map *)map,
+1 -4
kernel/bpf/map_in_map.c
··· 29 29 return ERR_PTR(-ENOTSUPP); 30 30 } 31 31 32 - if (map_value_has_spin_lock(inner_map)) { 32 + if (btf_record_has_field(inner_map->record, BPF_SPIN_LOCK)) { 33 33 fdput(f); 34 34 return ERR_PTR(-ENOTSUPP); 35 35 } ··· 50 50 inner_map_meta->value_size = inner_map->value_size; 51 51 inner_map_meta->map_flags = inner_map->map_flags; 52 52 inner_map_meta->max_entries = inner_map->max_entries; 53 - inner_map_meta->spin_lock_off = inner_map->spin_lock_off; 54 - inner_map_meta->timer_off = inner_map->timer_off; 55 53 inner_map_meta->record = btf_record_dup(inner_map->record); 56 54 if (IS_ERR(inner_map_meta->record)) { 57 55 /* btf_record_dup returns NULL or valid pointer in case of ··· 90 92 return meta0->map_type == meta1->map_type && 91 93 meta0->key_size == meta1->key_size && 92 94 meta0->value_size == meta1->value_size && 93 - meta0->timer_off == meta1->timer_off && 94 95 meta0->map_flags == meta1->map_flags && 95 96 btf_record_equal(meta0->record, meta1->record); 96 97 }
+60 -75
kernel/bpf/syscall.c
··· 527 527 return; 528 528 for (i = 0; i < rec->cnt; i++) { 529 529 switch (rec->fields[i].type) { 530 + case BPF_SPIN_LOCK: 531 + case BPF_TIMER: 532 + break; 530 533 case BPF_KPTR_UNREF: 531 534 case BPF_KPTR_REF: 532 535 if (rec->fields[i].kptr.module) ··· 567 564 new_rec->cnt = 0; 568 565 for (i = 0; i < rec->cnt; i++) { 569 566 switch (fields[i].type) { 567 + case BPF_SPIN_LOCK: 568 + case BPF_TIMER: 569 + break; 570 570 case BPF_KPTR_UNREF: 571 571 case BPF_KPTR_REF: 572 572 btf_get(fields[i].kptr.btf); ··· 606 600 return !memcmp(rec_a, rec_b, size); 607 601 } 608 602 603 + void bpf_obj_free_timer(const struct btf_record *rec, void *obj) 604 + { 605 + if (WARN_ON_ONCE(!btf_record_has_field(rec, BPF_TIMER))) 606 + return; 607 + bpf_timer_cancel_and_free(obj + rec->timer_off); 608 + } 609 + 609 610 void bpf_obj_free_fields(const struct btf_record *rec, void *obj) 610 611 { 611 612 const struct btf_field *fields; ··· 626 613 void *field_ptr = obj + field->offset; 627 614 628 615 switch (fields[i].type) { 616 + case BPF_SPIN_LOCK: 617 + break; 618 + case BPF_TIMER: 619 + bpf_timer_cancel_and_free(field_ptr); 620 + break; 629 621 case BPF_KPTR_UNREF: 630 622 WRITE_ONCE(*(u64 *)field_ptr, 0); 631 623 break; ··· 816 798 struct bpf_map *map = filp->private_data; 817 799 int err; 818 800 819 - if (!map->ops->map_mmap || map_value_has_spin_lock(map) || 820 - map_value_has_timer(map) || !IS_ERR_OR_NULL(map->record)) 801 + if (!map->ops->map_mmap || !IS_ERR_OR_NULL(map->record)) 821 802 return -ENOTSUPP; 822 803 823 804 if (!(vma->vm_flags & VM_SHARED)) ··· 971 954 972 955 static int bpf_map_alloc_off_arr(struct bpf_map *map) 973 956 { 974 - bool has_spin_lock = map_value_has_spin_lock(map); 975 - bool has_timer = map_value_has_timer(map); 976 957 bool has_fields = !IS_ERR_OR_NULL(map->record); 977 958 struct btf_field_offs *fo; 978 - u32 i; 959 + struct btf_record *rec; 960 + u32 i, *off; 961 + u8 *sz; 979 962 980 - if (!has_spin_lock && !has_timer && !has_fields) { 963 + if (!has_fields) { 981 964 map->field_offs = NULL; 982 965 return 0; 983 966 } 984 967 985 - fo = kmalloc(sizeof(*map->field_offs), GFP_KERNEL | __GFP_NOWARN); 968 + fo = kzalloc(sizeof(*map->field_offs), GFP_KERNEL | __GFP_NOWARN); 986 969 if (!fo) 987 970 return -ENOMEM; 988 971 map->field_offs = fo; 989 972 990 - fo->cnt = 0; 991 - if (has_spin_lock) { 992 - i = fo->cnt; 993 - 994 - fo->field_off[i] = map->spin_lock_off; 995 - fo->field_sz[i] = sizeof(struct bpf_spin_lock); 996 - fo->cnt++; 973 + rec = map->record; 974 + off = fo->field_off; 975 + sz = fo->field_sz; 976 + for (i = 0; i < rec->cnt; i++) { 977 + *off++ = rec->fields[i].offset; 978 + *sz++ = btf_field_type_size(rec->fields[i].type); 997 979 } 998 - if (has_timer) { 999 - i = fo->cnt; 1000 - 1001 - fo->field_off[i] = map->timer_off; 1002 - fo->field_sz[i] = sizeof(struct bpf_timer); 1003 - fo->cnt++; 1004 - } 1005 - if (has_fields) { 1006 - struct btf_record *rec = map->record; 1007 - u32 *off = &fo->field_off[fo->cnt]; 1008 - u8 *sz = &fo->field_sz[fo->cnt]; 1009 - 1010 - for (i = 0; i < rec->cnt; i++) { 1011 - *off++ = rec->fields[i].offset; 1012 - *sz++ = btf_field_type_size(rec->fields[i].type); 1013 - } 1014 - fo->cnt += rec->cnt; 1015 - } 980 + fo->cnt = rec->cnt; 1016 981 1017 982 if (fo->cnt == 1) 1018 983 return 0; ··· 1025 1026 if (!value_type || value_size != map->value_size) 1026 1027 return -EINVAL; 1027 1028 1028 - map->spin_lock_off = btf_find_spin_lock(btf, value_type); 1029 - 1030 - if (map_value_has_spin_lock(map)) { 1031 - if (map->map_flags & BPF_F_RDONLY_PROG) 1032 - return -EACCES; 1033 - if (map->map_type != BPF_MAP_TYPE_HASH && 1034 - map->map_type != BPF_MAP_TYPE_ARRAY && 1035 - map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE && 1036 - map->map_type != BPF_MAP_TYPE_SK_STORAGE && 1037 - map->map_type != BPF_MAP_TYPE_INODE_STORAGE && 1038 - map->map_type != BPF_MAP_TYPE_TASK_STORAGE && 1039 - map->map_type != BPF_MAP_TYPE_CGRP_STORAGE) 1040 - return -ENOTSUPP; 1041 - if (map->spin_lock_off + sizeof(struct bpf_spin_lock) > 1042 - map->value_size) { 1043 - WARN_ONCE(1, 1044 - "verifier bug spin_lock_off %d value_size %d\n", 1045 - map->spin_lock_off, map->value_size); 1046 - return -EFAULT; 1047 - } 1048 - } 1049 - 1050 - map->timer_off = btf_find_timer(btf, value_type); 1051 - if (map_value_has_timer(map)) { 1052 - if (map->map_flags & BPF_F_RDONLY_PROG) 1053 - return -EACCES; 1054 - if (map->map_type != BPF_MAP_TYPE_HASH && 1055 - map->map_type != BPF_MAP_TYPE_LRU_HASH && 1056 - map->map_type != BPF_MAP_TYPE_ARRAY) 1057 - return -EOPNOTSUPP; 1058 - } 1059 - 1060 - map->record = btf_parse_fields(btf, value_type); 1029 + map->record = btf_parse_fields(btf, value_type, BPF_SPIN_LOCK | BPF_TIMER | BPF_KPTR, 1030 + map->value_size); 1061 1031 if (!IS_ERR_OR_NULL(map->record)) { 1062 1032 int i; 1063 1033 ··· 1042 1074 switch (map->record->field_mask & (1 << i)) { 1043 1075 case 0: 1044 1076 continue; 1077 + case BPF_SPIN_LOCK: 1078 + if (map->map_type != BPF_MAP_TYPE_HASH && 1079 + map->map_type != BPF_MAP_TYPE_ARRAY && 1080 + map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE && 1081 + map->map_type != BPF_MAP_TYPE_SK_STORAGE && 1082 + map->map_type != BPF_MAP_TYPE_INODE_STORAGE && 1083 + map->map_type != BPF_MAP_TYPE_TASK_STORAGE && 1084 + map->map_type != BPF_MAP_TYPE_CGRP_STORAGE) { 1085 + ret = -EOPNOTSUPP; 1086 + goto free_map_tab; 1087 + } 1088 + break; 1089 + case BPF_TIMER: 1090 + if (map->map_type != BPF_MAP_TYPE_HASH && 1091 + map->map_type != BPF_MAP_TYPE_LRU_HASH && 1092 + map->map_type != BPF_MAP_TYPE_ARRAY) { 1093 + return -EOPNOTSUPP; 1094 + goto free_map_tab; 1095 + } 1096 + break; 1045 1097 case BPF_KPTR_UNREF: 1046 1098 case BPF_KPTR_REF: 1047 1099 if (map->map_type != BPF_MAP_TYPE_HASH && ··· 1141 1153 mutex_init(&map->freeze_mutex); 1142 1154 spin_lock_init(&map->owner.lock); 1143 1155 1144 - map->spin_lock_off = -EINVAL; 1145 - map->timer_off = -EINVAL; 1146 1156 if (attr->btf_key_type_id || attr->btf_value_type_id || 1147 1157 /* Even the map's value is a kernel's struct, 1148 1158 * the bpf_prog.o must have BTF to begin with ··· 1354 1368 } 1355 1369 1356 1370 if ((attr->flags & BPF_F_LOCK) && 1357 - !map_value_has_spin_lock(map)) { 1371 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 1358 1372 err = -EINVAL; 1359 1373 goto err_put; 1360 1374 } ··· 1427 1441 } 1428 1442 1429 1443 if ((attr->flags & BPF_F_LOCK) && 1430 - !map_value_has_spin_lock(map)) { 1444 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 1431 1445 err = -EINVAL; 1432 1446 goto err_put; 1433 1447 } ··· 1590 1604 return -EINVAL; 1591 1605 1592 1606 if ((attr->batch.elem_flags & BPF_F_LOCK) && 1593 - !map_value_has_spin_lock(map)) { 1607 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 1594 1608 return -EINVAL; 1595 1609 } 1596 1610 ··· 1647 1661 return -EINVAL; 1648 1662 1649 1663 if ((attr->batch.elem_flags & BPF_F_LOCK) && 1650 - !map_value_has_spin_lock(map)) { 1664 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 1651 1665 return -EINVAL; 1652 1666 } 1653 1667 ··· 1710 1724 return -EINVAL; 1711 1725 1712 1726 if ((attr->batch.elem_flags & BPF_F_LOCK) && 1713 - !map_value_has_spin_lock(map)) 1727 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) 1714 1728 return -EINVAL; 1715 1729 1716 1730 value_size = bpf_map_value_size(map); ··· 1832 1846 } 1833 1847 1834 1848 if ((attr->flags & BPF_F_LOCK) && 1835 - !map_value_has_spin_lock(map)) { 1849 + !btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 1836 1850 err = -EINVAL; 1837 1851 goto err_put; 1838 1852 } ··· 1903 1917 if (IS_ERR(map)) 1904 1918 return PTR_ERR(map); 1905 1919 1906 - if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS || 1907 - map_value_has_timer(map) || !IS_ERR_OR_NULL(map->record)) { 1920 + if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS || !IS_ERR_OR_NULL(map->record)) { 1908 1921 fdput(f); 1909 1922 return -ENOTSUPP; 1910 1923 }
+21 -61
kernel/bpf/verifier.c
··· 454 454 static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) 455 455 { 456 456 return reg->type == PTR_TO_MAP_VALUE && 457 - map_value_has_spin_lock(reg->map_ptr); 457 + btf_record_has_field(reg->map_ptr->record, BPF_SPIN_LOCK); 458 458 } 459 459 460 460 static bool type_is_rdonly_mem(u32 type) ··· 1388 1388 /* transfer reg's id which is unique for every map_lookup_elem 1389 1389 * as UID of the inner map. 1390 1390 */ 1391 - if (map_value_has_timer(map->inner_map_meta)) 1391 + if (btf_record_has_field(map->inner_map_meta->record, BPF_TIMER)) 1392 1392 reg->map_uid = reg->id; 1393 1393 } else if (map->map_type == BPF_MAP_TYPE_XSKMAP) { 1394 1394 reg->type = PTR_TO_XDP_SOCK; ··· 3817 3817 if (err) 3818 3818 return err; 3819 3819 3820 - if (map_value_has_spin_lock(map)) { 3821 - u32 lock = map->spin_lock_off; 3822 - 3823 - /* if any part of struct bpf_spin_lock can be touched by 3824 - * load/store reject this program. 3825 - * To check that [x1, x2) overlaps with [y1, y2) 3826 - * it is sufficient to check x1 < y2 && y1 < x2. 3827 - */ 3828 - if (reg->smin_value + off < lock + sizeof(struct bpf_spin_lock) && 3829 - lock < reg->umax_value + off + size) { 3830 - verbose(env, "bpf_spin_lock cannot be accessed directly by load/store\n"); 3831 - return -EACCES; 3832 - } 3833 - } 3834 - if (map_value_has_timer(map)) { 3835 - u32 t = map->timer_off; 3836 - 3837 - if (reg->smin_value + off < t + sizeof(struct bpf_timer) && 3838 - t < reg->umax_value + off + size) { 3839 - verbose(env, "bpf_timer cannot be accessed directly by load/store\n"); 3840 - return -EACCES; 3841 - } 3842 - } 3843 3820 if (IS_ERR_OR_NULL(map->record)) 3844 3821 return 0; 3845 3822 rec = map->record; ··· 3824 3847 struct btf_field *field = &rec->fields[i]; 3825 3848 u32 p = field->offset; 3826 3849 3850 + /* If any part of a field can be touched by load/store, reject 3851 + * this program. To check that [x1, x2) overlaps with [y1, y2), 3852 + * it is sufficient to check x1 < y2 && y1 < x2. 3853 + */ 3827 3854 if (reg->smin_value + off < p + btf_field_type_size(field->type) && 3828 3855 p < reg->umax_value + off + size) { 3829 3856 switch (field->type) { ··· 3852 3871 } 3853 3872 break; 3854 3873 default: 3855 - verbose(env, "field cannot be accessed directly by load/store\n"); 3874 + verbose(env, "%s cannot be accessed directly by load/store\n", 3875 + btf_field_type_name(field->type)); 3856 3876 return -EACCES; 3857 3877 } 3858 3878 } ··· 5422 5440 map->name); 5423 5441 return -EINVAL; 5424 5442 } 5425 - if (!map_value_has_spin_lock(map)) { 5426 - if (map->spin_lock_off == -E2BIG) 5427 - verbose(env, 5428 - "map '%s' has more than one 'struct bpf_spin_lock'\n", 5429 - map->name); 5430 - else if (map->spin_lock_off == -ENOENT) 5431 - verbose(env, 5432 - "map '%s' doesn't have 'struct bpf_spin_lock'\n", 5433 - map->name); 5434 - else 5435 - verbose(env, 5436 - "map '%s' is not a struct type or bpf_spin_lock is mangled\n", 5437 - map->name); 5443 + if (!btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 5444 + verbose(env, "map '%s' has no valid bpf_spin_lock\n", map->name); 5438 5445 return -EINVAL; 5439 5446 } 5440 - if (map->spin_lock_off != val + reg->off) { 5441 - verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock'\n", 5442 - val + reg->off); 5447 + if (map->record->spin_lock_off != val + reg->off) { 5448 + verbose(env, "off %lld doesn't point to 'struct bpf_spin_lock' that is at %d\n", 5449 + val + reg->off, map->record->spin_lock_off); 5443 5450 return -EINVAL; 5444 5451 } 5445 5452 if (is_lock) { ··· 5471 5500 map->name); 5472 5501 return -EINVAL; 5473 5502 } 5474 - if (!map_value_has_timer(map)) { 5475 - if (map->timer_off == -E2BIG) 5476 - verbose(env, 5477 - "map '%s' has more than one 'struct bpf_timer'\n", 5478 - map->name); 5479 - else if (map->timer_off == -ENOENT) 5480 - verbose(env, 5481 - "map '%s' doesn't have 'struct bpf_timer'\n", 5482 - map->name); 5483 - else 5484 - verbose(env, 5485 - "map '%s' is not a struct type or bpf_timer is mangled\n", 5486 - map->name); 5503 + if (!btf_record_has_field(map->record, BPF_TIMER)) { 5504 + verbose(env, "map '%s' has no valid bpf_timer\n", map->name); 5487 5505 return -EINVAL; 5488 5506 } 5489 - if (map->timer_off != val + reg->off) { 5507 + if (map->record->timer_off != val + reg->off) { 5490 5508 verbose(env, "off %lld doesn't point to 'struct bpf_timer' that is at %d\n", 5491 - val + reg->off, map->timer_off); 5509 + val + reg->off, map->record->timer_off); 5492 5510 return -EINVAL; 5493 5511 } 5494 5512 if (meta->map_ptr) { ··· 7430 7470 regs[BPF_REG_0].map_uid = meta.map_uid; 7431 7471 regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag; 7432 7472 if (!type_may_be_null(ret_type) && 7433 - map_value_has_spin_lock(meta.map_ptr)) { 7473 + btf_record_has_field(meta.map_ptr->record, BPF_SPIN_LOCK)) { 7434 7474 regs[BPF_REG_0].id = ++env->id_gen; 7435 7475 } 7436 7476 break; ··· 10341 10381 insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE) { 10342 10382 dst_reg->type = PTR_TO_MAP_VALUE; 10343 10383 dst_reg->off = aux->map_off; 10344 - if (map_value_has_spin_lock(map)) 10384 + if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) 10345 10385 dst_reg->id = ++env->id_gen; 10346 10386 } else if (insn->src_reg == BPF_PSEUDO_MAP_FD || 10347 10387 insn->src_reg == BPF_PSEUDO_MAP_IDX) { ··· 12619 12659 { 12620 12660 enum bpf_prog_type prog_type = resolve_prog_type(prog); 12621 12661 12622 - if (map_value_has_spin_lock(map)) { 12662 + if (btf_record_has_field(map->record, BPF_SPIN_LOCK)) { 12623 12663 if (prog_type == BPF_PROG_TYPE_SOCKET_FILTER) { 12624 12664 verbose(env, "socket filter progs cannot use bpf_spin_lock yet\n"); 12625 12665 return -EINVAL; ··· 12636 12676 } 12637 12677 } 12638 12678 12639 - if (map_value_has_timer(map)) { 12679 + if (btf_record_has_field(map->record, BPF_TIMER)) { 12640 12680 if (is_tracing_prog_type(prog_type)) { 12641 12681 verbose(env, "tracing progs cannot use bpf_timer yet\n"); 12642 12682 return -EINVAL;
+2 -2
net/core/bpf_sk_storage.c
··· 147 147 if (!copy_selem) 148 148 return NULL; 149 149 150 - if (map_value_has_spin_lock(&smap->map)) 150 + if (btf_record_has_field(smap->map.record, BPF_SPIN_LOCK)) 151 151 copy_map_value_locked(&smap->map, SDATA(copy_selem)->data, 152 152 SDATA(selem)->data, true); 153 153 else ··· 566 566 if (!nla_value) 567 567 goto errout; 568 568 569 - if (map_value_has_spin_lock(&smap->map)) 569 + if (btf_record_has_field(smap->map.record, BPF_SPIN_LOCK)) 570 570 copy_map_value_locked(&smap->map, nla_data(nla_value), 571 571 sdata->data, true); 572 572 else