Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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}