/* This test crafts a race between btf_try_get_module and do_init_module, and *checkswhetherbtf_try_get_modulehandlestheinvocationforawell-formed *butuninitializedmodulecorrectly.Unlessthemodulehascompletedits *initcalls,theverifiershouldfailtheprogramloadandreturnENXIO. * *userfaultfdisusedtotriggerafaultinanfmod_retprogram,andmakeit *sleep,thentheBPFprogramisloadedandthereturnvaluefromverifieris *inspected.Afterthis,theuserfaultfdisclosedsothatthemoduleloading *threadmakesforwardprogress,andfmod_retinjectsanerrorsothatthe *moduleloadfailsanditisfreed. * *Iftheverifiersucceededinloadingthesuppliedprogram,itwillendup *takingreferencetofreedmodule,andtriggeracrashwhentheprogramfd *isclosedlater.Thisistrueforbothkfuncsandksyms.Inbothcases, *thecrashistriggeredinsidebpf_prog_free_deferred,whenmodulereference *isfinallyreleased.
*/
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;
if (!ASSERT_OK(pthread_create(&load_mod_thrd, NULL, load_module_thread, NULL), "load module thread")) goto end_uffd;
/* Now, we either fail loading module, or block in bpf prog, spin to find out */ while (!atomic_load(&state) && !atomic_load(blockingp))
; if (!ASSERT_EQ(state, _TS_INVALID, "module load should block")) goto end_join; if (!ASSERT_EQ(*blockingp, 1, "module load blocked")) {
pthread_kill(load_mod_thrd, SIGKILL); goto end_uffd;
}
/* We might have set bpf_blocking to 1, but may have not blocked in *bpf_copy_from_user.Readuserfaultfddescriptortoverifythat.
*/ if (!ASSERT_EQ(read(uffd, &uffd_msg, sizeof(uffd_msg)), sizeof(uffd_msg), "read uffd block event")) goto end_join; if (!ASSERT_EQ(uffd_msg.event, UFFD_EVENT_PAGEFAULT, "read uffd event is pagefault")) goto end_join;
/* We know that load_mod_thrd is blocked in the fmod_ret program, the *modulestateisstillMODULE_STATE_COMINGbecausemod->inithasn't *returned.Thisisthetimewetrytoloadaprogramcallingkfuncand *checkifwegetENXIOfromverifier.
*/
skel_fail = config->bpf_open_and_load();
ret = errno; if (!ASSERT_EQ(skel_fail, NULL, config->str_open)) { /* Close uffd to unblock load_mod_thrd */
close(uffd);
uffd = -1; while (atomic_load(blockingp) != 2)
;
ASSERT_OK(kern_sync_rcu(), "kern_sync_rcu");
config->bpf_destroy(skel_fail); goto end_join;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.