tools/testing/selftests/bpf/prog_tests/bpf_mod_race.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/bpf_mod_race.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/bpf_mod_race.c
Extension
.c
Size
6265 bytes
Lines
207
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct test_config {
	const char *str_open;
	void *(*bpf_open_and_load)();
	void (*bpf_destroy)(void *);
};

enum bpf_test_state {
	_TS_INVALID,
	TS_MODULE_LOAD,
	TS_MODULE_LOAD_FAIL,
};

static _Atomic enum bpf_test_state state = _TS_INVALID;

static void *load_module_thread(void *p)
{

	if (!ASSERT_NEQ(load_bpf_testmod(false), 0, "load_module_thread must fail"))
		atomic_store(&state, TS_MODULE_LOAD);
	else
		atomic_store(&state, TS_MODULE_LOAD_FAIL);
	return p;
}

static int sys_userfaultfd(int flags)
{
	return syscall(__NR_userfaultfd, flags);
}

static int test_setup_uffd(void *fault_addr)
{
	struct uffdio_register uffd_register = {};
	struct uffdio_api uffd_api = {};
	int uffd;

	uffd = sys_userfaultfd(O_CLOEXEC);
	if (uffd < 0)
		return -errno;

	uffd_api.api = UFFD_API;
	uffd_api.features = 0;
	if (ioctl(uffd, UFFDIO_API, &uffd_api)) {
		close(uffd);
		return -1;
	}

	uffd_register.range.start = (unsigned long)fault_addr;
	uffd_register.range.len = getpagesize();
	uffd_register.mode = UFFDIO_REGISTER_MODE_MISSING;
	if (ioctl(uffd, UFFDIO_REGISTER, &uffd_register)) {
		close(uffd);
		return -1;
	}
	return uffd;
}

static void test_bpf_mod_race_config(const struct test_config *config)
{
	void *fault_addr, *skel_fail;
	struct bpf_mod_race *skel;
	struct uffd_msg uffd_msg;
	pthread_t load_mod_thrd;
	_Atomic int *blockingp;
	int uffd, ret;

	fault_addr = mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (!ASSERT_NEQ(fault_addr, MAP_FAILED, "mmap for uffd registration"))
		return;

	if (!ASSERT_OK(unload_bpf_testmod(false), "unload bpf_testmod"))
		goto end_mmap;

	skel = bpf_mod_race__open();
	if (!ASSERT_OK_PTR(skel, "bpf_mod_kfunc_race__open"))
		goto end_module;

	skel->rodata->bpf_mod_race_config.tgid = getpid();
	skel->rodata->bpf_mod_race_config.inject_error = -4242;
	skel->rodata->bpf_mod_race_config.fault_addr = fault_addr;
	if (!ASSERT_OK(bpf_mod_race__load(skel), "bpf_mod___load"))
		goto end_destroy;
	blockingp = (_Atomic int *)&skel->bss->bpf_blocking;

	if (!ASSERT_OK(bpf_mod_race__attach(skel), "bpf_mod_kfunc_race__attach"))
		goto end_destroy;

	uffd = test_setup_uffd(fault_addr);
	if (!ASSERT_GE(uffd, 0, "userfaultfd open + register address"))
		goto end_destroy;

Annotation

Implementation Notes