Commit 5c5371e0 authored by Dmitrii Dolgov's avatar Dmitrii Dolgov Committed by Alexei Starovoitov

selftests/bpf: Add test for recursive attachment of tracing progs

Verify the fact that only one fentry prog could be attached to another
fentry, building up an attachment chain of limited size. Use existing
bpf_testmod as a start of the chain.
Acked-by: default avatarJiri Olsa <olsajiri@gmail.com>
Acked-by: default avatarSong Liu <song@kernel.org>
Signed-off-by: default avatarDmitrii Dolgov <9erthalion6@gmail.com>
Link: https://lore.kernel.org/r/20240103190559.14750-3-9erthalion6@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 19bfcdf9
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Red Hat, Inc. */
#include <test_progs.h>
#include "fentry_recursive.skel.h"
#include "fentry_recursive_target.skel.h"
#include <bpf/btf.h>
#include "bpf/libbpf_internal.h"
/* Test recursive attachment of tracing progs with more than one nesting level
* is not possible. Create a chain of attachment, verify that the last prog
* will fail. Depending on the arguments, following cases are tested:
*
* - Recursive loading of tracing progs, without attaching (attach = false,
* detach = false). The chain looks like this:
* load target
* load fentry1 -> target
* load fentry2 -> fentry1 (fail)
*
* - Recursive attach of tracing progs (attach = true, detach = false). The
* chain looks like this:
* load target
* load fentry1 -> target
* attach fentry1 -> target
* load fentry2 -> fentry1 (fail)
*
* - Recursive attach and detach of tracing progs (attach = true, detach =
* true). This validates that attach_tracing_prog flag will be set throughout
* the whole lifecycle of an fentry prog, independently from whether it's
* detached. The chain looks like this:
* load target
* load fentry1 -> target
* attach fentry1 -> target
* detach fentry1
* load fentry2 -> fentry1 (fail)
*/
static void test_recursive_fentry_chain(bool attach, bool detach)
{
struct fentry_recursive_target *target_skel = NULL;
struct fentry_recursive *tracing_chain[2] = {};
struct bpf_program *prog;
int prev_fd, err;
target_skel = fentry_recursive_target__open_and_load();
if (!ASSERT_OK_PTR(target_skel, "fentry_recursive_target__open_and_load"))
return;
/* Create an attachment chain with two fentry progs */
for (int i = 0; i < 2; i++) {
tracing_chain[i] = fentry_recursive__open();
if (!ASSERT_OK_PTR(tracing_chain[i], "fentry_recursive__open"))
goto close_prog;
/* The first prog in the chain is going to be attached to the target
* fentry program, the second one to the previous in the chain.
*/
prog = tracing_chain[i]->progs.recursive_attach;
if (i == 0) {
prev_fd = bpf_program__fd(target_skel->progs.test1);
err = bpf_program__set_attach_target(prog, prev_fd, "test1");
} else {
prev_fd = bpf_program__fd(tracing_chain[i-1]->progs.recursive_attach);
err = bpf_program__set_attach_target(prog, prev_fd, "recursive_attach");
}
if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
goto close_prog;
err = fentry_recursive__load(tracing_chain[i]);
/* The first attach should succeed, the second fail */
if (i == 0) {
if (!ASSERT_OK(err, "fentry_recursive__load"))
goto close_prog;
if (attach) {
err = fentry_recursive__attach(tracing_chain[i]);
if (!ASSERT_OK(err, "fentry_recursive__attach"))
goto close_prog;
}
if (detach) {
/* Flag attach_tracing_prog should still be set, preventing
* attachment of the following prog.
*/
fentry_recursive__detach(tracing_chain[i]);
}
} else {
if (!ASSERT_ERR(err, "fentry_recursive__load"))
goto close_prog;
}
}
close_prog:
fentry_recursive_target__destroy(target_skel);
for (int i = 0; i < 2; i++) {
fentry_recursive__destroy(tracing_chain[i]);
}
}
void test_recursive_fentry(void)
{
if (test__start_subtest("attach"))
test_recursive_fentry_chain(true, false);
if (test__start_subtest("load"))
test_recursive_fentry_chain(false, false);
if (test__start_subtest("detach"))
test_recursive_fentry_chain(true, true);
}
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Red Hat, Inc. */
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char _license[] SEC("license") = "GPL";
/* Dummy fentry bpf prog for testing fentry attachment chains */
SEC("fentry/XXX")
int BPF_PROG(recursive_attach, int a)
{
return 0;
}
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Red Hat, Inc. */
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char _license[] SEC("license") = "GPL";
/* Dummy fentry bpf prog for testing fentry attachment chains. It's going to be
* a start of the chain.
*/
SEC("fentry/bpf_testmod_fentry_test1")
int BPF_PROG(test1, int a)
{
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment