Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2022 Red Hat */
  3#include <test_progs.h>
  4#include <bpf/btf.h>
  5#include "bpf/libbpf_internal.h"
  6#include "cgroup_helpers.h"
  7#include "bpf_util.h"
  8
  9static const char *module_name = "bpf_testmod";
 10static const char *symbol_name = "bpf_fentry_shadow_test";
 11
 12static int get_bpf_testmod_btf_fd(void)
 13{
 14	struct bpf_btf_info info;
 15	char name[64];
 16	__u32 id = 0, len;
 17	int err, fd;
 18
 19	while (true) {
 20		err = bpf_btf_get_next_id(id, &id);
 21		if (err) {
 22			log_err("failed to iterate BTF objects");
 23			return err;
 24		}
 25
 26		fd = bpf_btf_get_fd_by_id(id);
 27		if (fd < 0) {
 28			if (errno == ENOENT)
 29				continue; /* expected race: BTF was unloaded */
 30			err = -errno;
 31			log_err("failed to get FD for BTF object #%d", id);
 32			return err;
 33		}
 34
 35		len = sizeof(info);
 36		memset(&info, 0, sizeof(info));
 37		info.name = ptr_to_u64(name);
 38		info.name_len = sizeof(name);
 39
 40		err = bpf_obj_get_info_by_fd(fd, &info, &len);
 41		if (err) {
 42			err = -errno;
 43			log_err("failed to get info for BTF object #%d", id);
 44			close(fd);
 45			return err;
 46		}
 47
 48		if (strcmp(name, module_name) == 0)
 49			return fd;
 50
 51		close(fd);
 52	}
 53	return -ENOENT;
 54}
 55
 56void test_module_fentry_shadow(void)
 57{
 58	struct btf *vmlinux_btf = NULL, *mod_btf = NULL;
 59	int err, i;
 60	int btf_fd[2] = {};
 61	int prog_fd[2] = {};
 62	int link_fd[2] = {};
 63	__s32 btf_id[2] = {};
 64
 65	if (!env.has_testmod) {
 66		test__skip();
 67		return;
 68	}
 69
 70	LIBBPF_OPTS(bpf_prog_load_opts, load_opts,
 71		.expected_attach_type = BPF_TRACE_FENTRY,
 72	);
 73
 74	const struct bpf_insn trace_program[] = {
 75		BPF_MOV64_IMM(BPF_REG_0, 0),
 76		BPF_EXIT_INSN(),
 77	};
 78
 79	vmlinux_btf = btf__load_vmlinux_btf();
 80	if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf"))
 81		return;
 82
 83	btf_fd[1] = get_bpf_testmod_btf_fd();
 84	if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd"))
 85		goto out;
 86
 87	mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf);
 88	if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd"))
 89		goto out;
 90
 91	btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC);
 92	if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name"))
 93		goto out;
 94
 95	btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC);
 96	if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name"))
 97		goto out;
 98
 99	for (i = 0; i < 2; i++) {
100		load_opts.attach_btf_id = btf_id[i];
101		load_opts.attach_btf_obj_fd = btf_fd[i];
102		prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL",
103					   trace_program,
104					   ARRAY_SIZE(trace_program),
105					   &load_opts);
106		if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load"))
107			goto out;
108
109		/* If the verifier incorrectly resolves addresses of the
110		 * shadowed functions and uses the same address for both the
111		 * vmlinux and the bpf_testmod functions, this will fail on
112		 * attempting to create two trampolines for the same address,
113		 * which is forbidden.
114		 */
115		link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL);
116		if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create"))
117			goto out;
118	}
119
120	err = bpf_prog_test_run_opts(prog_fd[0], NULL);
121	ASSERT_OK(err, "running test");
122
123out:
124	btf__free(vmlinux_btf);
125	btf__free(mod_btf);
126	for (i = 0; i < 2; i++) {
127		if (btf_fd[i])
128			close(btf_fd[i]);
129		if (prog_fd[i] > 0)
130			close(prog_fd[i]);
131		if (link_fd[i] > 0)
132			close(link_fd[i]);
133	}
134}
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2022 Red Hat */
  3#include <test_progs.h>
  4#include <bpf/btf.h>
  5#include "bpf/libbpf_internal.h"
  6#include "cgroup_helpers.h"
 
  7
  8static const char *module_name = "bpf_testmod";
  9static const char *symbol_name = "bpf_fentry_shadow_test";
 10
 11static int get_bpf_testmod_btf_fd(void)
 12{
 13	struct bpf_btf_info info;
 14	char name[64];
 15	__u32 id = 0, len;
 16	int err, fd;
 17
 18	while (true) {
 19		err = bpf_btf_get_next_id(id, &id);
 20		if (err) {
 21			log_err("failed to iterate BTF objects");
 22			return err;
 23		}
 24
 25		fd = bpf_btf_get_fd_by_id(id);
 26		if (fd < 0) {
 27			if (errno == ENOENT)
 28				continue; /* expected race: BTF was unloaded */
 29			err = -errno;
 30			log_err("failed to get FD for BTF object #%d", id);
 31			return err;
 32		}
 33
 34		len = sizeof(info);
 35		memset(&info, 0, sizeof(info));
 36		info.name = ptr_to_u64(name);
 37		info.name_len = sizeof(name);
 38
 39		err = bpf_obj_get_info_by_fd(fd, &info, &len);
 40		if (err) {
 41			err = -errno;
 42			log_err("failed to get info for BTF object #%d", id);
 43			close(fd);
 44			return err;
 45		}
 46
 47		if (strcmp(name, module_name) == 0)
 48			return fd;
 49
 50		close(fd);
 51	}
 52	return -ENOENT;
 53}
 54
 55void test_module_fentry_shadow(void)
 56{
 57	struct btf *vmlinux_btf = NULL, *mod_btf = NULL;
 58	int err, i;
 59	int btf_fd[2] = {};
 60	int prog_fd[2] = {};
 61	int link_fd[2] = {};
 62	__s32 btf_id[2] = {};
 63
 64	if (!env.has_testmod) {
 65		test__skip();
 66		return;
 67	}
 68
 69	LIBBPF_OPTS(bpf_prog_load_opts, load_opts,
 70		.expected_attach_type = BPF_TRACE_FENTRY,
 71	);
 72
 73	const struct bpf_insn trace_program[] = {
 74		BPF_MOV64_IMM(BPF_REG_0, 0),
 75		BPF_EXIT_INSN(),
 76	};
 77
 78	vmlinux_btf = btf__load_vmlinux_btf();
 79	if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf"))
 80		return;
 81
 82	btf_fd[1] = get_bpf_testmod_btf_fd();
 83	if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd"))
 84		goto out;
 85
 86	mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf);
 87	if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd"))
 88		goto out;
 89
 90	btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC);
 91	if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name"))
 92		goto out;
 93
 94	btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC);
 95	if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name"))
 96		goto out;
 97
 98	for (i = 0; i < 2; i++) {
 99		load_opts.attach_btf_id = btf_id[i];
100		load_opts.attach_btf_obj_fd = btf_fd[i];
101		prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL",
102					   trace_program,
103					   sizeof(trace_program) / sizeof(struct bpf_insn),
104					   &load_opts);
105		if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load"))
106			goto out;
107
108		/* If the verifier incorrectly resolves addresses of the
109		 * shadowed functions and uses the same address for both the
110		 * vmlinux and the bpf_testmod functions, this will fail on
111		 * attempting to create two trampolines for the same address,
112		 * which is forbidden.
113		 */
114		link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL);
115		if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create"))
116			goto out;
117	}
118
119	err = bpf_prog_test_run_opts(prog_fd[0], NULL);
120	ASSERT_OK(err, "running test");
121
122out:
123	btf__free(vmlinux_btf);
124	btf__free(mod_btf);
125	for (i = 0; i < 2; i++) {
126		if (btf_fd[i])
127			close(btf_fd[i]);
128		if (prog_fd[i] > 0)
129			close(prog_fd[i]);
130		if (link_fd[i] > 0)
131			close(link_fd[i]);
132	}
133}