152 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2023 Red Hat, Inc. */3#include <test_progs.h>4#include "fentry_recursive.skel.h"5#include "fentry_recursive_target.skel.h"6#include <bpf/btf.h>7#include "bpf/libbpf_internal.h"8 9/* Test recursive attachment of tracing progs with more than one nesting level10 * is not possible. Create a chain of attachment, verify that the last prog11 * will fail. Depending on the arguments, following cases are tested:12 *13 * - Recursive loading of tracing progs, without attaching (attach = false,14 * detach = false). The chain looks like this:15 * load target16 * load fentry1 -> target17 * load fentry2 -> fentry1 (fail)18 *19 * - Recursive attach of tracing progs (attach = true, detach = false). The20 * chain looks like this:21 * load target22 * load fentry1 -> target23 * attach fentry1 -> target24 * load fentry2 -> fentry1 (fail)25 *26 * - Recursive attach and detach of tracing progs (attach = true, detach =27 * true). This validates that attach_tracing_prog flag will be set throughout28 * the whole lifecycle of an fentry prog, independently from whether it's29 * detached. The chain looks like this:30 * load target31 * load fentry1 -> target32 * attach fentry1 -> target33 * detach fentry134 * load fentry2 -> fentry1 (fail)35 */36static void test_recursive_fentry_chain(bool attach, bool detach)37{38 struct fentry_recursive_target *target_skel = NULL;39 struct fentry_recursive *tracing_chain[2] = {};40 struct bpf_program *prog;41 int prev_fd, err;42 43 target_skel = fentry_recursive_target__open_and_load();44 if (!ASSERT_OK_PTR(target_skel, "fentry_recursive_target__open_and_load"))45 return;46 47 /* Create an attachment chain with two fentry progs */48 for (int i = 0; i < 2; i++) {49 tracing_chain[i] = fentry_recursive__open();50 if (!ASSERT_OK_PTR(tracing_chain[i], "fentry_recursive__open"))51 goto close_prog;52 53 /* The first prog in the chain is going to be attached to the target54 * fentry program, the second one to the previous in the chain.55 */56 prog = tracing_chain[i]->progs.recursive_attach;57 if (i == 0) {58 prev_fd = bpf_program__fd(target_skel->progs.test1);59 err = bpf_program__set_attach_target(prog, prev_fd, "test1");60 } else {61 prev_fd = bpf_program__fd(tracing_chain[i-1]->progs.recursive_attach);62 err = bpf_program__set_attach_target(prog, prev_fd, "recursive_attach");63 }64 65 if (!ASSERT_OK(err, "bpf_program__set_attach_target"))66 goto close_prog;67 68 err = fentry_recursive__load(tracing_chain[i]);69 /* The first attach should succeed, the second fail */70 if (i == 0) {71 if (!ASSERT_OK(err, "fentry_recursive__load"))72 goto close_prog;73 74 if (attach) {75 err = fentry_recursive__attach(tracing_chain[i]);76 if (!ASSERT_OK(err, "fentry_recursive__attach"))77 goto close_prog;78 }79 80 if (detach) {81 /* Flag attach_tracing_prog should still be set, preventing82 * attachment of the following prog.83 */84 fentry_recursive__detach(tracing_chain[i]);85 }86 } else {87 if (!ASSERT_ERR(err, "fentry_recursive__load"))88 goto close_prog;89 }90 }91 92close_prog:93 fentry_recursive_target__destroy(target_skel);94 for (int i = 0; i < 2; i++) {95 fentry_recursive__destroy(tracing_chain[i]);96 }97}98 99void test_recursive_fentry(void)100{101 if (test__start_subtest("attach"))102 test_recursive_fentry_chain(true, false);103 if (test__start_subtest("load"))104 test_recursive_fentry_chain(false, false);105 if (test__start_subtest("detach"))106 test_recursive_fentry_chain(true, true);107}108 109/* Test that a tracing prog reattachment (when we land in110 * "prog->aux->dst_trampoline and tgt_prog is NULL" branch in111 * bpf_tracing_prog_attach) does not lead to a crash due to missing attach_btf112 */113void test_fentry_attach_btf_presence(void)114{115 struct fentry_recursive_target *target_skel = NULL;116 struct fentry_recursive *tracing_skel = NULL;117 struct bpf_program *prog;118 int err, link_fd, tgt_prog_fd;119 120 target_skel = fentry_recursive_target__open_and_load();121 if (!ASSERT_OK_PTR(target_skel, "fentry_recursive_target__open_and_load"))122 goto close_prog;123 124 tracing_skel = fentry_recursive__open();125 if (!ASSERT_OK_PTR(tracing_skel, "fentry_recursive__open"))126 goto close_prog;127 128 prog = tracing_skel->progs.recursive_attach;129 tgt_prog_fd = bpf_program__fd(target_skel->progs.fentry_target);130 err = bpf_program__set_attach_target(prog, tgt_prog_fd, "fentry_target");131 if (!ASSERT_OK(err, "bpf_program__set_attach_target"))132 goto close_prog;133 134 err = fentry_recursive__load(tracing_skel);135 if (!ASSERT_OK(err, "fentry_recursive__load"))136 goto close_prog;137 138 tgt_prog_fd = bpf_program__fd(tracing_skel->progs.recursive_attach);139 link_fd = bpf_link_create(tgt_prog_fd, 0, BPF_TRACE_FENTRY, NULL);140 if (!ASSERT_GE(link_fd, 0, "link_fd"))141 goto close_prog;142 143 fentry_recursive__detach(tracing_skel);144 145 err = fentry_recursive__attach(tracing_skel);146 ASSERT_ERR(err, "fentry_recursive__attach");147 148close_prog:149 fentry_recursive_target__destroy(target_skel);150 fentry_recursive__destroy(tracing_skel);151}152