Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add a test to verify previous stacksafe() fix

A selftest is added such that without the previous patch,
a crash can happen. With the previous patch, the test can
run successfully. The new test is written in a way which
mimics original crash case:
main_prog
static_prog_1
static_prog_2
where static_prog_1 has different paths to static_prog_2
and some path has stack allocated and some other path
does not. A stacksafe() checking in static_prog_2()
triggered the crash.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20240812214852.214037-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yonghong Song and committed by
Alexei Starovoitov
662c3e2d bed2eb96

+54
+54
tools/testing/selftests/bpf/progs/iters.c
··· 1432 1432 return sum; 1433 1433 } 1434 1434 1435 + __u32 upper, select_n, result; 1436 + __u64 global; 1437 + 1438 + static __noinline bool nest_2(char *str) 1439 + { 1440 + /* some insns (including branch insns) to ensure stacksafe() is triggered 1441 + * in nest_2(). This way, stacksafe() can compare frame associated with nest_1(). 1442 + */ 1443 + if (str[0] == 't') 1444 + return true; 1445 + if (str[1] == 'e') 1446 + return true; 1447 + if (str[2] == 's') 1448 + return true; 1449 + if (str[3] == 't') 1450 + return true; 1451 + return false; 1452 + } 1453 + 1454 + static __noinline bool nest_1(int n) 1455 + { 1456 + /* case 0: allocate stack, case 1: no allocate stack */ 1457 + switch (n) { 1458 + case 0: { 1459 + char comm[16]; 1460 + 1461 + if (bpf_get_current_comm(comm, 16)) 1462 + return false; 1463 + return nest_2(comm); 1464 + } 1465 + case 1: 1466 + return nest_2((char *)&global); 1467 + default: 1468 + return false; 1469 + } 1470 + } 1471 + 1472 + SEC("raw_tp") 1473 + __success 1474 + int iter_subprog_check_stacksafe(const void *ctx) 1475 + { 1476 + long i; 1477 + 1478 + bpf_for(i, 0, upper) { 1479 + if (!nest_1(select_n)) { 1480 + result = 1; 1481 + return 0; 1482 + } 1483 + } 1484 + 1485 + result = 2; 1486 + return 0; 1487 + } 1488 + 1435 1489 char _license[] SEC("license") = "GPL";