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

Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says:

====================
pull-request: bpf 2023-11-08

We've added 16 non-merge commits during the last 6 day(s) which contain
a total of 30 files changed, 341 insertions(+), 130 deletions(-).

The main changes are:

1) Fix a BPF verifier issue in precision tracking for BPF_ALU | BPF_TO_BE |
BPF_END where the source register was incorrectly marked as precise,
from Shung-Hsi Yu.

2) Fix a concurrency issue in bpf_timer where the former could still have
been alive after an application releases or unpins the map, from Hou Tao.

3) Fix a BPF verifier issue where immediates are incorrectly cast to u32
before being spilled and therefore losing sign information, from Hao Sun.

4) Fix a misplaced BPF_TRACE_ITER in check_css_task_iter_allowlist which
incorrectly compared bpf_prog_type with bpf_attach_type, from Chuyi Zhou.

5) Add __bpf_hook_{start,end} as well as __bpf_kfunc_{start,end}_defs macros,
migrate all BPF-related __diag callsites over to it, and add a new
__diag_ignore_all for -Wmissing-declarations to the macros to address
recent build warnings, from Dave Marchevsky.

6) Fix broken BPF selftest build of xdp_hw_metadata test on architectures
where char is not signed, from Björn Töpel.

7) Fix test_maps selftest to properly use LIBBPF_OPTS() macro to initialize
the bpf_map_create_opts, from Andrii Nakryiko.

8) Fix bpffs selftest to avoid unmounting /sys/kernel/debug as it may have
been mounted and used by other applications already, from Manu Bretelle.

9) Fix a build issue without CONFIG_CGROUPS wrt css_task open-coded
iterators, from Matthieu Baerts.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
selftests/bpf: get trusted cgrp from bpf_iter__cgroup directly
bpf: Let verifier consider {task,cgroup} is trusted in bpf_iter_reg
selftests/bpf: Fix broken build where char is unsigned
selftests/bpf: precision tracking test for BPF_NEG and BPF_END
bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
selftests/bpf: Add test for using css_task iter in sleepable progs
selftests/bpf: Add tests for css_task iter combining with cgroup iter
bpf: Relax allowlist for css_task iter
selftests/bpf: fix test_maps' use of bpf_map_create_opts
bpf: Check map->usercnt after timer->timer is assigned
bpf: Add __bpf_hook_{start,end} macros
bpf: Add __bpf_kfunc_{start,end}_defs macros
selftests/bpf: fix test_bpffs
selftests/bpf: Add test for immediate spilled to stack
bpf: Fix check_stack_write_fixed_off() to correctly spill imm
bpf: fix compilation error without CGROUPS
====================

Link: https://lore.kernel.org/r/20231108132448.1970-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+341 -130
+2 -4
Documentation/bpf/kfuncs.rst
··· 37 37 An example is given below:: 38 38 39 39 /* Disables missing prototype warnings */ 40 - __diag_push(); 41 - __diag_ignore_all("-Wmissing-prototypes", 42 - "Global kfuncs as their definitions will be in BTF"); 40 + __bpf_kfunc_start_defs(); 43 41 44 42 __bpf_kfunc struct task_struct *bpf_find_get_task_by_vpid(pid_t nr) 45 43 { 46 44 return find_get_task_by_vpid(nr); 47 45 } 48 46 49 - __diag_pop(); 47 + __bpf_kfunc_end_defs(); 50 48 51 49 A wrapper kfunc is often needed when we need to annotate parameters of the 52 50 kfunc. Otherwise one may directly make the kfunc visible to the BPF program by
+11
include/linux/btf.h
··· 84 84 */ 85 85 #define __bpf_kfunc __used noinline 86 86 87 + #define __bpf_kfunc_start_defs() \ 88 + __diag_push(); \ 89 + __diag_ignore_all("-Wmissing-declarations", \ 90 + "Global kfuncs as their definitions will be in BTF");\ 91 + __diag_ignore_all("-Wmissing-prototypes", \ 92 + "Global kfuncs as their definitions will be in BTF") 93 + 94 + #define __bpf_kfunc_end_defs() __diag_pop() 95 + #define __bpf_hook_start() __bpf_kfunc_start_defs() 96 + #define __bpf_hook_end() __bpf_kfunc_end_defs() 97 + 87 98 /* 88 99 * Return the name of the passed struct, if exists, or halt the build if for 89 100 * example the structure gets renamed. In this way, developers have to revisit
+2 -4
kernel/bpf/bpf_iter.c
··· 782 782 int end; /* final value, exclusive */ 783 783 } __aligned(8); 784 784 785 - __diag_push(); 786 - __diag_ignore_all("-Wmissing-prototypes", 787 - "Global functions as their definitions will be in vmlinux BTF"); 785 + __bpf_kfunc_start_defs(); 788 786 789 787 __bpf_kfunc int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end) 790 788 { ··· 841 843 s->cur = s->end = 0; 842 844 } 843 845 844 - __diag_pop(); 846 + __bpf_kfunc_end_defs();
+3 -5
kernel/bpf/cgroup_iter.c
··· 282 282 .ctx_arg_info_size = 1, 283 283 .ctx_arg_info = { 284 284 { offsetof(struct bpf_iter__cgroup, cgroup), 285 - PTR_TO_BTF_ID_OR_NULL }, 285 + PTR_TO_BTF_ID_OR_NULL | PTR_TRUSTED }, 286 286 }, 287 287 .seq_info = &cgroup_iter_seq_info, 288 288 }; ··· 305 305 unsigned int flags; 306 306 } __attribute__((aligned(8))); 307 307 308 - __diag_push(); 309 - __diag_ignore_all("-Wmissing-prototypes", 310 - "Global functions as their definitions will be in vmlinux BTF"); 308 + __bpf_kfunc_start_defs(); 311 309 312 310 __bpf_kfunc int bpf_iter_css_new(struct bpf_iter_css *it, 313 311 struct cgroup_subsys_state *start, unsigned int flags) ··· 356 358 { 357 359 } 358 360 359 - __diag_pop(); 361 + __bpf_kfunc_end_defs();
+2 -4
kernel/bpf/cpumask.c
··· 34 34 return cpu < nr_cpu_ids; 35 35 } 36 36 37 - __diag_push(); 38 - __diag_ignore_all("-Wmissing-prototypes", 39 - "Global kfuncs as their definitions will be in BTF"); 37 + __bpf_kfunc_start_defs(); 40 38 41 39 /** 42 40 * bpf_cpumask_create() - Create a mutable BPF cpumask. ··· 405 407 return cpumask_any_and_distribute(src1, src2); 406 408 } 407 409 408 - __diag_pop(); 410 + __bpf_kfunc_end_defs(); 409 411 410 412 BTF_SET8_START(cpumask_kfunc_btf_ids) 411 413 BTF_ID_FLAGS(func, bpf_cpumask_create, KF_ACQUIRE | KF_RET_NULL)
+23 -16
kernel/bpf/helpers.c
··· 1177 1177 ret = -EBUSY; 1178 1178 goto out; 1179 1179 } 1180 - if (!atomic64_read(&map->usercnt)) { 1181 - /* maps with timers must be either held by user space 1182 - * or pinned in bpffs. 1183 - */ 1184 - ret = -EPERM; 1185 - goto out; 1186 - } 1187 1180 /* allocate hrtimer via map_kmalloc to use memcg accounting */ 1188 1181 t = bpf_map_kmalloc_node(map, sizeof(*t), GFP_ATOMIC, map->numa_node); 1189 1182 if (!t) { ··· 1189 1196 rcu_assign_pointer(t->callback_fn, NULL); 1190 1197 hrtimer_init(&t->timer, clockid, HRTIMER_MODE_REL_SOFT); 1191 1198 t->timer.function = bpf_timer_cb; 1192 - timer->timer = t; 1199 + WRITE_ONCE(timer->timer, t); 1200 + /* Guarantee the order between timer->timer and map->usercnt. So 1201 + * when there are concurrent uref release and bpf timer init, either 1202 + * bpf_timer_cancel_and_free() called by uref release reads a no-NULL 1203 + * timer or atomic64_read() below returns a zero usercnt. 1204 + */ 1205 + smp_mb(); 1206 + if (!atomic64_read(&map->usercnt)) { 1207 + /* maps with timers must be either held by user space 1208 + * or pinned in bpffs. 1209 + */ 1210 + WRITE_ONCE(timer->timer, NULL); 1211 + kfree(t); 1212 + ret = -EPERM; 1213 + } 1193 1214 out: 1194 1215 __bpf_spin_unlock_irqrestore(&timer->lock); 1195 1216 return ret; ··· 1381 1374 /* The subsequent bpf_timer_start/cancel() helpers won't be able to use 1382 1375 * this timer, since it won't be initialized. 1383 1376 */ 1384 - timer->timer = NULL; 1377 + WRITE_ONCE(timer->timer, NULL); 1385 1378 out: 1386 1379 __bpf_spin_unlock_irqrestore(&timer->lock); 1387 1380 if (!t) ··· 1893 1886 } 1894 1887 } 1895 1888 1896 - __diag_push(); 1897 - __diag_ignore_all("-Wmissing-prototypes", 1898 - "Global functions as their definitions will be in vmlinux BTF"); 1889 + __bpf_kfunc_start_defs(); 1899 1890 1900 1891 __bpf_kfunc void *bpf_obj_new_impl(u64 local_type_id__k, void *meta__ign) 1901 1892 { ··· 2510 2505 WARN(1, "A call to BPF exception callback should never return\n"); 2511 2506 } 2512 2507 2513 - __diag_pop(); 2508 + __bpf_kfunc_end_defs(); 2514 2509 2515 2510 BTF_SET8_START(generic_btf_ids) 2516 2511 #ifdef CONFIG_KEXEC_CORE ··· 2569 2564 BTF_ID_FLAGS(func, bpf_iter_task_vma_new, KF_ITER_NEW | KF_RCU) 2570 2565 BTF_ID_FLAGS(func, bpf_iter_task_vma_next, KF_ITER_NEXT | KF_RET_NULL) 2571 2566 BTF_ID_FLAGS(func, bpf_iter_task_vma_destroy, KF_ITER_DESTROY) 2567 + #ifdef CONFIG_CGROUPS 2572 2568 BTF_ID_FLAGS(func, bpf_iter_css_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS) 2573 2569 BTF_ID_FLAGS(func, bpf_iter_css_task_next, KF_ITER_NEXT | KF_RET_NULL) 2574 2570 BTF_ID_FLAGS(func, bpf_iter_css_task_destroy, KF_ITER_DESTROY) 2575 - BTF_ID_FLAGS(func, bpf_iter_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED) 2576 - BTF_ID_FLAGS(func, bpf_iter_task_next, KF_ITER_NEXT | KF_RET_NULL) 2577 - BTF_ID_FLAGS(func, bpf_iter_task_destroy, KF_ITER_DESTROY) 2578 2571 BTF_ID_FLAGS(func, bpf_iter_css_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED) 2579 2572 BTF_ID_FLAGS(func, bpf_iter_css_next, KF_ITER_NEXT | KF_RET_NULL) 2580 2573 BTF_ID_FLAGS(func, bpf_iter_css_destroy, KF_ITER_DESTROY) 2574 + #endif 2575 + BTF_ID_FLAGS(func, bpf_iter_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED) 2576 + BTF_ID_FLAGS(func, bpf_iter_task_next, KF_ITER_NEXT | KF_RET_NULL) 2577 + BTF_ID_FLAGS(func, bpf_iter_task_destroy, KF_ITER_DESTROY) 2581 2578 BTF_ID_FLAGS(func, bpf_dynptr_adjust) 2582 2579 BTF_ID_FLAGS(func, bpf_dynptr_is_null) 2583 2580 BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
+2 -4
kernel/bpf/map_iter.c
··· 193 193 194 194 late_initcall(bpf_map_iter_init); 195 195 196 - __diag_push(); 197 - __diag_ignore_all("-Wmissing-prototypes", 198 - "Global functions as their definitions will be in vmlinux BTF"); 196 + __bpf_kfunc_start_defs(); 199 197 200 198 __bpf_kfunc s64 bpf_map_sum_elem_count(const struct bpf_map *map) 201 199 { ··· 211 213 return ret; 212 214 } 213 215 214 - __diag_pop(); 216 + __bpf_kfunc_end_defs(); 215 217 216 218 BTF_SET8_START(bpf_map_iter_kfunc_ids) 217 219 BTF_ID_FLAGS(func, bpf_map_sum_elem_count, KF_TRUSTED_ARGS)
+11 -13
kernel/bpf/task_iter.c
··· 704 704 .ctx_arg_info_size = 1, 705 705 .ctx_arg_info = { 706 706 { offsetof(struct bpf_iter__task, task), 707 - PTR_TO_BTF_ID_OR_NULL }, 707 + PTR_TO_BTF_ID_OR_NULL | PTR_TRUSTED }, 708 708 }, 709 709 .seq_info = &task_seq_info, 710 710 .fill_link_info = bpf_iter_fill_link_info, ··· 822 822 struct bpf_iter_task_vma_kern_data *data; 823 823 } __attribute__((aligned(8))); 824 824 825 - __diag_push(); 826 - __diag_ignore_all("-Wmissing-prototypes", 827 - "Global functions as their definitions will be in vmlinux BTF"); 825 + __bpf_kfunc_start_defs(); 828 826 829 827 __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, 830 828 struct task_struct *task, u64 addr) ··· 888 890 } 889 891 } 890 892 891 - __diag_pop(); 893 + __bpf_kfunc_end_defs(); 894 + 895 + #ifdef CONFIG_CGROUPS 892 896 893 897 struct bpf_iter_css_task { 894 898 __u64 __opaque[1]; ··· 900 900 struct css_task_iter *css_it; 901 901 } __attribute__((aligned(8))); 902 902 903 - __diag_push(); 904 - __diag_ignore_all("-Wmissing-prototypes", 905 - "Global functions as their definitions will be in vmlinux BTF"); 903 + __bpf_kfunc_start_defs(); 906 904 907 905 __bpf_kfunc int bpf_iter_css_task_new(struct bpf_iter_css_task *it, 908 906 struct cgroup_subsys_state *css, unsigned int flags) ··· 946 948 bpf_mem_free(&bpf_global_ma, kit->css_it); 947 949 } 948 950 949 - __diag_pop(); 951 + __bpf_kfunc_end_defs(); 952 + 953 + #endif /* CONFIG_CGROUPS */ 950 954 951 955 struct bpf_iter_task { 952 956 __u64 __opaque[3]; ··· 969 969 BPF_TASK_ITER_PROC_THREADS 970 970 }; 971 971 972 - __diag_push(); 973 - __diag_ignore_all("-Wmissing-prototypes", 974 - "Global functions as their definitions will be in vmlinux BTF"); 972 + __bpf_kfunc_start_defs(); 975 973 976 974 __bpf_kfunc int bpf_iter_task_new(struct bpf_iter_task *it, 977 975 struct task_struct *task__nullable, unsigned int flags) ··· 1039 1041 { 1040 1042 } 1041 1043 1042 - __diag_pop(); 1044 + __bpf_kfunc_end_defs(); 1043 1045 1044 1046 DEFINE_PER_CPU(struct mmap_unlock_irq_work, mmap_unlock_work); 1045 1047
+27 -6
kernel/bpf/verifier.c
··· 3742 3742 if (class == BPF_ALU || class == BPF_ALU64) { 3743 3743 if (!bt_is_reg_set(bt, dreg)) 3744 3744 return 0; 3745 - if (opcode == BPF_MOV) { 3745 + if (opcode == BPF_END || opcode == BPF_NEG) { 3746 + /* sreg is reserved and unused 3747 + * dreg still need precision before this insn 3748 + */ 3749 + return 0; 3750 + } else if (opcode == BPF_MOV) { 3746 3751 if (BPF_SRC(insn->code) == BPF_X) { 3747 3752 /* dreg = sreg or dreg = (s8, s16, s32)sreg 3748 3753 * dreg needs precision after this insn ··· 4679 4674 insn->imm != 0 && env->bpf_capable) { 4680 4675 struct bpf_reg_state fake_reg = {}; 4681 4676 4682 - __mark_reg_known(&fake_reg, (u32)insn->imm); 4677 + __mark_reg_known(&fake_reg, insn->imm); 4683 4678 fake_reg.type = SCALAR_VALUE; 4684 4679 save_register_state(state, spi, &fake_reg, size); 4685 4680 } else if (reg && is_spillable_regtype(reg->type)) { ··· 5393 5388 /* Once GCC supports btf_type_tag the following mechanism will be replaced with tag check */ 5394 5389 BTF_SET_START(rcu_protected_types) 5395 5390 BTF_ID(struct, prog_test_ref_kfunc) 5391 + #ifdef CONFIG_CGROUPS 5396 5392 BTF_ID(struct, cgroup) 5393 + #endif 5397 5394 BTF_ID(struct, bpf_cpumask) 5398 5395 BTF_ID(struct, task_struct) 5399 5396 BTF_SET_END(rcu_protected_types) ··· 10842 10835 BTF_ID(func, bpf_percpu_obj_new_impl) 10843 10836 BTF_ID(func, bpf_percpu_obj_drop_impl) 10844 10837 BTF_ID(func, bpf_throw) 10838 + #ifdef CONFIG_CGROUPS 10845 10839 BTF_ID(func, bpf_iter_css_task_new) 10840 + #endif 10846 10841 BTF_SET_END(special_kfunc_set) 10847 10842 10848 10843 BTF_ID_LIST(special_kfunc_list) ··· 10870 10861 BTF_ID(func, bpf_percpu_obj_new_impl) 10871 10862 BTF_ID(func, bpf_percpu_obj_drop_impl) 10872 10863 BTF_ID(func, bpf_throw) 10864 + #ifdef CONFIG_CGROUPS 10873 10865 BTF_ID(func, bpf_iter_css_task_new) 10866 + #else 10867 + BTF_ID_UNUSED 10868 + #endif 10874 10869 10875 10870 static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta) 10876 10871 { ··· 11407 11394 &meta->arg_rbtree_root.field); 11408 11395 } 11409 11396 11397 + /* 11398 + * css_task iter allowlist is needed to avoid dead locking on css_set_lock. 11399 + * LSM hooks and iters (both sleepable and non-sleepable) are safe. 11400 + * Any sleepable progs are also safe since bpf_check_attach_target() enforce 11401 + * them can only be attached to some specific hook points. 11402 + */ 11410 11403 static bool check_css_task_iter_allowlist(struct bpf_verifier_env *env) 11411 11404 { 11412 11405 enum bpf_prog_type prog_type = resolve_prog_type(env->prog); ··· 11420 11401 switch (prog_type) { 11421 11402 case BPF_PROG_TYPE_LSM: 11422 11403 return true; 11423 - case BPF_TRACE_ITER: 11424 - return env->prog->aux->sleepable; 11404 + case BPF_PROG_TYPE_TRACING: 11405 + if (env->prog->expected_attach_type == BPF_TRACE_ITER) 11406 + return true; 11407 + fallthrough; 11425 11408 default: 11426 - return false; 11409 + return env->prog->aux->sleepable; 11427 11410 } 11428 11411 } 11429 11412 ··· 11684 11663 case KF_ARG_PTR_TO_ITER: 11685 11664 if (meta->func_id == special_kfunc_list[KF_bpf_iter_css_task_new]) { 11686 11665 if (!check_css_task_iter_allowlist(env)) { 11687 - verbose(env, "css_task_iter is only allowed in bpf_lsm and bpf iter-s\n"); 11666 + verbose(env, "css_task_iter is only allowed in bpf_lsm, bpf_iter and sleepable progs\n"); 11688 11667 return -EINVAL; 11689 11668 } 11690 11669 }
+3 -6
kernel/cgroup/rstat.c
··· 156 156 * optimize away the callsite. Therefore, __weak is needed to ensure that the 157 157 * call is still emitted, by telling the compiler that we don't know what the 158 158 * function might eventually be. 159 - * 160 - * __diag_* below are needed to dismiss the missing prototype warning. 161 159 */ 162 - __diag_push(); 163 - __diag_ignore_all("-Wmissing-prototypes", 164 - "kfuncs which will be used in BPF programs"); 160 + 161 + __bpf_hook_start(); 165 162 166 163 __weak noinline void bpf_rstat_flush(struct cgroup *cgrp, 167 164 struct cgroup *parent, int cpu) 168 165 { 169 166 } 170 167 171 - __diag_pop(); 168 + __bpf_hook_end(); 172 169 173 170 /* see cgroup_rstat_flush() */ 174 171 static void cgroup_rstat_flush_locked(struct cgroup *cgrp)
+2 -4
kernel/trace/bpf_trace.c
··· 1252 1252 }; 1253 1253 1254 1254 #ifdef CONFIG_KEYS 1255 - __diag_push(); 1256 - __diag_ignore_all("-Wmissing-prototypes", 1257 - "kfuncs which will be used in BPF programs"); 1255 + __bpf_kfunc_start_defs(); 1258 1256 1259 1257 /** 1260 1258 * bpf_lookup_user_key - lookup a key by its serial ··· 1402 1404 } 1403 1405 #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ 1404 1406 1405 - __diag_pop(); 1407 + __bpf_kfunc_end_defs(); 1406 1408 1407 1409 BTF_SET8_START(key_sig_kfunc_set) 1408 1410 BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
+3 -4
net/bpf/test_run.c
··· 503 503 * architecture dependent calling conventions. 7+ can be supported in the 504 504 * future. 505 505 */ 506 - __diag_push(); 507 - __diag_ignore_all("-Wmissing-prototypes", 508 - "Global functions as their definitions will be in vmlinux BTF"); 506 + __bpf_kfunc_start_defs(); 507 + 509 508 __bpf_kfunc int bpf_fentry_test1(int a) 510 509 { 511 510 return a + 1; ··· 604 605 { 605 606 } 606 607 607 - __diag_pop(); 608 + __bpf_kfunc_end_defs(); 608 609 609 610 BTF_SET8_START(bpf_test_modify_return_ids) 610 611 BTF_ID_FLAGS(func, bpf_modify_return_test)
+4 -9
net/core/filter.c
··· 11767 11767 return func; 11768 11768 } 11769 11769 11770 - __diag_push(); 11771 - __diag_ignore_all("-Wmissing-prototypes", 11772 - "Global functions as their definitions will be in vmlinux BTF"); 11770 + __bpf_kfunc_start_defs(); 11773 11771 __bpf_kfunc int bpf_dynptr_from_skb(struct sk_buff *skb, u64 flags, 11774 11772 struct bpf_dynptr_kern *ptr__uninit) 11775 11773 { ··· 11814 11816 11815 11817 return 0; 11816 11818 } 11817 - __diag_pop(); 11819 + __bpf_kfunc_end_defs(); 11818 11820 11819 11821 int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags, 11820 11822 struct bpf_dynptr_kern *ptr__uninit) ··· 11877 11879 } 11878 11880 late_initcall(bpf_kfunc_init); 11879 11881 11880 - /* Disables missing prototype warnings */ 11881 - __diag_push(); 11882 - __diag_ignore_all("-Wmissing-prototypes", 11883 - "Global functions as their definitions will be in vmlinux BTF"); 11882 + __bpf_kfunc_start_defs(); 11884 11883 11885 11884 /* bpf_sock_destroy: Destroy the given socket with ECONNABORTED error code. 11886 11885 * ··· 11911 11916 return sk->sk_prot->diag_destroy(sk, ECONNABORTED); 11912 11917 } 11913 11918 11914 - __diag_pop() 11919 + __bpf_kfunc_end_defs(); 11915 11920 11916 11921 BTF_SET8_START(bpf_sk_iter_kfunc_ids) 11917 11922 BTF_ID_FLAGS(func, bpf_sock_destroy, KF_TRUSTED_ARGS)
+2 -4
net/core/xdp.c
··· 696 696 return nxdpf; 697 697 } 698 698 699 - __diag_push(); 700 - __diag_ignore_all("-Wmissing-prototypes", 701 - "Global functions as their definitions will be in vmlinux BTF"); 699 + __bpf_kfunc_start_defs(); 702 700 703 701 /** 704 702 * bpf_xdp_metadata_rx_timestamp - Read XDP frame RX timestamp. ··· 736 738 return -EOPNOTSUPP; 737 739 } 738 740 739 - __diag_pop(); 741 + __bpf_kfunc_end_defs(); 740 742 741 743 BTF_SET8_START(xdp_metadata_kfunc_ids) 742 744 #define XDP_METADATA_KFUNC(_, __, name, ___) BTF_ID_FLAGS(func, name, KF_TRUSTED_ARGS)
+2 -4
net/ipv4/fou_bpf.c
··· 22 22 FOU_BPF_ENCAP_GUE, 23 23 }; 24 24 25 - __diag_push(); 26 - __diag_ignore_all("-Wmissing-prototypes", 27 - "Global functions as their definitions will be in BTF"); 25 + __bpf_kfunc_start_defs(); 28 26 29 27 /* bpf_skb_set_fou_encap - Set FOU encap parameters 30 28 * ··· 98 100 return 0; 99 101 } 100 102 101 - __diag_pop() 103 + __bpf_kfunc_end_defs(); 102 104 103 105 BTF_SET8_START(fou_kfunc_set) 104 106 BTF_ID_FLAGS(func, bpf_skb_set_fou_encap)
+2 -4
net/netfilter/nf_conntrack_bpf.c
··· 230 230 return 0; 231 231 } 232 232 233 - __diag_push(); 234 - __diag_ignore_all("-Wmissing-prototypes", 235 - "Global functions as their definitions will be in nf_conntrack BTF"); 233 + __bpf_kfunc_start_defs(); 236 234 237 235 /* bpf_xdp_ct_alloc - Allocate a new CT entry 238 236 * ··· 465 467 return nf_ct_change_status_common(nfct, status); 466 468 } 467 469 468 - __diag_pop() 470 + __bpf_kfunc_end_defs(); 469 471 470 472 BTF_SET8_START(nf_ct_kfunc_set) 471 473 BTF_ID_FLAGS(func, bpf_xdp_ct_alloc, KF_ACQUIRE | KF_RET_NULL)
+2 -4
net/netfilter/nf_nat_bpf.c
··· 12 12 #include <net/netfilter/nf_conntrack_core.h> 13 13 #include <net/netfilter/nf_nat.h> 14 14 15 - __diag_push(); 16 - __diag_ignore_all("-Wmissing-prototypes", 17 - "Global functions as their definitions will be in nf_nat BTF"); 15 + __bpf_kfunc_start_defs(); 18 16 19 17 /* bpf_ct_set_nat_info - Set source or destination nat address 20 18 * ··· 52 54 return nf_nat_setup_info(ct, &range, manip) == NF_DROP ? -ENOMEM : 0; 53 55 } 54 56 55 - __diag_pop() 57 + __bpf_kfunc_end_defs(); 56 58 57 59 BTF_SET8_START(nf_nat_kfunc_set) 58 60 BTF_ID_FLAGS(func, bpf_ct_set_nat_info, KF_TRUSTED_ARGS)
+2 -6
net/socket.c
··· 1685 1685 * Therefore, __weak is needed to ensure that the call is still 1686 1686 * emitted, by telling the compiler that we don't know what the 1687 1687 * function might eventually be. 1688 - * 1689 - * __diag_* below are needed to dismiss the missing prototype warning. 1690 1688 */ 1691 1689 1692 - __diag_push(); 1693 - __diag_ignore_all("-Wmissing-prototypes", 1694 - "A fmod_ret entry point for BPF programs"); 1690 + __bpf_hook_start(); 1695 1691 1696 1692 __weak noinline int update_socket_protocol(int family, int type, int protocol) 1697 1693 { 1698 1694 return protocol; 1699 1695 } 1700 1696 1701 - __diag_pop(); 1697 + __bpf_hook_end(); 1702 1698 1703 1699 int __sys_socket(int family, int type, int protocol) 1704 1700 {
+2 -4
net/xfrm/xfrm_interface_bpf.c
··· 27 27 int link; 28 28 }; 29 29 30 - __diag_push(); 31 - __diag_ignore_all("-Wmissing-prototypes", 32 - "Global functions as their definitions will be in xfrm_interface BTF"); 30 + __bpf_kfunc_start_defs(); 33 31 34 32 /* bpf_skb_get_xfrm_info - Get XFRM metadata 35 33 * ··· 91 93 return 0; 92 94 } 93 95 94 - __diag_pop() 96 + __bpf_kfunc_end_defs(); 95 97 96 98 BTF_SET8_START(xfrm_ifc_kfunc_set) 97 99 BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info)
+2 -4
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
··· 39 39 int b; 40 40 }; 41 41 42 - __diag_push(); 43 - __diag_ignore_all("-Wmissing-prototypes", 44 - "Global functions as their definitions will be in bpf_testmod.ko BTF"); 42 + __bpf_hook_start(); 45 43 46 44 noinline int 47 45 bpf_testmod_test_struct_arg_1(struct bpf_testmod_struct_arg_2 a, int b, int c) { ··· 333 335 } 334 336 EXPORT_SYMBOL_GPL(bpf_fentry_shadow_test); 335 337 336 - __diag_pop(); 338 + __bpf_hook_end(); 337 339 338 340 static struct bin_attribute bin_attr_bpf_testmod_file __ro_after_init = { 339 341 .attr = { .name = "bpf_testmod", .mode = 0666, },
+5 -15
tools/testing/selftests/bpf/map_tests/map_percpu_stats.c
··· 326 326 327 327 static int create_hash(void) 328 328 { 329 - struct bpf_map_create_opts map_opts = { 330 - .sz = sizeof(map_opts), 331 - .map_flags = BPF_F_NO_PREALLOC, 332 - }; 329 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = BPF_F_NO_PREALLOC); 333 330 334 331 return map_create(BPF_MAP_TYPE_HASH, "hash", &map_opts); 335 332 } 336 333 337 334 static int create_percpu_hash(void) 338 335 { 339 - struct bpf_map_create_opts map_opts = { 340 - .sz = sizeof(map_opts), 341 - .map_flags = BPF_F_NO_PREALLOC, 342 - }; 336 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = BPF_F_NO_PREALLOC); 343 337 344 338 return map_create(BPF_MAP_TYPE_PERCPU_HASH, "percpu_hash", &map_opts); 345 339 } ··· 350 356 351 357 static int create_lru_hash(__u32 type, __u32 map_flags) 352 358 { 353 - struct bpf_map_create_opts map_opts = { 354 - .sz = sizeof(map_opts), 355 - .map_flags = map_flags, 356 - }; 359 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = map_flags); 357 360 358 361 return map_create(type, "lru_hash", &map_opts); 359 362 } 360 363 361 364 static int create_hash_of_maps(void) 362 365 { 363 - struct bpf_map_create_opts map_opts = { 364 - .sz = sizeof(map_opts), 366 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, 365 367 .map_flags = BPF_F_NO_PREALLOC, 366 368 .inner_map_fd = create_small_hash(), 367 - }; 369 + ); 368 370 int ret; 369 371 370 372 ret = map_create_opts(BPF_MAP_TYPE_HASH_OF_MAPS, "hash_of_maps",
+33
tools/testing/selftests/bpf/prog_tests/cgroup_iter.c
··· 4 4 #include <test_progs.h> 5 5 #include <bpf/libbpf.h> 6 6 #include <bpf/btf.h> 7 + #include "iters_css_task.skel.h" 7 8 #include "cgroup_iter.skel.h" 8 9 #include "cgroup_helpers.h" 9 10 ··· 264 263 close(cgrp_fd); 265 264 } 266 265 266 + static void test_walk_self_only_css_task(void) 267 + { 268 + struct iters_css_task *skel; 269 + int err; 270 + 271 + skel = iters_css_task__open(); 272 + if (!ASSERT_OK_PTR(skel, "skel_open")) 273 + return; 274 + 275 + bpf_program__set_autoload(skel->progs.cgroup_id_printer, true); 276 + 277 + err = iters_css_task__load(skel); 278 + if (!ASSERT_OK(err, "skel_load")) 279 + goto cleanup; 280 + 281 + err = join_cgroup(cg_path[CHILD2]); 282 + if (!ASSERT_OK(err, "join_cgroup")) 283 + goto cleanup; 284 + 285 + skel->bss->target_pid = getpid(); 286 + snprintf(expected_output, sizeof(expected_output), 287 + PROLOGUE "%8llu\n" EPILOGUE, cg_id[CHILD2]); 288 + read_from_cgroup_iter(skel->progs.cgroup_id_printer, cg_fd[CHILD2], 289 + BPF_CGROUP_ITER_SELF_ONLY, "test_walk_self_only_css_task"); 290 + ASSERT_EQ(skel->bss->css_task_cnt, 1, "css_task_cnt"); 291 + cleanup: 292 + iters_css_task__destroy(skel); 293 + } 294 + 267 295 void test_cgroup_iter(void) 268 296 { 269 297 struct cgroup_iter *skel = NULL; ··· 323 293 test_walk_self_only(skel); 324 294 if (test__start_subtest("cgroup_iter__dead_self_only")) 325 295 test_walk_dead_self_only(skel); 296 + if (test__start_subtest("cgroup_iter__self_only_css_task")) 297 + test_walk_self_only_css_task(); 298 + 326 299 out: 327 300 cgroup_iter__destroy(skel); 328 301 cleanup_cgroups();
+1
tools/testing/selftests/bpf/prog_tests/iters.c
··· 294 294 RUN_TESTS(iters_state_safety); 295 295 RUN_TESTS(iters_looping); 296 296 RUN_TESTS(iters); 297 + RUN_TESTS(iters_css_task); 297 298 298 299 if (env.has_testmod) 299 300 RUN_TESTS(iters_testmod_seq);
+8 -3
tools/testing/selftests/bpf/prog_tests/test_bpffs.c
··· 8 8 #include <sys/types.h> 9 9 #include <test_progs.h> 10 10 11 - #define TDIR "/sys/kernel/debug" 11 + /* TDIR must be in a location we can create a directory in. */ 12 + #define TDIR "/tmp/test_bpffs_testdir" 12 13 13 14 static int read_iter(char *file) 14 15 { ··· 44 43 if (!ASSERT_OK(err, "mount /")) 45 44 goto out; 46 45 47 - err = umount(TDIR); 48 - if (!ASSERT_OK(err, "umount " TDIR)) 46 + err = mkdir(TDIR, 0777); 47 + /* If the directory already exists we can carry on. It may be left over 48 + * from a previous run. 49 + */ 50 + if ((err && errno != EEXIST) && !ASSERT_OK(err, "mkdir " TDIR)) 49 51 goto out; 50 52 51 53 err = mount("none", TDIR, "tmpfs", 0, NULL); ··· 142 138 rmdir(TDIR "/fs1"); 143 139 rmdir(TDIR "/fs2"); 144 140 umount(TDIR); 141 + rmdir(TDIR); 145 142 exit(err); 146 143 } 147 144
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 46 46 #include "verifier_movsx.skel.h" 47 47 #include "verifier_netfilter_ctx.skel.h" 48 48 #include "verifier_netfilter_retcode.skel.h" 49 + #include "verifier_precision.skel.h" 49 50 #include "verifier_prevent_map_lookup.skel.h" 50 51 #include "verifier_raw_stack.skel.h" 51 52 #include "verifier_raw_tp_writable.skel.h" ··· 154 153 void test_verifier_movsx(void) { RUN(verifier_movsx); } 155 154 void test_verifier_netfilter_ctx(void) { RUN(verifier_netfilter_ctx); } 156 155 void test_verifier_netfilter_retcode(void) { RUN(verifier_netfilter_retcode); } 156 + void test_verifier_precision(void) { RUN(verifier_precision); } 157 157 void test_verifier_prevent_map_lookup(void) { RUN(verifier_prevent_map_lookup); } 158 158 void test_verifier_raw_stack(void) { RUN(verifier_raw_stack); } 159 159 void test_verifier_raw_tp_writable(void) { RUN(verifier_raw_tp_writable); }
+55
tools/testing/selftests/bpf/progs/iters_css_task.c
··· 10 10 11 11 char _license[] SEC("license") = "GPL"; 12 12 13 + struct cgroup *bpf_cgroup_acquire(struct cgroup *p) __ksym; 13 14 struct cgroup *bpf_cgroup_from_id(u64 cgid) __ksym; 14 15 void bpf_cgroup_release(struct cgroup *p) __ksym; 15 16 ··· 45 44 bpf_cgroup_release(cgrp); 46 45 47 46 return -EPERM; 47 + } 48 + 49 + static inline u64 cgroup_id(struct cgroup *cgrp) 50 + { 51 + return cgrp->kn->id; 52 + } 53 + 54 + SEC("?iter/cgroup") 55 + int cgroup_id_printer(struct bpf_iter__cgroup *ctx) 56 + { 57 + struct seq_file *seq = ctx->meta->seq; 58 + struct cgroup *cgrp = ctx->cgroup; 59 + struct cgroup_subsys_state *css; 60 + struct task_struct *task; 61 + 62 + /* epilogue */ 63 + if (cgrp == NULL) { 64 + BPF_SEQ_PRINTF(seq, "epilogue\n"); 65 + return 0; 66 + } 67 + 68 + /* prologue */ 69 + if (ctx->meta->seq_num == 0) 70 + BPF_SEQ_PRINTF(seq, "prologue\n"); 71 + 72 + BPF_SEQ_PRINTF(seq, "%8llu\n", cgroup_id(cgrp)); 73 + 74 + css = &cgrp->self; 75 + css_task_cnt = 0; 76 + bpf_for_each(css_task, task, css, CSS_TASK_ITER_PROCS) { 77 + if (task->pid == target_pid) 78 + css_task_cnt++; 79 + } 80 + 81 + return 0; 82 + } 83 + 84 + SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") 85 + int BPF_PROG(iter_css_task_for_each_sleep) 86 + { 87 + u64 cgrp_id = bpf_get_current_cgroup_id(); 88 + struct cgroup *cgrp = bpf_cgroup_from_id(cgrp_id); 89 + struct cgroup_subsys_state *css; 90 + struct task_struct *task; 91 + 92 + if (cgrp == NULL) 93 + return 0; 94 + css = &cgrp->self; 95 + 96 + bpf_for_each(css_task, task, css, CSS_TASK_ITER_PROCS) { 97 + 98 + } 99 + bpf_cgroup_release(cgrp); 100 + return 0; 48 101 }
+2 -2
tools/testing/selftests/bpf/progs/iters_task_failure.c
··· 84 84 return 0; 85 85 } 86 86 87 - SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") 88 - __failure __msg("css_task_iter is only allowed in bpf_lsm and bpf iter-s") 87 + SEC("?fentry/" SYS_PREFIX "sys_getpgid") 88 + __failure __msg("css_task_iter is only allowed in bpf_lsm, bpf_iter and sleepable progs") 89 89 int BPF_PROG(iter_css_task_for_each) 90 90 { 91 91 u64 cg_id = bpf_get_current_cgroup_id();
+93
tools/testing/selftests/bpf/progs/verifier_precision.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) 2023 SUSE LLC */ 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 6 + 7 + SEC("?raw_tp") 8 + __success __log_level(2) 9 + __msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10") 10 + __msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0xfffffff8 goto pc+2") 11 + __msg("mark_precise: frame0: regs=r2 stack= before 1: (87) r2 = -r2") 12 + __msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 8") 13 + __naked int bpf_neg(void) 14 + { 15 + asm volatile ( 16 + "r2 = 8;" 17 + "r2 = -r2;" 18 + "if r2 != -8 goto 1f;" 19 + "r1 = r10;" 20 + "r1 += r2;" 21 + "1:" 22 + "r0 = 0;" 23 + "exit;" 24 + ::: __clobber_all); 25 + } 26 + 27 + SEC("?raw_tp") 28 + __success __log_level(2) 29 + __msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10") 30 + __msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2") 31 + __msg("mark_precise: frame0: regs=r2 stack= before 1: (d4) r2 = le16 r2") 32 + __msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0") 33 + __naked int bpf_end_to_le(void) 34 + { 35 + asm volatile ( 36 + "r2 = 0;" 37 + "r2 = le16 r2;" 38 + "if r2 != 0 goto 1f;" 39 + "r1 = r10;" 40 + "r1 += r2;" 41 + "1:" 42 + "r0 = 0;" 43 + "exit;" 44 + ::: __clobber_all); 45 + } 46 + 47 + 48 + SEC("?raw_tp") 49 + __success __log_level(2) 50 + __msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10") 51 + __msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2") 52 + __msg("mark_precise: frame0: regs=r2 stack= before 1: (dc) r2 = be16 r2") 53 + __msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0") 54 + __naked int bpf_end_to_be(void) 55 + { 56 + asm volatile ( 57 + "r2 = 0;" 58 + "r2 = be16 r2;" 59 + "if r2 != 0 goto 1f;" 60 + "r1 = r10;" 61 + "r1 += r2;" 62 + "1:" 63 + "r0 = 0;" 64 + "exit;" 65 + ::: __clobber_all); 66 + } 67 + 68 + #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 69 + (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 70 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 71 + __clang_major__ >= 18 72 + 73 + SEC("?raw_tp") 74 + __success __log_level(2) 75 + __msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10") 76 + __msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2") 77 + __msg("mark_precise: frame0: regs=r2 stack= before 1: (d7) r2 = bswap16 r2") 78 + __msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0") 79 + __naked int bpf_end_bswap(void) 80 + { 81 + asm volatile ( 82 + "r2 = 0;" 83 + "r2 = bswap16 r2;" 84 + "if r2 != 0 goto 1f;" 85 + "r1 = r10;" 86 + "r1 += r2;" 87 + "1:" 88 + "r0 = 0;" 89 + "exit;" 90 + ::: __clobber_all); 91 + } 92 + 93 + #endif /* v4 instruction */
+32
tools/testing/selftests/bpf/verifier/bpf_st_mem.c
··· 65 65 .expected_attach_type = BPF_SK_LOOKUP, 66 66 .runs = -1, 67 67 }, 68 + { 69 + "BPF_ST_MEM stack imm sign", 70 + /* Check if verifier correctly reasons about sign of an 71 + * immediate spilled to stack by BPF_ST instruction. 72 + * 73 + * fp[-8] = -44; 74 + * r0 = fp[-8]; 75 + * if r0 s< 0 goto ret0; 76 + * r0 = -1; 77 + * exit; 78 + * ret0: 79 + * r0 = 0; 80 + * exit; 81 + */ 82 + .insns = { 83 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, -44), 84 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 85 + BPF_JMP_IMM(BPF_JSLT, BPF_REG_0, 0, 2), 86 + BPF_MOV64_IMM(BPF_REG_0, -1), 87 + BPF_EXIT_INSN(), 88 + BPF_MOV64_IMM(BPF_REG_0, 0), 89 + BPF_EXIT_INSN(), 90 + }, 91 + /* Use prog type that requires return value in range [0, 1] */ 92 + .prog_type = BPF_PROG_TYPE_SK_LOOKUP, 93 + .expected_attach_type = BPF_SK_LOOKUP, 94 + .result = VERBOSE_ACCEPT, 95 + .runs = -1, 96 + .errstr = "0: (7a) *(u64 *)(r10 -8) = -44 ; R10=fp0 fp-8_w=-44\ 97 + 2: (c5) if r0 s< 0x0 goto pc+2\ 98 + R0_w=-44", 99 + },
+1 -1
tools/testing/selftests/bpf/xdp_hw_metadata.c
··· 430 430 431 431 static void read_args(int argc, char *argv[]) 432 432 { 433 - char opt; 433 + int opt; 434 434 435 435 while ((opt = getopt(argc, argv, "mh")) != -1) { 436 436 switch (opt) {