Commit d3eee81f authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Daniel Borkmann says:

====================
pull-request: bpf 2024-03-06

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

The main changes are:

1) Fix BPF verifier to check bpf_func_state->callback_depth when pruning
   states as otherwise unsafe programs could get accepted,
   from Eduard Zingerman.

2) Fix to zero-initialise xdp_rxq_info struct before running XDP program in
   CPU map which led to random xdp_md fields, from Toke Høiland-Jørgensen.

3) Fix bonding XDP feature flags calculation when bonding device has no
   slave devices anymore, from Daniel Borkmann.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  cpumap: Zero-initialise xdp_rxq_info struct before running XDP program
  selftests/bpf: Fix up xdp bonding test wrt feature flags
  xdp, bonding: Fix feature flags when there are no slave devs anymore
  selftests/bpf: test case for callback_depth states pruning logic
  bpf: check bpf_func_state->callback_depth when pruning states
====================

Link: https://lore.kernel.org/r/20240306220309.13534-1-daniel@iogearbox.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c055fc00 2487007a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1811,7 +1811,7 @@ void bond_xdp_set_features(struct net_device *bond_dev)

	ASSERT_RTNL();

	if (!bond_xdp_check(bond)) {
	if (!bond_xdp_check(bond) || !bond_has_slaves(bond)) {
		xdp_clear_features_flag(bond_dev);
		return;
	}
+1 −1
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
				    void **frames, int n,
				    struct xdp_cpumap_stats *stats)
{
	struct xdp_rxq_info rxq;
	struct xdp_rxq_info rxq = {};
	struct xdp_buff xdp;
	int i, nframes = 0;

+3 −0
Original line number Diff line number Diff line
@@ -16602,6 +16602,9 @@ static bool func_states_equal(struct bpf_verifier_env *env, struct bpf_func_stat
{
	int i;
	if (old->callback_depth > cur->callback_depth)
		return false;
	for (i = 0; i < MAX_BPF_REG; i++)
		if (!regsafe(env, &old->regs[i], &cur->regs[i],
			     &env->idmap_scratch, exact))
+2 −2
Original line number Diff line number Diff line
@@ -511,7 +511,7 @@ static void test_xdp_bonding_features(struct skeletons *skeletons)
	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
		goto out;

	if (!ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
	if (!ASSERT_EQ(query_opts.feature_flags, 0,
		       "bond query_opts.feature_flags"))
		goto out;

@@ -601,7 +601,7 @@ static void test_xdp_bonding_features(struct skeletons *skeletons)
	if (!ASSERT_OK(err, "bond bpf_xdp_query"))
		goto out;

	ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
	ASSERT_EQ(query_opts.feature_flags, 0,
		  "bond query_opts.feature_flags");
out:
	bpf_link__destroy(link);
+70 −0
Original line number Diff line number Diff line
@@ -239,4 +239,74 @@ int bpf_loop_iter_limit_nested(void *unused)
	return 1000 * a + b + c;
}

struct iter_limit_bug_ctx {
	__u64 a;
	__u64 b;
	__u64 c;
};

static __naked void iter_limit_bug_cb(void)
{
	/* This is the same as C code below, but written
	 * in assembly to control which branches are fall-through.
	 *
	 *   switch (bpf_get_prandom_u32()) {
	 *   case 1:  ctx->a = 42; break;
	 *   case 2:  ctx->b = 42; break;
	 *   default: ctx->c = 42; break;
	 *   }
	 */
	asm volatile (
	"r9 = r2;"
	"call %[bpf_get_prandom_u32];"
	"r1 = r0;"
	"r2 = 42;"
	"r0 = 0;"
	"if r1 == 0x1 goto 1f;"
	"if r1 == 0x2 goto 2f;"
	"*(u64 *)(r9 + 16) = r2;"
	"exit;"
	"1: *(u64 *)(r9 + 0) = r2;"
	"exit;"
	"2: *(u64 *)(r9 + 8) = r2;"
	"exit;"
	:
	: __imm(bpf_get_prandom_u32)
	: __clobber_all
	);
}

SEC("tc")
__failure
__flag(BPF_F_TEST_STATE_FREQ)
int iter_limit_bug(struct __sk_buff *skb)
{
	struct iter_limit_bug_ctx ctx = { 7, 7, 7 };

	bpf_loop(2, iter_limit_bug_cb, &ctx, 0);

	/* This is the same as C code below,
	 * written in assembly to guarantee checks order.
	 *
	 *   if (ctx.a == 42 && ctx.b == 42 && ctx.c == 7)
	 *     asm volatile("r1 /= 0;":::"r1");
	 */
	asm volatile (
	"r1 = *(u64 *)%[ctx_a];"
	"if r1 != 42 goto 1f;"
	"r1 = *(u64 *)%[ctx_b];"
	"if r1 != 42 goto 1f;"
	"r1 = *(u64 *)%[ctx_c];"
	"if r1 != 7 goto 1f;"
	"r1 /= 0;"
	"1:"
	:
	: [ctx_a]"m"(ctx.a),
	  [ctx_b]"m"(ctx.b),
	  [ctx_c]"m"(ctx.c)
	: "r1"
	);
	return 0;
}

char _license[] SEC("license") = "GPL";