Commit ad98426a authored by Jakub Kicinski's avatar Jakub Kicinski

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

Daniel Borkmann says:

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

We've added 14 non-merge commits during the last 5 day(s) which contain
a total of 12 files changed, 398 insertions(+), 104 deletions(-).

The main changes are:

1) Fix s390 JIT backchain issues in the trampoline code generation which
   previously clobbered the caller's backchain, from Ilya Leoshkevich.

2) Fix zero-size allocation warning in xsk sockets when the configured
   ring size was close to SIZE_MAX, from Andrew Kanner.

3) Fixes for bpf_mprog API that were found when implementing support
   in the ebpf-go library along with selftests, from Daniel Borkmann
   and Lorenz Bauer.

4) Fix riscv JIT to properly sign-extend the return register in programs.
   This fixes various test_progs selftests on riscv, from Björn Töpel.

5) Fix verifier log for async callback return values where the allowed
   range was displayed incorrectly, from David Vernet.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  s390/bpf: Fix unwinding past the trampoline
  s390/bpf: Fix clobbering the caller's backchain in the trampoline
  selftests/bpf: Add testcase for async callback return value failure
  bpf: Fix verifier log for async callback return values
  xdp: Fix zero-size allocation warning in xskq_create()
  riscv, bpf: Track both a0 (RISC-V ABI) and a5 (BPF) return values
  riscv, bpf: Sign-extend return values
  selftests/bpf: Make seen_tc* variable tests more robust
  selftests/bpf: Test query on empty mprog and pass revision into attach
  selftests/bpf: Adapt assert_mprog_count to always expect 0 count
  selftests/bpf: Test bpf_mprog query API via libbpf and raw syscall
  bpf: Refuse unused attributes in bpf_prog_{attach,detach}
  bpf: Handle bpf_mprog_query with NULL entry
  bpf: Fix BPF_PROG_QUERY last field check
====================

