mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
bpf-for-netdev
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQTFp0I1jqZrAX+hPRXbK58LschIgwUCZUsiDAAKCRDbK58LschI g9xXAQCaFjj55sXDpr1qKG2D3PMSDURx7SzmpzIay/A/dqVDPgEAlgU6XsMW6w6S poMN8KniDLtBgj6nIKfJEAgIXeIYTAs= =qXjW -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
942b8b38de
|
|
@ -37,16 +37,14 @@ prototype in a header for the wrapper kfunc.
|
|||
An example is given below::
|
||||
|
||||
/* Disables missing prototype warnings */
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global kfuncs as their definitions will be in BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc struct task_struct *bpf_find_get_task_by_vpid(pid_t nr)
|
||||
{
|
||||
return find_get_task_by_vpid(nr);
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
A wrapper kfunc is often needed when we need to annotate parameters of the
|
||||
kfunc. Otherwise one may directly make the kfunc visible to the BPF program by
|
||||
|
|
|
|||
|
|
@ -84,6 +84,17 @@
|
|||
*/
|
||||
#define __bpf_kfunc __used noinline
|
||||
|
||||
#define __bpf_kfunc_start_defs() \
|
||||
__diag_push(); \
|
||||
__diag_ignore_all("-Wmissing-declarations", \
|
||||
"Global kfuncs as their definitions will be in BTF");\
|
||||
__diag_ignore_all("-Wmissing-prototypes", \
|
||||
"Global kfuncs as their definitions will be in BTF")
|
||||
|
||||
#define __bpf_kfunc_end_defs() __diag_pop()
|
||||
#define __bpf_hook_start() __bpf_kfunc_start_defs()
|
||||
#define __bpf_hook_end() __bpf_kfunc_end_defs()
|
||||
|
||||
/*
|
||||
* Return the name of the passed struct, if exists, or halt the build if for
|
||||
* example the structure gets renamed. In this way, developers have to revisit
|
||||
|
|
|
|||
|
|
@ -782,9 +782,7 @@ struct bpf_iter_num_kern {
|
|||
int end; /* final value, exclusive */
|
||||
} __aligned(8);
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end)
|
||||
{
|
||||
|
|
@ -843,4 +841,4 @@ __bpf_kfunc void bpf_iter_num_destroy(struct bpf_iter_num *it)
|
|||
s->cur = s->end = 0;
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ static struct bpf_iter_reg bpf_cgroup_reg_info = {
|
|||
.ctx_arg_info_size = 1,
|
||||
.ctx_arg_info = {
|
||||
{ offsetof(struct bpf_iter__cgroup, cgroup),
|
||||
PTR_TO_BTF_ID_OR_NULL },
|
||||
PTR_TO_BTF_ID_OR_NULL | PTR_TRUSTED },
|
||||
},
|
||||
.seq_info = &cgroup_iter_seq_info,
|
||||
};
|
||||
|
|
@ -305,9 +305,7 @@ struct bpf_iter_css_kern {
|
|||
unsigned int flags;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_iter_css_new(struct bpf_iter_css *it,
|
||||
struct cgroup_subsys_state *start, unsigned int flags)
|
||||
|
|
@ -358,4 +356,4 @@ __bpf_kfunc void bpf_iter_css_destroy(struct bpf_iter_css *it)
|
|||
{
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ static bool cpu_valid(u32 cpu)
|
|||
return cpu < nr_cpu_ids;
|
||||
}
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global kfuncs as their definitions will be in BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/**
|
||||
* bpf_cpumask_create() - Create a mutable BPF cpumask.
|
||||
|
|
@ -407,7 +405,7 @@ __bpf_kfunc u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1,
|
|||
return cpumask_any_and_distribute(src1, src2);
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(cpumask_kfunc_btf_ids)
|
||||
BTF_ID_FLAGS(func, bpf_cpumask_create, KF_ACQUIRE | KF_RET_NULL)
|
||||
|
|
|
|||
|
|
@ -1177,13 +1177,6 @@ BPF_CALL_3(bpf_timer_init, struct bpf_timer_kern *, timer, struct bpf_map *, map
|
|||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (!atomic64_read(&map->usercnt)) {
|
||||
/* maps with timers must be either held by user space
|
||||
* or pinned in bpffs.
|
||||
*/
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
/* allocate hrtimer via map_kmalloc to use memcg accounting */
|
||||
t = bpf_map_kmalloc_node(map, sizeof(*t), GFP_ATOMIC, map->numa_node);
|
||||
if (!t) {
|
||||
|
|
@ -1196,7 +1189,21 @@ BPF_CALL_3(bpf_timer_init, struct bpf_timer_kern *, timer, struct bpf_map *, map
|
|||
rcu_assign_pointer(t->callback_fn, NULL);
|
||||
hrtimer_init(&t->timer, clockid, HRTIMER_MODE_REL_SOFT);
|
||||
t->timer.function = bpf_timer_cb;
|
||||
timer->timer = t;
|
||||
WRITE_ONCE(timer->timer, t);
|
||||
/* Guarantee the order between timer->timer and map->usercnt. So
|
||||
* when there are concurrent uref release and bpf timer init, either
|
||||
* bpf_timer_cancel_and_free() called by uref release reads a no-NULL
|
||||
* timer or atomic64_read() below returns a zero usercnt.
|
||||
*/
|
||||
smp_mb();
|
||||
if (!atomic64_read(&map->usercnt)) {
|
||||
/* maps with timers must be either held by user space
|
||||
* or pinned in bpffs.
|
||||
*/
|
||||
WRITE_ONCE(timer->timer, NULL);
|
||||
kfree(t);
|
||||
ret = -EPERM;
|
||||
}
|
||||
out:
|
||||
__bpf_spin_unlock_irqrestore(&timer->lock);
|
||||
return ret;
|
||||
|
|
@ -1374,7 +1381,7 @@ void bpf_timer_cancel_and_free(void *val)
|
|||
/* The subsequent bpf_timer_start/cancel() helpers won't be able to use
|
||||
* this timer, since it won't be initialized.
|
||||
*/
|
||||
timer->timer = NULL;
|
||||
WRITE_ONCE(timer->timer, NULL);
|
||||
out:
|
||||
__bpf_spin_unlock_irqrestore(&timer->lock);
|
||||
if (!t)
|
||||
|
|
@ -1886,9 +1893,7 @@ void bpf_rb_root_free(const struct btf_field *field, void *rb_root,
|
|||
}
|
||||
}
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc void *bpf_obj_new_impl(u64 local_type_id__k, void *meta__ign)
|
||||
{
|
||||
|
|
@ -2505,7 +2510,7 @@ __bpf_kfunc void bpf_throw(u64 cookie)
|
|||
WARN(1, "A call to BPF exception callback should never return\n");
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(generic_btf_ids)
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
|
|
@ -2564,15 +2569,17 @@ BTF_ID_FLAGS(func, bpf_iter_num_destroy, KF_ITER_DESTROY)
|
|||
BTF_ID_FLAGS(func, bpf_iter_task_vma_new, KF_ITER_NEW | KF_RCU)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_vma_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_vma_destroy, KF_ITER_DESTROY)
|
||||
#ifdef CONFIG_CGROUPS
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_task_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_task_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED)
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_css_destroy, KF_ITER_DESTROY)
|
||||
#endif
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_new, KF_ITER_NEW | KF_TRUSTED_ARGS | KF_RCU_PROTECTED)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_next, KF_ITER_NEXT | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_iter_task_destroy, KF_ITER_DESTROY)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_adjust)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_is_null)
|
||||
BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly)
|
||||
|
|
|
|||
|
|
@ -193,9 +193,7 @@ static int __init bpf_map_iter_init(void)
|
|||
|
||||
late_initcall(bpf_map_iter_init);
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc s64 bpf_map_sum_elem_count(const struct bpf_map *map)
|
||||
{
|
||||
|
|
@ -213,7 +211,7 @@ __bpf_kfunc s64 bpf_map_sum_elem_count(const struct bpf_map *map)
|
|||
return ret;
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(bpf_map_iter_kfunc_ids)
|
||||
BTF_ID_FLAGS(func, bpf_map_sum_elem_count, KF_TRUSTED_ARGS)
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ static struct bpf_iter_reg task_reg_info = {
|
|||
.ctx_arg_info_size = 1,
|
||||
.ctx_arg_info = {
|
||||
{ offsetof(struct bpf_iter__task, task),
|
||||
PTR_TO_BTF_ID_OR_NULL },
|
||||
PTR_TO_BTF_ID_OR_NULL | PTR_TRUSTED },
|
||||
},
|
||||
.seq_info = &task_seq_info,
|
||||
.fill_link_info = bpf_iter_fill_link_info,
|
||||
|
|
@ -822,9 +822,7 @@ struct bpf_iter_task_vma_kern {
|
|||
struct bpf_iter_task_vma_kern_data *data;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,
|
||||
struct task_struct *task, u64 addr)
|
||||
|
|
@ -890,7 +888,9 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
|
|||
}
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
#ifdef CONFIG_CGROUPS
|
||||
|
||||
struct bpf_iter_css_task {
|
||||
__u64 __opaque[1];
|
||||
|
|
@ -900,9 +900,7 @@ struct bpf_iter_css_task_kern {
|
|||
struct css_task_iter *css_it;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_iter_css_task_new(struct bpf_iter_css_task *it,
|
||||
struct cgroup_subsys_state *css, unsigned int flags)
|
||||
|
|
@ -948,7 +946,9 @@ __bpf_kfunc void bpf_iter_css_task_destroy(struct bpf_iter_css_task *it)
|
|||
bpf_mem_free(&bpf_global_ma, kit->css_it);
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
#endif /* CONFIG_CGROUPS */
|
||||
|
||||
struct bpf_iter_task {
|
||||
__u64 __opaque[3];
|
||||
|
|
@ -969,9 +969,7 @@ enum {
|
|||
BPF_TASK_ITER_PROC_THREADS
|
||||
};
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_iter_task_new(struct bpf_iter_task *it,
|
||||
struct task_struct *task__nullable, unsigned int flags)
|
||||
|
|
@ -1041,7 +1039,7 @@ __bpf_kfunc void bpf_iter_task_destroy(struct bpf_iter_task *it)
|
|||
{
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
DEFINE_PER_CPU(struct mmap_unlock_irq_work, mmap_unlock_work);
|
||||
|
||||
|
|
|
|||
|
|
@ -3742,7 +3742,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|||
if (class == BPF_ALU || class == BPF_ALU64) {
|
||||
if (!bt_is_reg_set(bt, dreg))
|
||||
return 0;
|
||||
if (opcode == BPF_MOV) {
|
||||
if (opcode == BPF_END || opcode == BPF_NEG) {
|
||||
/* sreg is reserved and unused
|
||||
* dreg still need precision before this insn
|
||||
*/
|
||||
return 0;
|
||||
} else if (opcode == BPF_MOV) {
|
||||
if (BPF_SRC(insn->code) == BPF_X) {
|
||||
/* dreg = sreg or dreg = (s8, s16, s32)sreg
|
||||
* dreg needs precision after this insn
|
||||
|
|
@ -4674,7 +4679,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|||
insn->imm != 0 && env->bpf_capable) {
|
||||
struct bpf_reg_state fake_reg = {};
|
||||
|
||||
__mark_reg_known(&fake_reg, (u32)insn->imm);
|
||||
__mark_reg_known(&fake_reg, insn->imm);
|
||||
fake_reg.type = SCALAR_VALUE;
|
||||
save_register_state(state, spi, &fake_reg, size);
|
||||
} else if (reg && is_spillable_regtype(reg->type)) {
|
||||
|
|
@ -5388,7 +5393,9 @@ static bool in_rcu_cs(struct bpf_verifier_env *env)
|
|||
/* Once GCC supports btf_type_tag the following mechanism will be replaced with tag check */
|
||||
BTF_SET_START(rcu_protected_types)
|
||||
BTF_ID(struct, prog_test_ref_kfunc)
|
||||
#ifdef CONFIG_CGROUPS
|
||||
BTF_ID(struct, cgroup)
|
||||
#endif
|
||||
BTF_ID(struct, bpf_cpumask)
|
||||
BTF_ID(struct, task_struct)
|
||||
BTF_SET_END(rcu_protected_types)
|
||||
|
|
@ -10835,7 +10842,9 @@ BTF_ID(func, bpf_dynptr_clone)
|
|||
BTF_ID(func, bpf_percpu_obj_new_impl)
|
||||
BTF_ID(func, bpf_percpu_obj_drop_impl)
|
||||
BTF_ID(func, bpf_throw)
|
||||
#ifdef CONFIG_CGROUPS
|
||||
BTF_ID(func, bpf_iter_css_task_new)
|
||||
#endif
|
||||
BTF_SET_END(special_kfunc_set)
|
||||
|
||||
BTF_ID_LIST(special_kfunc_list)
|
||||
|
|
@ -10861,7 +10870,11 @@ BTF_ID(func, bpf_dynptr_clone)
|
|||
BTF_ID(func, bpf_percpu_obj_new_impl)
|
||||
BTF_ID(func, bpf_percpu_obj_drop_impl)
|
||||
BTF_ID(func, bpf_throw)
|
||||
#ifdef CONFIG_CGROUPS
|
||||
BTF_ID(func, bpf_iter_css_task_new)
|
||||
#else
|
||||
BTF_ID_UNUSED
|
||||
#endif
|
||||
|
||||
static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
|
||||
{
|
||||
|
|
@ -11394,6 +11407,12 @@ static int process_kf_arg_ptr_to_rbtree_node(struct bpf_verifier_env *env,
|
|||
&meta->arg_rbtree_root.field);
|
||||
}
|
||||
|
||||
/*
|
||||
* css_task iter allowlist is needed to avoid dead locking on css_set_lock.
|
||||
* LSM hooks and iters (both sleepable and non-sleepable) are safe.
|
||||
* Any sleepable progs are also safe since bpf_check_attach_target() enforce
|
||||
* them can only be attached to some specific hook points.
|
||||
*/
|
||||
static bool check_css_task_iter_allowlist(struct bpf_verifier_env *env)
|
||||
{
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
|
||||
|
|
@ -11401,10 +11420,12 @@ static bool check_css_task_iter_allowlist(struct bpf_verifier_env *env)
|
|||
switch (prog_type) {
|
||||
case BPF_PROG_TYPE_LSM:
|
||||
return true;
|
||||
case BPF_TRACE_ITER:
|
||||
return env->prog->aux->sleepable;
|
||||
case BPF_PROG_TYPE_TRACING:
|
||||
if (env->prog->expected_attach_type == BPF_TRACE_ITER)
|
||||
return true;
|
||||
fallthrough;
|
||||
default:
|
||||
return false;
|
||||
return env->prog->aux->sleepable;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11663,7 +11684,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
|
|||
case KF_ARG_PTR_TO_ITER:
|
||||
if (meta->func_id == special_kfunc_list[KF_bpf_iter_css_task_new]) {
|
||||
if (!check_css_task_iter_allowlist(env)) {
|
||||
verbose(env, "css_task_iter is only allowed in bpf_lsm and bpf iter-s\n");
|
||||
verbose(env, "css_task_iter is only allowed in bpf_lsm, bpf_iter and sleepable progs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,19 +156,16 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
|
|||
* optimize away the callsite. Therefore, __weak is needed to ensure that the
|
||||
* call is still emitted, by telling the compiler that we don't know what the
|
||||
* function might eventually be.
|
||||
*
|
||||
* __diag_* below are needed to dismiss the missing prototype warning.
|
||||
*/
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"kfuncs which will be used in BPF programs");
|
||||
|
||||
__bpf_hook_start();
|
||||
|
||||
__weak noinline void bpf_rstat_flush(struct cgroup *cgrp,
|
||||
struct cgroup *parent, int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_hook_end();
|
||||
|
||||
/* see cgroup_rstat_flush() */
|
||||
static void cgroup_rstat_flush_locked(struct cgroup *cgrp)
|
||||
|
|
|
|||
|
|
@ -1252,9 +1252,7 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_KEYS
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"kfuncs which will be used in BPF programs");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/**
|
||||
* bpf_lookup_user_key - lookup a key by its serial
|
||||
|
|
@ -1404,7 +1402,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr_kern *data_ptr,
|
|||
}
|
||||
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(key_sig_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
|
||||
|
|
|
|||
|
|
@ -503,9 +503,8 @@ static int bpf_test_finish(const union bpf_attr *kattr,
|
|||
* architecture dependent calling conventions. 7+ can be supported in the
|
||||
* future.
|
||||
*/
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
__bpf_kfunc int bpf_fentry_test1(int a)
|
||||
{
|
||||
return a + 1;
|
||||
|
|
@ -605,7 +604,7 @@ __bpf_kfunc void bpf_kfunc_call_memb_release(struct prog_test_member *p)
|
|||
{
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(bpf_test_modify_return_ids)
|
||||
BTF_ID_FLAGS(func, bpf_modify_return_test)
|
||||
|
|
|
|||
|
|
@ -11767,9 +11767,7 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id)
|
|||
return func;
|
||||
}
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
__bpf_kfunc int bpf_dynptr_from_skb(struct sk_buff *skb, u64 flags,
|
||||
struct bpf_dynptr_kern *ptr__uninit)
|
||||
{
|
||||
|
|
@ -11816,7 +11814,7 @@ __bpf_kfunc int bpf_sock_addr_set_sun_path(struct bpf_sock_addr_kern *sa_kern,
|
|||
|
||||
return 0;
|
||||
}
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
|
||||
struct bpf_dynptr_kern *ptr__uninit)
|
||||
|
|
@ -11879,10 +11877,7 @@ static int __init bpf_kfunc_init(void)
|
|||
}
|
||||
late_initcall(bpf_kfunc_init);
|
||||
|
||||
/* Disables missing prototype warnings */
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/* bpf_sock_destroy: Destroy the given socket with ECONNABORTED error code.
|
||||
*
|
||||
|
|
@ -11916,7 +11911,7 @@ __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)
|
|||
return sk->sk_prot->diag_destroy(sk, ECONNABORTED);
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(bpf_sk_iter_kfunc_ids)
|
||||
BTF_ID_FLAGS(func, bpf_sock_destroy, KF_TRUSTED_ARGS)
|
||||
|
|
|
|||
|
|
@ -696,9 +696,7 @@ struct xdp_frame *xdpf_clone(struct xdp_frame *xdpf)
|
|||
return nxdpf;
|
||||
}
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in vmlinux BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/**
|
||||
* bpf_xdp_metadata_rx_timestamp - Read XDP frame RX timestamp.
|
||||
|
|
@ -738,7 +736,7 @@ __bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(xdp_metadata_kfunc_ids)
|
||||
#define XDP_METADATA_KFUNC(_, __, name, ___) BTF_ID_FLAGS(func, name, KF_TRUSTED_ARGS)
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ enum bpf_fou_encap_type {
|
|||
FOU_BPF_ENCAP_GUE,
|
||||
};
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/* bpf_skb_set_fou_encap - Set FOU encap parameters
|
||||
*
|
||||
|
|
@ -100,7 +98,7 @@ __bpf_kfunc int bpf_skb_get_fou_encap(struct __sk_buff *skb_ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(fou_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_skb_set_fou_encap)
|
||||
|
|
|
|||
|
|
@ -230,9 +230,7 @@ static int _nf_conntrack_btf_struct_access(struct bpf_verifier_log *log,
|
|||
return 0;
|
||||
}
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in nf_conntrack BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/* bpf_xdp_ct_alloc - Allocate a new CT entry
|
||||
*
|
||||
|
|
@ -467,7 +465,7 @@ __bpf_kfunc int bpf_ct_change_status(struct nf_conn *nfct, u32 status)
|
|||
return nf_ct_change_status_common(nfct, status);
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(nf_ct_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_xdp_ct_alloc, KF_ACQUIRE | KF_RET_NULL)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@
|
|||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in nf_nat BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/* bpf_ct_set_nat_info - Set source or destination nat address
|
||||
*
|
||||
|
|
@ -54,7 +52,7 @@ __bpf_kfunc int bpf_ct_set_nat_info(struct nf_conn___init *nfct,
|
|||
return nf_nat_setup_info(ct, &range, manip) == NF_DROP ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(nf_nat_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_ct_set_nat_info, KF_TRUSTED_ARGS)
|
||||
|
|
|
|||
|
|
@ -1685,20 +1685,16 @@ struct file *__sys_socket_file(int family, int type, int protocol)
|
|||
* Therefore, __weak is needed to ensure that the call is still
|
||||
* emitted, by telling the compiler that we don't know what the
|
||||
* function might eventually be.
|
||||
*
|
||||
* __diag_* below are needed to dismiss the missing prototype warning.
|
||||
*/
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"A fmod_ret entry point for BPF programs");
|
||||
__bpf_hook_start();
|
||||
|
||||
__weak noinline int update_socket_protocol(int family, int type, int protocol)
|
||||
{
|
||||
return protocol;
|
||||
}
|
||||
|
||||
__diag_pop();
|
||||
__bpf_hook_end();
|
||||
|
||||
int __sys_socket(int family, int type, int protocol)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ struct bpf_xfrm_info {
|
|||
int link;
|
||||
};
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in xfrm_interface BTF");
|
||||
__bpf_kfunc_start_defs();
|
||||
|
||||
/* bpf_skb_get_xfrm_info - Get XFRM metadata
|
||||
*
|
||||
|
|
@ -93,7 +91,7 @@ __bpf_kfunc int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx, const struct bp
|
|||
return 0;
|
||||
}
|
||||
|
||||
__diag_pop()
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_SET8_START(xfrm_ifc_kfunc_set)
|
||||
BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info)
|
||||
|
|
|
|||
|
|
@ -39,9 +39,7 @@ struct bpf_testmod_struct_arg_4 {
|
|||
int b;
|
||||
};
|
||||
|
||||
__diag_push();
|
||||
__diag_ignore_all("-Wmissing-prototypes",
|
||||
"Global functions as their definitions will be in bpf_testmod.ko BTF");
|
||||
__bpf_hook_start();
|
||||
|
||||
noinline int
|
||||
bpf_testmod_test_struct_arg_1(struct bpf_testmod_struct_arg_2 a, int b, int c) {
|
||||
|
|
@ -335,7 +333,7 @@ noinline int bpf_fentry_shadow_test(int a)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(bpf_fentry_shadow_test);
|
||||
|
||||
__diag_pop();
|
||||
__bpf_hook_end();
|
||||
|
||||
static struct bin_attribute bin_attr_bpf_testmod_file __ro_after_init = {
|
||||
.attr = { .name = "bpf_testmod", .mode = 0666, },
|
||||
|
|
|
|||
|
|
@ -326,20 +326,14 @@ static int map_create(__u32 type, const char *name, struct bpf_map_create_opts *
|
|||
|
||||
static int create_hash(void)
|
||||
{
|
||||
struct bpf_map_create_opts map_opts = {
|
||||
.sz = sizeof(map_opts),
|
||||
.map_flags = BPF_F_NO_PREALLOC,
|
||||
};
|
||||
LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = BPF_F_NO_PREALLOC);
|
||||
|
||||
return map_create(BPF_MAP_TYPE_HASH, "hash", &map_opts);
|
||||
}
|
||||
|
||||
static int create_percpu_hash(void)
|
||||
{
|
||||
struct bpf_map_create_opts map_opts = {
|
||||
.sz = sizeof(map_opts),
|
||||
.map_flags = BPF_F_NO_PREALLOC,
|
||||
};
|
||||
LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = BPF_F_NO_PREALLOC);
|
||||
|
||||
return map_create(BPF_MAP_TYPE_PERCPU_HASH, "percpu_hash", &map_opts);
|
||||
}
|
||||
|
|
@ -356,21 +350,17 @@ static int create_percpu_hash_prealloc(void)
|
|||
|
||||
static int create_lru_hash(__u32 type, __u32 map_flags)
|
||||
{
|
||||
struct bpf_map_create_opts map_opts = {
|
||||
.sz = sizeof(map_opts),
|
||||
.map_flags = map_flags,
|
||||
};
|
||||
LIBBPF_OPTS(bpf_map_create_opts, map_opts, .map_flags = map_flags);
|
||||
|
||||
return map_create(type, "lru_hash", &map_opts);
|
||||
}
|
||||
|
||||
static int create_hash_of_maps(void)
|
||||
{
|
||||
struct bpf_map_create_opts map_opts = {
|
||||
.sz = sizeof(map_opts),
|
||||
LIBBPF_OPTS(bpf_map_create_opts, map_opts,
|
||||
.map_flags = BPF_F_NO_PREALLOC,
|
||||
.inner_map_fd = create_small_hash(),
|
||||
};
|
||||
);
|
||||
int ret;
|
||||
|
||||
ret = map_create_opts(BPF_MAP_TYPE_HASH_OF_MAPS, "hash_of_maps",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <test_progs.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <bpf/btf.h>
|
||||
#include "iters_css_task.skel.h"
|
||||
#include "cgroup_iter.skel.h"
|
||||
#include "cgroup_helpers.h"
|
||||
|
||||
|
|
@ -263,6 +264,35 @@ static void test_walk_dead_self_only(struct cgroup_iter *skel)
|
|||
close(cgrp_fd);
|
||||
}
|
||||
|
||||
static void test_walk_self_only_css_task(void)
|
||||
{
|
||||
struct iters_css_task *skel;
|
||||
int err;
|
||||
|
||||
skel = iters_css_task__open();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
return;
|
||||
|
||||
bpf_program__set_autoload(skel->progs.cgroup_id_printer, true);
|
||||
|
||||
err = iters_css_task__load(skel);
|
||||
if (!ASSERT_OK(err, "skel_load"))
|
||||
goto cleanup;
|
||||
|
||||
err = join_cgroup(cg_path[CHILD2]);
|
||||
if (!ASSERT_OK(err, "join_cgroup"))
|
||||
goto cleanup;
|
||||
|
||||
skel->bss->target_pid = getpid();
|
||||
snprintf(expected_output, sizeof(expected_output),
|
||||
PROLOGUE "%8llu\n" EPILOGUE, cg_id[CHILD2]);
|
||||
read_from_cgroup_iter(skel->progs.cgroup_id_printer, cg_fd[CHILD2],
|
||||
BPF_CGROUP_ITER_SELF_ONLY, "test_walk_self_only_css_task");
|
||||
ASSERT_EQ(skel->bss->css_task_cnt, 1, "css_task_cnt");
|
||||
cleanup:
|
||||
iters_css_task__destroy(skel);
|
||||
}
|
||||
|
||||
void test_cgroup_iter(void)
|
||||
{
|
||||
struct cgroup_iter *skel = NULL;
|
||||
|
|
@ -293,6 +323,9 @@ void test_cgroup_iter(void)
|
|||
test_walk_self_only(skel);
|
||||
if (test__start_subtest("cgroup_iter__dead_self_only"))
|
||||
test_walk_dead_self_only(skel);
|
||||
if (test__start_subtest("cgroup_iter__self_only_css_task"))
|
||||
test_walk_self_only_css_task();
|
||||
|
||||
out:
|
||||
cgroup_iter__destroy(skel);
|
||||
cleanup_cgroups();
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ void test_iters(void)
|
|||
RUN_TESTS(iters_state_safety);
|
||||
RUN_TESTS(iters_looping);
|
||||
RUN_TESTS(iters);
|
||||
RUN_TESTS(iters_css_task);
|
||||
|
||||
if (env.has_testmod)
|
||||
RUN_TESTS(iters_testmod_seq);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
#include <sys/types.h>
|
||||
#include <test_progs.h>
|
||||
|
||||
#define TDIR "/sys/kernel/debug"
|
||||
/* TDIR must be in a location we can create a directory in. */
|
||||
#define TDIR "/tmp/test_bpffs_testdir"
|
||||
|
||||
static int read_iter(char *file)
|
||||
{
|
||||
|
|
@ -43,8 +44,11 @@ static int fn(void)
|
|||
if (!ASSERT_OK(err, "mount /"))
|
||||
goto out;
|
||||
|
||||
err = umount(TDIR);
|
||||
if (!ASSERT_OK(err, "umount " TDIR))
|
||||
err = mkdir(TDIR, 0777);
|
||||
/* If the directory already exists we can carry on. It may be left over
|
||||
* from a previous run.
|
||||
*/
|
||||
if ((err && errno != EEXIST) && !ASSERT_OK(err, "mkdir " TDIR))
|
||||
goto out;
|
||||
|
||||
err = mount("none", TDIR, "tmpfs", 0, NULL);
|
||||
|
|
@ -138,6 +142,7 @@ static int fn(void)
|
|||
rmdir(TDIR "/fs1");
|
||||
rmdir(TDIR "/fs2");
|
||||
umount(TDIR);
|
||||
rmdir(TDIR);
|
||||
exit(err);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "verifier_movsx.skel.h"
|
||||
#include "verifier_netfilter_ctx.skel.h"
|
||||
#include "verifier_netfilter_retcode.skel.h"
|
||||
#include "verifier_precision.skel.h"
|
||||
#include "verifier_prevent_map_lookup.skel.h"
|
||||
#include "verifier_raw_stack.skel.h"
|
||||
#include "verifier_raw_tp_writable.skel.h"
|
||||
|
|
@ -153,6 +154,7 @@ void test_verifier_meta_access(void) { RUN(verifier_meta_access); }
|
|||
void test_verifier_movsx(void) { RUN(verifier_movsx); }
|
||||
void test_verifier_netfilter_ctx(void) { RUN(verifier_netfilter_ctx); }
|
||||
void test_verifier_netfilter_retcode(void) { RUN(verifier_netfilter_retcode); }
|
||||
void test_verifier_precision(void) { RUN(verifier_precision); }
|
||||
void test_verifier_prevent_map_lookup(void) { RUN(verifier_prevent_map_lookup); }
|
||||
void test_verifier_raw_stack(void) { RUN(verifier_raw_stack); }
|
||||
void test_verifier_raw_tp_writable(void) { RUN(verifier_raw_tp_writable); }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
struct cgroup *bpf_cgroup_acquire(struct cgroup *p) __ksym;
|
||||
struct cgroup *bpf_cgroup_from_id(u64 cgid) __ksym;
|
||||
void bpf_cgroup_release(struct cgroup *p) __ksym;
|
||||
|
||||
|
|
@ -45,3 +46,57 @@ int BPF_PROG(iter_css_task_for_each, struct vm_area_struct *vma,
|
|||
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline u64 cgroup_id(struct cgroup *cgrp)
|
||||
{
|
||||
return cgrp->kn->id;
|
||||
}
|
||||
|
||||
SEC("?iter/cgroup")
|
||||
int cgroup_id_printer(struct bpf_iter__cgroup *ctx)
|
||||
{
|
||||
struct seq_file *seq = ctx->meta->seq;
|
||||
struct cgroup *cgrp = ctx->cgroup;
|
||||
struct cgroup_subsys_state *css;
|
||||
struct task_struct *task;
|
||||
|
||||
/* epilogue */
|
||||
if (cgrp == NULL) {
|
||||
BPF_SEQ_PRINTF(seq, "epilogue\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prologue */
|
||||
if (ctx->meta->seq_num == 0)
|
||||
BPF_SEQ_PRINTF(seq, "prologue\n");
|
||||
|
||||
BPF_SEQ_PRINTF(seq, "%8llu\n", cgroup_id(cgrp));
|
||||
|
||||
css = &cgrp->self;
|
||||
css_task_cnt = 0;
|
||||
bpf_for_each(css_task, task, css, CSS_TASK_ITER_PROCS) {
|
||||
if (task->pid == target_pid)
|
||||
css_task_cnt++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
|
||||
int BPF_PROG(iter_css_task_for_each_sleep)
|
||||
{
|
||||
u64 cgrp_id = bpf_get_current_cgroup_id();
|
||||
struct cgroup *cgrp = bpf_cgroup_from_id(cgrp_id);
|
||||
struct cgroup_subsys_state *css;
|
||||
struct task_struct *task;
|
||||
|
||||
if (cgrp == NULL)
|
||||
return 0;
|
||||
css = &cgrp->self;
|
||||
|
||||
bpf_for_each(css_task, task, css, CSS_TASK_ITER_PROCS) {
|
||||
|
||||
}
|
||||
bpf_cgroup_release(cgrp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ int BPF_PROG(iter_css_lock_and_unlock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
|
||||
__failure __msg("css_task_iter is only allowed in bpf_lsm and bpf iter-s")
|
||||
SEC("?fentry/" SYS_PREFIX "sys_getpgid")
|
||||
__failure __msg("css_task_iter is only allowed in bpf_lsm, bpf_iter and sleepable progs")
|
||||
int BPF_PROG(iter_css_task_for_each)
|
||||
{
|
||||
u64 cg_id = bpf_get_current_cgroup_id();
|
||||
|
|
|
|||
93
tools/testing/selftests/bpf/progs/verifier_precision.c
Normal file
93
tools/testing/selftests/bpf/progs/verifier_precision.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2023 SUSE LLC */
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_misc.h"
|
||||
|
||||
SEC("?raw_tp")
|
||||
__success __log_level(2)
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0xfffffff8 goto pc+2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 1: (87) r2 = -r2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 8")
|
||||
__naked int bpf_neg(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r2 = 8;"
|
||||
"r2 = -r2;"
|
||||
"if r2 != -8 goto 1f;"
|
||||
"r1 = r10;"
|
||||
"r1 += r2;"
|
||||
"1:"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("?raw_tp")
|
||||
__success __log_level(2)
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 1: (d4) r2 = le16 r2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
|
||||
__naked int bpf_end_to_le(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r2 = 0;"
|
||||
"r2 = le16 r2;"
|
||||
"if r2 != 0 goto 1f;"
|
||||
"r1 = r10;"
|
||||
"r1 += r2;"
|
||||
"1:"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
|
||||
SEC("?raw_tp")
|
||||
__success __log_level(2)
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 1: (dc) r2 = be16 r2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
|
||||
__naked int bpf_end_to_be(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r2 = 0;"
|
||||
"r2 = be16 r2;"
|
||||
"if r2 != 0 goto 1f;"
|
||||
"r1 = r10;"
|
||||
"r1 += r2;"
|
||||
"1:"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
|
||||
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
|
||||
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \
|
||||
__clang_major__ >= 18
|
||||
|
||||
SEC("?raw_tp")
|
||||
__success __log_level(2)
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 3: (bf) r1 = r10")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 2: (55) if r2 != 0x0 goto pc+2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 1: (d7) r2 = bswap16 r2")
|
||||
__msg("mark_precise: frame0: regs=r2 stack= before 0: (b7) r2 = 0")
|
||||
__naked int bpf_end_bswap(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r2 = 0;"
|
||||
"r2 = bswap16 r2;"
|
||||
"if r2 != 0 goto 1f;"
|
||||
"r1 = r10;"
|
||||
"r1 += r2;"
|
||||
"1:"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
#endif /* v4 instruction */
|
||||
|
|
@ -65,3 +65,35 @@
|
|||
.expected_attach_type = BPF_SK_LOOKUP,
|
||||
.runs = -1,
|
||||
},
|
||||
{
|
||||
"BPF_ST_MEM stack imm sign",
|
||||
/* Check if verifier correctly reasons about sign of an
|
||||
* immediate spilled to stack by BPF_ST instruction.
|
||||
*
|
||||
* fp[-8] = -44;
|
||||
* r0 = fp[-8];
|
||||
* if r0 s< 0 goto ret0;
|
||||
* r0 = -1;
|
||||
* exit;
|
||||
* ret0:
|
||||
* r0 = 0;
|
||||
* exit;
|
||||
*/
|
||||
.insns = {
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, -44),
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
|
||||
BPF_JMP_IMM(BPF_JSLT, BPF_REG_0, 0, 2),
|
||||
BPF_MOV64_IMM(BPF_REG_0, -1),
|
||||
BPF_EXIT_INSN(),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
/* Use prog type that requires return value in range [0, 1] */
|
||||
.prog_type = BPF_PROG_TYPE_SK_LOOKUP,
|
||||
.expected_attach_type = BPF_SK_LOOKUP,
|
||||
.result = VERBOSE_ACCEPT,
|
||||
.runs = -1,
|
||||
.errstr = "0: (7a) *(u64 *)(r10 -8) = -44 ; R10=fp0 fp-8_w=-44\
|
||||
2: (c5) if r0 s< 0x0 goto pc+2\
|
||||
R0_w=-44",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ static void print_usage(void)
|
|||
|
||||
static void read_args(int argc, char *argv[])
|
||||
{
|
||||
char opt;
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "mh")) != -1) {
|
||||
switch (opt) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user