Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at for-next 151 lines 5.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 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 level 10 * is not possible. Create a chain of attachment, verify that the last prog 11 * 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 target 16 * load fentry1 -> target 17 * load fentry2 -> fentry1 (fail) 18 * 19 * - Recursive attach of tracing progs (attach = true, detach = false). The 20 * chain looks like this: 21 * load target 22 * load fentry1 -> target 23 * attach fentry1 -> target 24 * 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 throughout 28 * the whole lifecycle of an fentry prog, independently from whether it's 29 * detached. The chain looks like this: 30 * load target 31 * load fentry1 -> target 32 * attach fentry1 -> target 33 * detach fentry1 34 * 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 target 54 * 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, preventing 82 * 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 in 110 * "prog->aux->dst_trampoline and tgt_prog is NULL" branch in 111 * bpf_tracing_prog_attach) does not lead to a crash due to missing attach_btf 112 */ 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}