aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/prog_tests/module_fentry_shadow.c
blob: bea05f78de5fd556ecf2ff3dccabf89d1c891f2d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2022 Red Hat */
#include <test_progs.h>
#include <bpf/btf.h>
#include "bpf/libbpf_internal.h"
#include "cgroup_helpers.h"
#include "bpf_util.h"

static const char *module_name = "bpf_testmod";
static const char *symbol_name = "bpf_fentry_shadow_test";

static int get_bpf_testmod_btf_fd(void)
{
	struct bpf_btf_info info;
	char name[64];
	__u32 id = 0, len;
	int err, fd;

	while (true) {
		err = bpf_btf_get_next_id(id, &id);
		if (err) {
			log_err("failed to iterate BTF objects");
			return err;
		}

		fd = bpf_btf_get_fd_by_id(id);
		if (fd < 0) {
			if (errno == ENOENT)
				continue; /* expected race: BTF was unloaded */
			err = -errno;
			log_err("failed to get FD for BTF object #%d", id);
			return err;
		}

		len = sizeof(info);
		memset(&info, 0, sizeof(info));
		info.name = ptr_to_u64(name);
		info.name_len = sizeof(name);

		err = bpf_obj_get_info_by_fd(fd, &info, &len);
		if (err) {
			err = -errno;
			log_err("failed to get info for BTF object #%d", id);
			close(fd);
			return err;
		}

		if (strcmp(name, module_name) == 0)
			return fd;

		close(fd);
	}
	return -ENOENT;
}

void test_module_fentry_shadow(void)
{
	struct btf *vmlinux_btf = NULL, *mod_btf = NULL;
	int err, i;
	int btf_fd[2] = {};
	int prog_fd[2] = {};
	int link_fd[2] = {};
	__s32 btf_id[2] = {};

	if (!env.has_testmod) {
		test__skip();
		return;
	}

	LIBBPF_OPTS(bpf_prog_load_opts, load_opts,
		.expected_attach_type = BPF_TRACE_FENTRY,
	);

	const struct bpf_insn trace_program[] = {
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
	};

	vmlinux_btf = btf__load_vmlinux_btf();
	if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf"))
		return;

	btf_fd[1] = get_bpf_testmod_btf_fd();
	if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd"))
		goto out;

	mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf);
	if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd"))
		goto out;

	btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC);
	if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name"))
		goto out;

	btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC);
	if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name"))
		goto out;

	for (i = 0; i < 2; i++) {
		load_opts.attach_btf_id = btf_id[i];
		load_opts.attach_btf_obj_fd = btf_fd[i];
		prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL",
					   trace_program,
					   ARRAY_SIZE(trace_program),
					   &load_opts);
		if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load"))
			goto out;

		/* If the verifier incorrectly resolves addresses of the
		 * shadowed functions and uses the same address for both the
		 * vmlinux and the bpf_testmod functions, this will fail on
		 * attempting to create two trampolines for the same address,
		 * which is forbidden.
		 */
		link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL);
		if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create"))
			goto out;
	}

	err = bpf_prog_test_run_opts(prog_fd[0], NULL);
	ASSERT_OK(err, "running test");

out:
	btf__free(vmlinux_btf);
	btf__free(mod_btf);
	for (i = 0; i < 2; i++) {
		if (btf_fd[i])
			close(btf_fd[i]);
		if (prog_fd[i] > 0)
			close(prog_fd[i]);
		if (link_fd[i] > 0)
			close(link_fd[i]);
	}
}
7baf8762ac304b4&follow=1'>Update draft release notes to 1.7.0Junio C Hamano1-3/+2 2010-01-31Make NO_PTHREADS the sole thread configuration variableDan McGee5-36/+13 2010-01-31RPM packaging: use %global inside %{!?...}Junio C Hamano1-1/+4 2010-01-31mention new shell execution behavior in release notesJeff King1-0/+7 2010-01-31Fix memory leak in submodule.cJens Lehmann1-5/+9 2010-01-31Fix typos in technical documentation.Ralf Wildenhues13-24/+24 2010-01-30gitweb: Add optional extra parameter to die_error, for extended explanationJohn 'Warthog9' Hawley1-1/+7 2010-01-30gitweb: add a "string" variant of print_sort_thJohn 'Warthog9' Hawley1-5/+12 2010-01-30gitweb: add a "string" variant of print_local_timeJohn 'Warthog9' Hawley1-2/+9 2010-01-30gitweb: Check that $site_header etc. are defined before using themJohn 'Warthog9' Hawley1-3/+3 2010-01-30gitweb: Makefile improvementsJohn 'Warthog9' Hawley2-53/+141 2010-01-30gitweb: Load checkingJohn 'Warthog9' Hawley4-6/+72 2010-01-30gitweb: Make running t9501 test with '--debug' reliable and usableJakub Narebski1-5/+3 2010-01-30is_submodule_modified(): fix breakage with external GIT_INDEX_FILEv1.7.0-rc1Junio C Hamano1-2/+5 2010-01-30RPM packaging: don't include foreign-scm-helper bits yetJunio C Hamano1-0/+5 2010-01-30grep: Fix two memory leaksDan McGee1-0/+2 2010-01-30rebase: don't invoke the pager for each commit summaryMarkus Heidelberg1-1/+1 2010-01-29Update draft release notes to 1.7.0Junio C Hamano1-2/+15 2010-01-29Implement pthread_cond_broadcast on WindowsJohannes Sixt2-15/+94 2010-01-29If deriving SVN_SSH from GIT_SSH on msys, also add quotesSebastian Schuberth1-0/+1 2010-01-29add shebang line to git-mergetool--lib.shJeff King1-0/+1 2010-01-29fix off-by-one allocation errorJeff King1-1/+1 2010-01-29fix memcpy of overlapping areaJeff King1-1/+1 2010-01-29gitk: Update German translationChristian Stimming1-309/+432