Link: https://lore.kernel.org/r/20231010223610.3984-1-daniel@iogearbox.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 108a36d0 5356ba1f
...@@ -245,7 +245,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx) ...@@ -245,7 +245,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx); emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
/* Set return value. */ /* Set return value. */
if (!is_tail_call) if (!is_tail_call)
emit_mv(RV_REG_A0, RV_REG_A5, ctx); emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx);
emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA, emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */ is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */
ctx); ctx);
...@@ -759,8 +759,10 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of ...@@ -759,8 +759,10 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
if (ret) if (ret)
return ret; return ret;
if (save_ret) if (save_ret) {
emit_sd(RV_REG_FP, -retval_off, regmap[BPF_REG_0], ctx); emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
}
/* update branch with beqz */ /* update branch with beqz */
if (ctx->insns) { if (ctx->insns) {
...@@ -853,7 +855,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -853,7 +855,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET); save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
if (save_ret) { if (save_ret) {
stack_size += 8; stack_size += 16; /* Save both A5 (BPF R0) and A0 */
retval_off = stack_size; retval_off = stack_size;
} }
...@@ -957,6 +959,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -957,6 +959,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
if (ret) if (ret)
goto out; goto out;
emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx); emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
im->ip_after_call = ctx->insns + ctx->ninsns; im->ip_after_call = ctx->insns + ctx->ninsns;
/* 2 nops reserved for auipc+jalr pair */ /* 2 nops reserved for auipc+jalr pair */
emit(rv_nop(), ctx); emit(rv_nop(), ctx);
...@@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
if (flags & BPF_TRAMP_F_RESTORE_REGS) if (flags & BPF_TRAMP_F_RESTORE_REGS)
restore_args(nregs, args_off, ctx); restore_args(nregs, args_off, ctx);
if (save_ret) if (save_ret) {
emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx); emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx);
emit_ld(regmap[BPF_REG_0], -(retval_off - 8), RV_REG_FP, ctx);
}
emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx); emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx);
...@@ -1515,7 +1520,8 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, ...@@ -1515,7 +1520,8 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
if (ret) if (ret)
return ret; return ret;
emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx); if (insn->src_reg != BPF_PSEUDO_CALL)
emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
break; break;
} }
/* tail call */ /* tail call */
......
...@@ -2066,6 +2066,7 @@ struct bpf_tramp_jit { ...@@ -2066,6 +2066,7 @@ struct bpf_tramp_jit {
* func_addr's original caller * func_addr's original caller
*/ */
int stack_size; /* Trampoline stack size */ int stack_size; /* Trampoline stack size */
int backchain_off; /* Offset of backchain */
int stack_args_off; /* Offset of stack arguments for calling int stack_args_off; /* Offset of stack arguments for calling
* func_addr, has to be at the top * func_addr, has to be at the top
*/ */
...@@ -2086,9 +2087,10 @@ struct bpf_tramp_jit { ...@@ -2086,9 +2087,10 @@ struct bpf_tramp_jit {
* for __bpf_prog_enter() return value and * for __bpf_prog_enter() return value and
* func_addr respectively * func_addr respectively
*/ */
int r14_off; /* Offset of saved %r14 */
int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */ int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */
int tccnt_off; /* Offset of saved tailcall counter */ int tccnt_off; /* Offset of saved tailcall counter */
int r14_off; /* Offset of saved %r14, has to be at the
* bottom */
int do_fexit; /* do_fexit: label */ int do_fexit; /* do_fexit: label */
}; };
...@@ -2247,8 +2249,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -2247,8 +2249,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
* Calculate the stack layout. * Calculate the stack layout.
*/ */
/* Reserve STACK_FRAME_OVERHEAD bytes for the callees. */ /*
* Allocate STACK_FRAME_OVERHEAD bytes for the callees. As the s390x
* ABI requires, put our backchain at the end of the allocated memory.
*/
tjit->stack_size = STACK_FRAME_OVERHEAD; tjit->stack_size = STACK_FRAME_OVERHEAD;
tjit->backchain_off = tjit->stack_size - sizeof(u64);
tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64)); tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64));
tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64)); tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64));
tjit->ip_off = alloc_stack(tjit, sizeof(u64)); tjit->ip_off = alloc_stack(tjit, sizeof(u64));
...@@ -2256,16 +2262,25 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -2256,16 +2262,25 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64)); tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64));
tjit->retval_off = alloc_stack(tjit, sizeof(u64)); tjit->retval_off = alloc_stack(tjit, sizeof(u64));
tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64)); tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64));
tjit->r14_off = alloc_stack(tjit, sizeof(u64));
tjit->run_ctx_off = alloc_stack(tjit, tjit->run_ctx_off = alloc_stack(tjit,
sizeof(struct bpf_tramp_run_ctx)); sizeof(struct bpf_tramp_run_ctx));
tjit->tccnt_off = alloc_stack(tjit, sizeof(u64)); tjit->tccnt_off = alloc_stack(tjit, sizeof(u64));
/* The caller has already reserved STACK_FRAME_OVERHEAD bytes. */ tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2);
tjit->stack_size -= STACK_FRAME_OVERHEAD; /*
* In accordance with the s390x ABI, the caller has allocated
* STACK_FRAME_OVERHEAD bytes for us. 8 of them contain the caller's
* backchain, and the rest we can use.
*/
tjit->stack_size -= STACK_FRAME_OVERHEAD - sizeof(u64);
tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD; tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD;
/* lgr %r1,%r15 */
EMIT4(0xb9040000, REG_1, REG_15);
/* aghi %r15,-stack_size */ /* aghi %r15,-stack_size */
EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size); EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size);
/* stg %r1,backchain_off(%r15) */
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15,
tjit->backchain_off);
/* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */
_EMIT6(0xd203f000 | tjit->tccnt_off, _EMIT6(0xd203f000 | tjit->tccnt_off,
0xf000 | (tjit->stack_size + STK_OFF_TCCNT)); 0xf000 | (tjit->stack_size + STK_OFF_TCCNT));
......
...@@ -401,14 +401,16 @@ int bpf_mprog_query(const union bpf_attr *attr, union bpf_attr __user *uattr, ...@@ -401,14 +401,16 @@ int bpf_mprog_query(const union bpf_attr *attr, union bpf_attr __user *uattr,
struct bpf_mprog_cp *cp; struct bpf_mprog_cp *cp;
struct bpf_prog *prog; struct bpf_prog *prog;
const u32 flags = 0; const u32 flags = 0;
u32 id, count = 0;
u64 revision = 1;
int i, ret = 0; int i, ret = 0;
u32 id, count;
u64 revision;
if (attr->query.query_flags || attr->query.attach_flags) if (attr->query.query_flags || attr->query.attach_flags)
return -EINVAL; return -EINVAL;
revision = bpf_mprog_revision(entry); if (entry) {
count = bpf_mprog_total(entry); revision = bpf_mprog_revision(entry);
count = bpf_mprog_total(entry);
}
if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
return -EFAULT; return -EFAULT;
if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision))) if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision)))
......
...@@ -3796,7 +3796,6 @@ static int bpf_prog_attach(const union bpf_attr *attr) ...@@ -3796,7 +3796,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
{ {
enum bpf_prog_type ptype; enum bpf_prog_type ptype;
struct bpf_prog *prog; struct bpf_prog *prog;
u32 mask;
int ret; int ret;
if (CHECK_ATTR(BPF_PROG_ATTACH)) if (CHECK_ATTR(BPF_PROG_ATTACH))
...@@ -3805,10 +3804,16 @@ static int bpf_prog_attach(const union bpf_attr *attr) ...@@ -3805,10 +3804,16 @@ static int bpf_prog_attach(const union bpf_attr *attr)
ptype = attach_type_to_prog_type(attr->attach_type); ptype = attach_type_to_prog_type(attr->attach_type);
if (ptype == BPF_PROG_TYPE_UNSPEC) if (ptype == BPF_PROG_TYPE_UNSPEC)
return -EINVAL; return -EINVAL;
mask = bpf_mprog_supported(ptype) ? if (bpf_mprog_supported(ptype)) {
BPF_F_ATTACH_MASK_MPROG : BPF_F_ATTACH_MASK_BASE; if (attr->attach_flags & ~BPF_F_ATTACH_MASK_MPROG)
if (attr->attach_flags & ~mask) return -EINVAL;
return -EINVAL; } else {
if (attr->attach_flags & ~BPF_F_ATTACH_MASK_BASE)
return -EINVAL;
if (attr->relative_fd ||
attr->expected_revision)
return -EINVAL;
}
prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
if (IS_ERR(prog)) if (IS_ERR(prog))
...@@ -3878,6 +3883,10 @@ static int bpf_prog_detach(const union bpf_attr *attr) ...@@ -3878,6 +3883,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
if (IS_ERR(prog)) if (IS_ERR(prog))
return PTR_ERR(prog); return PTR_ERR(prog);
} }
} else if (attr->attach_flags ||
attr->relative_fd ||
attr->expected_revision) {
return -EINVAL;
} }
switch (ptype) { switch (ptype) {
...@@ -3913,7 +3922,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) ...@@ -3913,7 +3922,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)
return ret; return ret;
} }
#define BPF_PROG_QUERY_LAST_FIELD query.link_attach_flags #define BPF_PROG_QUERY_LAST_FIELD query.revision
static int bpf_prog_query(const union bpf_attr *attr, static int bpf_prog_query(const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
......
...@@ -123,7 +123,6 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -123,7 +123,6 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
{ {
bool ingress = attr->query.attach_type == BPF_TCX_INGRESS; bool ingress = attr->query.attach_type == BPF_TCX_INGRESS;
struct net *net = current->nsproxy->net_ns; struct net *net = current->nsproxy->net_ns;
struct bpf_mprog_entry *entry;
struct net_device *dev; struct net_device *dev;
int ret; int ret;
...@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
entry = tcx_entry_fetch(dev, ingress); ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress));
if (!entry) {
ret = -ENOENT;
goto out;
}
ret = bpf_mprog_query(attr, uattr, entry);
out: out:
rtnl_unlock(); rtnl_unlock();
return ret; return ret;
......
...@@ -14479,7 +14479,7 @@ static int check_return_code(struct bpf_verifier_env *env) ...@@ -14479,7 +14479,7 @@ static int check_return_code(struct bpf_verifier_env *env)
struct tnum enforce_attach_type_range = tnum_unknown; struct tnum enforce_attach_type_range = tnum_unknown;
const struct bpf_prog *prog = env->prog; const struct bpf_prog *prog = env->prog;
struct bpf_reg_state *reg; struct bpf_reg_state *reg;
struct tnum range = tnum_range(0, 1); struct tnum range = tnum_range(0, 1), const_0 = tnum_const(0);
enum bpf_prog_type prog_type = resolve_prog_type(env->prog); enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
int err; int err;
struct bpf_func_state *frame = env->cur_state->frame[0]; struct bpf_func_state *frame = env->cur_state->frame[0];
...@@ -14527,8 +14527,8 @@ static int check_return_code(struct bpf_verifier_env *env) ...@@ -14527,8 +14527,8 @@ static int check_return_code(struct bpf_verifier_env *env)
return -EINVAL; return -EINVAL;
} }
if (!tnum_in(tnum_const(0), reg->var_off)) { if (!tnum_in(const_0, reg->var_off)) {
verbose_invalid_scalar(env, reg, &range, "async callback", "R0"); verbose_invalid_scalar(env, reg, &const_0, "async callback", "R0");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
......
...@@ -34,6 +34,16 @@ struct xsk_queue *xskq_create(u32 nentries, bool umem_queue) ...@@ -34,6 +34,16 @@ struct xsk_queue *xskq_create(u32 nentries, bool umem_queue)
q->ring_mask = nentries - 1; q->ring_mask = nentries - 1;
size = xskq_get_ring_size(q, umem_queue); size = xskq_get_ring_size(q, umem_queue);
/* size which is overflowing or close to SIZE_MAX will become 0 in
* PAGE_ALIGN(), checking SIZE_MAX is enough due to the previous
* is_power_of_2(), the rest will be handled by vmalloc_user()
*/
if (unlikely(size == SIZE_MAX)) {
kfree(q);
return NULL;
}
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
q->ring = vmalloc_user(size); q->ring = vmalloc_user(size);
......
...@@ -45,7 +45,7 @@ static inline __u32 ifindex_from_link_fd(int fd) ...@@ -45,7 +45,7 @@ static inline __u32 ifindex_from_link_fd(int fd)
return link_info.tcx.ifindex; return link_info.tcx.ifindex;
} }
static inline void __assert_mprog_count(int target, int expected, bool miniq, int ifindex) static inline void __assert_mprog_count(int target, int expected, int ifindex)
{ {
__u32 count = 0, attach_flags = 0; __u32 count = 0, attach_flags = 0;
int err; int err;
...@@ -53,20 +53,22 @@ static inline void __assert_mprog_count(int target, int expected, bool miniq, in ...@@ -53,20 +53,22 @@ static inline void __assert_mprog_count(int target, int expected, bool miniq, in
err = bpf_prog_query(ifindex, target, 0, &attach_flags, err = bpf_prog_query(ifindex, target, 0, &attach_flags,
NULL, &count); NULL, &count);
ASSERT_EQ(count, expected, "count"); ASSERT_EQ(count, expected, "count");
if (!expected && !miniq) ASSERT_EQ(err, 0, "prog_query");
ASSERT_EQ(err, -ENOENT, "prog_query");
else
ASSERT_EQ(err, 0, "prog_query");
} }
static inline void assert_mprog_count(int target, int expected) static inline void assert_mprog_count(int target, int expected)
{ {
__assert_mprog_count(target, expected, false, loopback); __assert_mprog_count(target, expected, loopback);
} }
static inline void assert_mprog_count_ifindex(int ifindex, int target, int expected) static inline void assert_mprog_count_ifindex(int ifindex, int target, int expected)
{ {
__assert_mprog_count(target, expected, false, ifindex); __assert_mprog_count(target, expected, ifindex);
}
static inline void tc_skel_reset_all_seen(struct test_tc_link *skel)
{
memset(skel->bss, 0, sizeof(*skel->bss));
} }
#endif /* TC_HELPERS */ #endif /* TC_HELPERS */
...@@ -65,6 +65,7 @@ void serial_test_tc_links_basic(void) ...@@ -65,6 +65,7 @@ void serial_test_tc_links_basic(void)
ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -97,6 +98,7 @@ void serial_test_tc_links_basic(void) ...@@ -97,6 +98,7 @@ void serial_test_tc_links_basic(void)
ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -187,6 +189,7 @@ static void test_tc_links_before_target(int target) ...@@ -187,6 +189,7 @@ static void test_tc_links_before_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -194,9 +197,6 @@ static void test_tc_links_before_target(int target) ...@@ -194,9 +197,6 @@ static void test_tc_links_before_target(int target)
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
LIBBPF_OPTS_RESET(optl, LIBBPF_OPTS_RESET(optl,
.flags = BPF_F_BEFORE, .flags = BPF_F_BEFORE,
.relative_fd = bpf_program__fd(skel->progs.tc2), .relative_fd = bpf_program__fd(skel->progs.tc2),
...@@ -246,6 +246,7 @@ static void test_tc_links_before_target(int target) ...@@ -246,6 +246,7 @@ static void test_tc_links_before_target(int target)
ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -342,6 +343,7 @@ static void test_tc_links_after_target(int target) ...@@ -342,6 +343,7 @@ static void test_tc_links_after_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -349,9 +351,6 @@ static void test_tc_links_after_target(int target) ...@@ -349,9 +351,6 @@ static void test_tc_links_after_target(int target)
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
LIBBPF_OPTS_RESET(optl, LIBBPF_OPTS_RESET(optl,
.flags = BPF_F_AFTER, .flags = BPF_F_AFTER,
.relative_fd = bpf_program__fd(skel->progs.tc1), .relative_fd = bpf_program__fd(skel->progs.tc1),
...@@ -401,6 +400,7 @@ static void test_tc_links_after_target(int target) ...@@ -401,6 +400,7 @@ static void test_tc_links_after_target(int target)
ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -502,6 +502,7 @@ static void test_tc_links_revision_target(int target) ...@@ -502,6 +502,7 @@ static void test_tc_links_revision_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "prog_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -581,22 +582,20 @@ static void test_tc_chain_classic(int target, bool chain_tc_old) ...@@ -581,22 +582,20 @@ static void test_tc_chain_classic(int target, bool chain_tc_old)
assert_mprog_count(target, 2); assert_mprog_count(target, 2);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
skel->bss->seen_tc3 = false;
err = bpf_link__detach(skel->links.tc2); err = bpf_link__detach(skel->links.tc2);
if (!ASSERT_OK(err, "prog_detach")) if (!ASSERT_OK(err, "prog_detach"))
goto cleanup; goto cleanup;
assert_mprog_count(target, 1); assert_mprog_count(target, 1);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -707,16 +706,13 @@ static void test_tc_links_replace_target(int target) ...@@ -707,16 +706,13 @@ static void test_tc_links_replace_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
skel->bss->seen_tc3 = false;
LIBBPF_OPTS_RESET(optl, LIBBPF_OPTS_RESET(optl,
.flags = BPF_F_REPLACE, .flags = BPF_F_REPLACE,
.relative_fd = bpf_program__fd(skel->progs.tc2), .relative_fd = bpf_program__fd(skel->progs.tc2),
...@@ -781,16 +777,13 @@ static void test_tc_links_replace_target(int target) ...@@ -781,16 +777,13 @@ static void test_tc_links_replace_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
skel->bss->seen_tc3 = false;
err = bpf_link__detach(skel->links.tc2); err = bpf_link__detach(skel->links.tc2);
if (!ASSERT_OK(err, "link_detach")) if (!ASSERT_OK(err, "link_detach"))
goto cleanup; goto cleanup;
...@@ -812,16 +805,13 @@ static void test_tc_links_replace_target(int target) ...@@ -812,16 +805,13 @@ static void test_tc_links_replace_target(int target)
ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
skel->bss->seen_tc3 = false;
err = bpf_link__update_program(skel->links.tc1, skel->progs.tc1); err = bpf_link__update_program(skel->links.tc1, skel->progs.tc1);
if (!ASSERT_OK(err, "link_update_self")) if (!ASSERT_OK(err, "link_update_self"))
goto cleanup; goto cleanup;
...@@ -843,6 +833,7 @@ static void test_tc_links_replace_target(int target) ...@@ -843,6 +833,7 @@ static void test_tc_links_replace_target(int target)
ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -1254,6 +1245,7 @@ static void test_tc_links_prepend_target(int target) ...@@ -1254,6 +1245,7 @@ static void test_tc_links_prepend_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -1261,9 +1253,6 @@ static void test_tc_links_prepend_target(int target) ...@@ -1261,9 +1253,6 @@ static void test_tc_links_prepend_target(int target)
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
LIBBPF_OPTS_RESET(optl, LIBBPF_OPTS_RESET(optl,
.flags = BPF_F_BEFORE, .flags = BPF_F_BEFORE,
); );
...@@ -1311,6 +1300,7 @@ static void test_tc_links_prepend_target(int target) ...@@ -1311,6 +1300,7 @@ static void test_tc_links_prepend_target(int target)
ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -1411,6 +1401,7 @@ static void test_tc_links_append_target(int target) ...@@ -1411,6 +1401,7 @@ static void test_tc_links_append_target(int target)
ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -1418,9 +1409,6 @@ static void test_tc_links_append_target(int target) ...@@ -1418,9 +1409,6 @@ static void test_tc_links_append_target(int target)
ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
LIBBPF_OPTS_RESET(optl, LIBBPF_OPTS_RESET(optl,
.flags = BPF_F_AFTER, .flags = BPF_F_AFTER,
); );
...@@ -1468,6 +1456,7 @@ static void test_tc_links_append_target(int target) ...@@ -1468,6 +1456,7 @@ static void test_tc_links_append_target(int target)
ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]");
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
...@@ -1637,38 +1626,33 @@ static void test_tc_chain_mixed(int target) ...@@ -1637,38 +1626,33 @@ static void test_tc_chain_mixed(int target)
assert_mprog_count(target, 1); assert_mprog_count(target, 1);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5");
ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6"); ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6");
skel->bss->seen_tc4 = false;
skel->bss->seen_tc5 = false;
skel->bss->seen_tc6 = false;
err = bpf_link__update_program(skel->links.tc6, skel->progs.tc4); err = bpf_link__update_program(skel->links.tc6, skel->progs.tc4);
if (!ASSERT_OK(err, "link_update")) if (!ASSERT_OK(err, "link_update"))
goto cleanup; goto cleanup;
assert_mprog_count(target, 1); assert_mprog_count(target, 1);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5");
ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6"); ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6");
skel->bss->seen_tc4 = false;
skel->bss->seen_tc5 = false;
skel->bss->seen_tc6 = false;
err = bpf_link__detach(skel->links.tc6); err = bpf_link__detach(skel->links.tc6);
if (!ASSERT_OK(err, "prog_detach")) if (!ASSERT_OK(err, "prog_detach"))
goto cleanup; goto cleanup;
__assert_mprog_count(target, 0, true, loopback); assert_mprog_count(target, 0);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
...@@ -1758,22 +1742,20 @@ static void test_tc_links_ingress(int target, bool chain_tc_old, ...@@ -1758,22 +1742,20 @@ static void test_tc_links_ingress(int target, bool chain_tc_old,
assert_mprog_count(target, 2); assert_mprog_count(target, 2);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3");
skel->bss->seen_tc1 = false;
skel->bss->seen_tc2 = false;
skel->bss->seen_tc3 = false;
err = bpf_link__detach(skel->links.tc2); err = bpf_link__detach(skel->links.tc2);
if (!ASSERT_OK(err, "prog_detach")) if (!ASSERT_OK(err, "prog_detach"))
goto cleanup; goto cleanup;
assert_mprog_count(target, 1); assert_mprog_count(target, 1);
tc_skel_reset_all_seen(skel);
ASSERT_OK(system(ping_cmd), ping_cmd); ASSERT_OK(system(ping_cmd), ping_cmd);
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2021 Facebook */ /* Copyright (c) 2021 Facebook */
#include <test_progs.h> #include <test_progs.h>
#include "timer.skel.h" #include "timer.skel.h"
#include "timer_failure.skel.h"
static int timer(struct timer *timer_skel) static int timer(struct timer *timer_skel)
{ {
...@@ -49,10 +50,11 @@ void serial_test_timer(void) ...@@ -49,10 +50,11 @@ void serial_test_timer(void)
timer_skel = timer__open_and_load(); timer_skel = timer__open_and_load();
if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load"))
goto cleanup; return;
err = timer(timer_skel); err = timer(timer_skel);
ASSERT_OK(err, "timer"); ASSERT_OK(err, "timer");
cleanup:
timer__destroy(timer_skel); timer__destroy(timer_skel);
RUN_TESTS(timer_failure);
} }
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include <linux/bpf.h>
#include <time.h>
#include <errno.h>
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"
#include "bpf_tcp_helpers.h"
char _license[] SEC("license") = "GPL";
struct elem {
struct bpf_timer t;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, struct elem);
} timer_map SEC(".maps");
static int timer_cb_ret1(void *map, int *key, struct bpf_timer *timer)
{
if (bpf_get_smp_processor_id() % 2)
return 1;
else
return 0;
}
SEC("fentry/bpf_fentry_test1")
__failure __msg("should have been in (0x0; 0x0)")
int BPF_PROG2(test_ret_1, int, a)
{
int key = 0;
struct bpf_timer *timer;
timer = bpf_map_lookup_elem(&timer_map, &key);
if (timer) {
bpf_timer_init(timer, &timer_map, CLOCK_BOOTTIME);
bpf_timer_set_callback(timer, timer_cb_ret1);
bpf_timer_start(timer, 1000, 0);
}
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment