Commit ad98426a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
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.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 108a36d0 5356ba1f
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -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);
	/* Set return value. */
	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,
		  is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */
		  ctx);
@@ -759,8 +759,10 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
	if (ret)
		return ret;

	if (save_ret)
		emit_sd(RV_REG_FP, -retval_off, regmap[BPF_REG_0], ctx);
	if (save_ret) {
		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 */
	if (ctx->insns) {
@@ -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);
	if (save_ret) {
		stack_size += 8;
		stack_size += 16; /* Save both A5 (BPF R0) and A0 */
		retval_off = stack_size;
	}

@@ -957,6 +959,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
		if (ret)
			goto out;
		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;
		/* 2 nops reserved for auipc+jalr pair */
		emit(rv_nop(), ctx);
@@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
	if (flags & BPF_TRAMP_F_RESTORE_REGS)
		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(regmap[BPF_REG_0], -(retval_off - 8), RV_REG_FP, ctx);
	}

	emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx);

@@ -1515,6 +1520,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
		if (ret)
			return ret;

		if (insn->src_reg != BPF_PSEUDO_CALL)
			emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
		break;
	}
+20 −5
Original line number Diff line number Diff line
@@ -2066,6 +2066,7 @@ struct bpf_tramp_jit {
				 * func_addr's original caller
				 */
	int stack_size;		/* Trampoline stack size */
	int backchain_off;	/* Offset of backchain */
	int stack_args_off;	/* Offset of stack arguments for calling
				 * func_addr, has to be at the top
				 */
@@ -2086,9 +2087,10 @@ struct bpf_tramp_jit {
				 * for __bpf_prog_enter() return value and
				 * func_addr respectively
				 */
	int r14_off;		/* Offset of saved %r14 */
	int run_ctx_off;	/* Offset of struct bpf_tramp_run_ctx */
	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 */
};

@@ -2247,8 +2249,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
	 * 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->backchain_off = tjit->stack_size - 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->ip_off = alloc_stack(tjit, sizeof(u64));
@@ -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->retval_off = alloc_stack(tjit, 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,
					sizeof(struct bpf_tramp_run_ctx));
	tjit->tccnt_off = alloc_stack(tjit, sizeof(u64));
	/* The caller has already reserved STACK_FRAME_OVERHEAD bytes. */
	tjit->stack_size -= STACK_FRAME_OVERHEAD;
	tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2);
	/*
	 * 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;

	/* lgr %r1,%r15 */
	EMIT4(0xb9040000, REG_1, REG_15);
	/* aghi %r15,-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) */
	_EMIT6(0xd203f000 | tjit->tccnt_off,
	       0xf000 | (tjit->stack_size + STK_OFF_TCCNT));
+6 −4
Original line number Diff line number Diff line
@@ -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_prog *prog;
	const u32 flags = 0;
	u32 id, count = 0;
	u64 revision = 1;
	int i, ret = 0;
	u32 id, count;
	u64 revision;

	if (attr->query.query_flags || attr->query.attach_flags)
		return -EINVAL;
	if (entry) {
		revision = bpf_mprog_revision(entry);
		count = bpf_mprog_total(entry);
	}
	if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
		return -EFAULT;
	if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision)))
+15 −6
Original line number Diff line number Diff line
@@ -3796,7 +3796,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
{
	enum bpf_prog_type ptype;
	struct bpf_prog *prog;
	u32 mask;
	int ret;

	if (CHECK_ATTR(BPF_PROG_ATTACH))
@@ -3805,10 +3804,16 @@ static int bpf_prog_attach(const union bpf_attr *attr)
	ptype = attach_type_to_prog_type(attr->attach_type);
	if (ptype == BPF_PROG_TYPE_UNSPEC)
		return -EINVAL;
	mask = bpf_mprog_supported(ptype) ?
	       BPF_F_ATTACH_MASK_MPROG : BPF_F_ATTACH_MASK_BASE;
	if (attr->attach_flags & ~mask)
	if (bpf_mprog_supported(ptype)) {
		if (attr->attach_flags & ~BPF_F_ATTACH_MASK_MPROG)
			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);
	if (IS_ERR(prog))
@@ -3878,6 +3883,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
			if (IS_ERR(prog))
				return PTR_ERR(prog);
		}
	} else if (attr->attach_flags ||
		   attr->relative_fd ||
		   attr->expected_revision) {
		return -EINVAL;
	}

	switch (ptype) {
@@ -3913,7 +3922,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)
	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,
			  union bpf_attr __user *uattr)
+1 −7
Original line number Diff line number Diff line
@@ -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;
	struct net *net = current->nsproxy->net_ns;
	struct bpf_mprog_entry *entry;
	struct net_device *dev;
	int ret;

@@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
		ret = -ENODEV;
		goto out;
	}
	entry = tcx_entry_fetch(dev, ingress);
	if (!entry) {
		ret = -ENOENT;
		goto out;
	}
	ret = bpf_mprog_query(attr, uattr, entry);
	ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress));
out:
	rtnl_unlock();
	return ret;
Loading