Skip to content

Commit f0a5056

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
selftests/bpf: add freplace of BTF-unreliable main prog test
Add a test validating that freplace'ing another main (entry) BPF program fails if the target BPF program doesn't have valid/expected func proto BTF. We extend fexit_bpf2bpf test to allow to specify expected log message for negative test cases (where freplace program is expected to fail to load). Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 0a0ffca commit f0a5056

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,14 +348,16 @@ static void test_func_sockmap_update(void)
348348
}
349349

350350
static void test_obj_load_failure_common(const char *obj_file,
351-
const char *target_obj_file)
351+
const char *target_obj_file,
352+
const char *exp_msg)
352353
{
353354
/*
354355
* standalone test that asserts failure to load freplace prog
355356
* because of invalid return code.
356357
*/
357358
struct bpf_object *obj = NULL, *pkt_obj;
358359
struct bpf_program *prog;
360+
char log_buf[64 * 1024];
359361
int err, pkt_fd;
360362
__u32 duration = 0;
361363

@@ -374,11 +376,21 @@ static void test_obj_load_failure_common(const char *obj_file,
374376
err = bpf_program__set_attach_target(prog, pkt_fd, NULL);
375377
ASSERT_OK(err, "set_attach_target");
376378

379+
log_buf[0] = '\0';
380+
if (exp_msg)
381+
bpf_program__set_log_buf(prog, log_buf, sizeof(log_buf));
382+
if (env.verbosity > VERBOSE_NONE)
383+
bpf_program__set_log_level(prog, 2);
384+
377385
/* It should fail to load the program */
378386
err = bpf_object__load(obj);
387+
if (env.verbosity > VERBOSE_NONE && exp_msg) /* we overtook log */
388+
printf("VERIFIER LOG:\n================\n%s\n================\n", log_buf);
379389
if (CHECK(!err, "bpf_obj_load should fail", "err %d\n", err))
380390
goto close_prog;
381391

392+
if (exp_msg)
393+
ASSERT_HAS_SUBSTR(log_buf, exp_msg, "fail_msg");
382394
close_prog:
383395
bpf_object__close(obj);
384396
bpf_object__close(pkt_obj);
@@ -388,14 +400,24 @@ static void test_func_replace_return_code(void)
388400
{
389401
/* test invalid return code in the replaced program */
390402
test_obj_load_failure_common("./freplace_connect_v4_prog.bpf.o",
391-
"./connect4_prog.bpf.o");
403+
"./connect4_prog.bpf.o", NULL);
392404
}
393405

394406
static void test_func_map_prog_compatibility(void)
395407
{
396408
/* test with spin lock map value in the replaced program */
397409
test_obj_load_failure_common("./freplace_attach_probe.bpf.o",
398-
"./test_attach_probe.bpf.o");
410+
"./test_attach_probe.bpf.o", NULL);
411+
}
412+
413+
static void test_func_replace_unreliable(void)
414+
{
415+
/* freplace'ing unreliable main prog should fail with error
416+
* "Cannot replace static functions"
417+
*/
418+
test_obj_load_failure_common("freplace_unreliable_prog.bpf.o",
419+
"./verifier_btf_unreliable_prog.bpf.o",
420+
"Cannot replace static functions");
399421
}
400422

401423
static void test_func_replace_global_func(void)
@@ -563,6 +585,8 @@ void serial_test_fexit_bpf2bpf(void)
563585
test_func_replace_return_code();
564586
if (test__start_subtest("func_map_prog_compatibility"))
565587
test_func_map_prog_compatibility();
588+
if (test__start_subtest("func_replace_unreliable"))
589+
test_func_replace_unreliable();
566590
if (test__start_subtest("func_replace_multi"))
567591
test_func_replace_multi();
568592
if (test__start_subtest("fmod_ret_freplace"))

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "verifier_bpf_get_stack.skel.h"
1515
#include "verifier_bswap.skel.h"
1616
#include "verifier_btf_ctx_access.skel.h"
17+
#include "verifier_btf_unreliable_prog.skel.h"
1718
#include "verifier_cfg.skel.h"
1819
#include "verifier_cgroup_inv_retcode.skel.h"
1920
#include "verifier_cgroup_skb.skel.h"
@@ -125,6 +126,7 @@ void test_verifier_bounds_mix_sign_unsign(void) { RUN(verifier_bounds_mix_sign_u
125126
void test_verifier_bpf_get_stack(void) { RUN(verifier_bpf_get_stack); }
126127
void test_verifier_bswap(void) { RUN(verifier_bswap); }
127128
void test_verifier_btf_ctx_access(void) { RUN(verifier_btf_ctx_access); }
129+
void test_verifier_btf_unreliable_prog(void) { RUN(verifier_btf_unreliable_prog); }
128130
void test_verifier_cfg(void) { RUN(verifier_cfg); }
129131
void test_verifier_cgroup_inv_retcode(void) { RUN(verifier_cgroup_inv_retcode); }
130132
void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2020 Facebook
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
8+
SEC("freplace/btf_unreliable_kprobe")
9+
/* context type is what BPF verifier expects for kprobe context, but target
10+
* program has `stuct whatever *ctx` argument, so freplace operation will be
11+
* rejected with the following message:
12+
*
13+
* arg0 replace_btf_unreliable_kprobe(struct pt_regs *) doesn't match btf_unreliable_kprobe(struct whatever *)
14+
*/
15+
int replace_btf_unreliable_kprobe(bpf_user_pt_regs_t *ctx)
16+
{
17+
return 0;
18+
}
19+
20+
char _license[] SEC("license") = "GPL";
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2017 Facebook
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
#include <bpf/bpf_core_read.h>
8+
#include "bpf_misc.h"
9+
10+
struct whatever {};
11+
12+
SEC("kprobe")
13+
__success __log_level(2)
14+
/* context type is wrong, making it impossible to freplace this program */
15+
int btf_unreliable_kprobe(struct whatever *ctx)
16+
{
17+
return 0;
18+
}
19+
20+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)