Skip to content

Commit d3eee81

Browse files
committed
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: Jakub Kicinski <kuba@kernel.org>
2 parents c055fc0 + 2487007 commit d3eee81

5 files changed

Lines changed: 77 additions & 4 deletions

File tree

drivers/net/bonding/bond_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1811,7 +1811,7 @@ void bond_xdp_set_features(struct net_device *bond_dev)
18111811

18121812
ASSERT_RTNL();
18131813

1814-
if (!bond_xdp_check(bond)) {
1814+
if (!bond_xdp_check(bond) || !bond_has_slaves(bond)) {
18151815
xdp_clear_features_flag(bond_dev);
18161816
return;
18171817
}

kernel/bpf/cpumap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
178178
void **frames, int n,
179179
struct xdp_cpumap_stats *stats)
180180
{
181-
struct xdp_rxq_info rxq;
181+
struct xdp_rxq_info rxq = {};
182182
struct xdp_buff xdp;
183183
int i, nframes = 0;
184184

kernel/bpf/verifier.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16602,6 +16602,9 @@ static bool func_states_equal(struct bpf_verifier_env *env, struct bpf_func_stat
1660216602
{
1660316603
int i;
1660416604

16605+
if (old->callback_depth > cur->callback_depth)
16606+
return false;
16607+
1660516608
for (i = 0; i < MAX_BPF_REG; i++)
1660616609
if (!regsafe(env, &old->regs[i], &cur->regs[i],
1660716610
&env->idmap_scratch, exact))

tools/testing/selftests/bpf/prog_tests/xdp_bonding.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ static void test_xdp_bonding_features(struct skeletons *skeletons)
511511
if (!ASSERT_OK(err, "bond bpf_xdp_query"))
512512
goto out;
513513

514-
if (!ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
514+
if (!ASSERT_EQ(query_opts.feature_flags, 0,
515515
"bond query_opts.feature_flags"))
516516
goto out;
517517

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

604-
ASSERT_EQ(query_opts.feature_flags, NETDEV_XDP_ACT_MASK,
604+
ASSERT_EQ(query_opts.feature_flags, 0,
605605
"bond query_opts.feature_flags");
606606
out:
607607
bpf_link__destroy(link);

tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,74 @@ int bpf_loop_iter_limit_nested(void *unused)
239239
return 1000 * a + b + c;
240240
}
241241

242+
struct iter_limit_bug_ctx {
243+
__u64 a;
244+
__u64 b;
245+
__u64 c;
246+
};
247+
248+
static __naked void iter_limit_bug_cb(void)
249+
{
250+
/* This is the same as C code below, but written
251+
* in assembly to control which branches are fall-through.
252+
*
253+
* switch (bpf_get_prandom_u32()) {
254+
* case 1: ctx->a = 42; break;
255+
* case 2: ctx->b = 42; break;
256+
* default: ctx->c = 42; break;
257+
* }
258+
*/
259+
asm volatile (
260+
"r9 = r2;"
261+
"call %[bpf_get_prandom_u32];"
262+
"r1 = r0;"
263+
"r2 = 42;"
264+
"r0 = 0;"
265+
"if r1 == 0x1 goto 1f;"
266+
"if r1 == 0x2 goto 2f;"
267+
"*(u64 *)(r9 + 16) = r2;"
268+
"exit;"
269+
"1: *(u64 *)(r9 + 0) = r2;"
270+
"exit;"
271+
"2: *(u64 *)(r9 + 8) = r2;"
272+
"exit;"
273+
:
274+
: __imm(bpf_get_prandom_u32)
275+
: __clobber_all
276+
);
277+
}
278+
279+
SEC("tc")
280+
__failure
281+
__flag(BPF_F_TEST_STATE_FREQ)
282+
int iter_limit_bug(struct __sk_buff *skb)
283+
{
284+
struct iter_limit_bug_ctx ctx = { 7, 7, 7 };
285+
286+
bpf_loop(2, iter_limit_bug_cb, &ctx, 0);
287+
288+
/* This is the same as C code below,
289+
* written in assembly to guarantee checks order.
290+
*
291+
* if (ctx.a == 42 && ctx.b == 42 && ctx.c == 7)
292+
* asm volatile("r1 /= 0;":::"r1");
293+
*/
294+
asm volatile (
295+
"r1 = *(u64 *)%[ctx_a];"
296+
"if r1 != 42 goto 1f;"
297+
"r1 = *(u64 *)%[ctx_b];"
298+
"if r1 != 42 goto 1f;"
299+
"r1 = *(u64 *)%[ctx_c];"
300+
"if r1 != 7 goto 1f;"
301+
"r1 /= 0;"
302+
"1:"
303+
:
304+
: [ctx_a]"m"(ctx.a),
305+
[ctx_b]"m"(ctx.b),
306+
[ctx_c]"m"(ctx.c)
307+
: "r1"
308+
);
309+
return 0;
310+
}
311+
242312
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)