Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <unistd.h>
0003 #include <pthread.h>
0004 #include <sys/mman.h>
0005 #include <stdatomic.h>
0006 #include <test_progs.h>
0007 #include <sys/syscall.h>
0008 #include <linux/module.h>
0009 #include <linux/userfaultfd.h>
0010 
0011 #include "ksym_race.skel.h"
0012 #include "bpf_mod_race.skel.h"
0013 #include "kfunc_call_race.skel.h"
0014 
0015 /* This test crafts a race between btf_try_get_module and do_init_module, and
0016  * checks whether btf_try_get_module handles the invocation for a well-formed
0017  * but uninitialized module correctly. Unless the module has completed its
0018  * initcalls, the verifier should fail the program load and return ENXIO.
0019  *
0020  * userfaultfd is used to trigger a fault in an fmod_ret program, and make it
0021  * sleep, then the BPF program is loaded and the return value from verifier is
0022  * inspected. After this, the userfaultfd is closed so that the module loading
0023  * thread makes forward progress, and fmod_ret injects an error so that the
0024  * module load fails and it is freed.
0025  *
0026  * If the verifier succeeded in loading the supplied program, it will end up
0027  * taking reference to freed module, and trigger a crash when the program fd
0028  * is closed later. This is true for both kfuncs and ksyms. In both cases,
0029  * the crash is triggered inside bpf_prog_free_deferred, when module reference
0030  * is finally released.
0031  */
0032 
0033 struct test_config {
0034     const char *str_open;
0035     void *(*bpf_open_and_load)();
0036     void (*bpf_destroy)(void *);
0037 };
0038 
0039 enum bpf_test_state {
0040     _TS_INVALID,
0041     TS_MODULE_LOAD,
0042     TS_MODULE_LOAD_FAIL,
0043 };
0044 
0045 static _Atomic enum bpf_test_state state = _TS_INVALID;
0046 
0047 static int sys_finit_module(int fd, const char *param_values, int flags)
0048 {
0049     return syscall(__NR_finit_module, fd, param_values, flags);
0050 }
0051 
0052 static int sys_delete_module(const char *name, unsigned int flags)
0053 {
0054     return syscall(__NR_delete_module, name, flags);
0055 }
0056 
0057 static int load_module(const char *mod)
0058 {
0059     int ret, fd;
0060 
0061     fd = open("bpf_testmod.ko", O_RDONLY);
0062     if (fd < 0)
0063         return fd;
0064 
0065     ret = sys_finit_module(fd, "", 0);
0066     close(fd);
0067     if (ret < 0)
0068         return ret;
0069     return 0;
0070 }
0071 
0072 static void *load_module_thread(void *p)
0073 {
0074 
0075     if (!ASSERT_NEQ(load_module("bpf_testmod.ko"), 0, "load_module_thread must fail"))
0076         atomic_store(&state, TS_MODULE_LOAD);
0077     else
0078         atomic_store(&state, TS_MODULE_LOAD_FAIL);
0079     return p;
0080 }
0081 
0082 static int sys_userfaultfd(int flags)
0083 {
0084     return syscall(__NR_userfaultfd, flags);
0085 }
0086 
0087 static int test_setup_uffd(void *fault_addr)
0088 {
0089     struct uffdio_register uffd_register = {};
0090     struct uffdio_api uffd_api = {};
0091     int uffd;
0092 
0093     uffd = sys_userfaultfd(O_CLOEXEC);
0094     if (uffd < 0)
0095         return -errno;
0096 
0097     uffd_api.api = UFFD_API;
0098     uffd_api.features = 0;
0099     if (ioctl(uffd, UFFDIO_API, &uffd_api)) {
0100         close(uffd);
0101         return -1;
0102     }
0103 
0104     uffd_register.range.start = (unsigned long)fault_addr;
0105     uffd_register.range.len = 4096;
0106     uffd_register.mode = UFFDIO_REGISTER_MODE_MISSING;
0107     if (ioctl(uffd, UFFDIO_REGISTER, &uffd_register)) {
0108         close(uffd);
0109         return -1;
0110     }
0111     return uffd;
0112 }
0113 
0114 static void test_bpf_mod_race_config(const struct test_config *config)
0115 {
0116     void *fault_addr, *skel_fail;
0117     struct bpf_mod_race *skel;
0118     struct uffd_msg uffd_msg;
0119     pthread_t load_mod_thrd;
0120     _Atomic int *blockingp;
0121     int uffd, ret;
0122 
0123     fault_addr = mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0124     if (!ASSERT_NEQ(fault_addr, MAP_FAILED, "mmap for uffd registration"))
0125         return;
0126 
0127     if (!ASSERT_OK(sys_delete_module("bpf_testmod", 0), "unload bpf_testmod"))
0128         goto end_mmap;
0129 
0130     skel = bpf_mod_race__open();
0131     if (!ASSERT_OK_PTR(skel, "bpf_mod_kfunc_race__open"))
0132         goto end_module;
0133 
0134     skel->rodata->bpf_mod_race_config.tgid = getpid();
0135     skel->rodata->bpf_mod_race_config.inject_error = -4242;
0136     skel->rodata->bpf_mod_race_config.fault_addr = fault_addr;
0137     if (!ASSERT_OK(bpf_mod_race__load(skel), "bpf_mod___load"))
0138         goto end_destroy;
0139     blockingp = (_Atomic int *)&skel->bss->bpf_blocking;
0140 
0141     if (!ASSERT_OK(bpf_mod_race__attach(skel), "bpf_mod_kfunc_race__attach"))
0142         goto end_destroy;
0143 
0144     uffd = test_setup_uffd(fault_addr);
0145     if (!ASSERT_GE(uffd, 0, "userfaultfd open + register address"))
0146         goto end_destroy;
0147 
0148     if (!ASSERT_OK(pthread_create(&load_mod_thrd, NULL, load_module_thread, NULL),
0149                "load module thread"))
0150         goto end_uffd;
0151 
0152     /* Now, we either fail loading module, or block in bpf prog, spin to find out */
0153     while (!atomic_load(&state) && !atomic_load(blockingp))
0154         ;
0155     if (!ASSERT_EQ(state, _TS_INVALID, "module load should block"))
0156         goto end_join;
0157     if (!ASSERT_EQ(*blockingp, 1, "module load blocked")) {
0158         pthread_kill(load_mod_thrd, SIGKILL);
0159         goto end_uffd;
0160     }
0161 
0162     /* We might have set bpf_blocking to 1, but may have not blocked in
0163      * bpf_copy_from_user. Read userfaultfd descriptor to verify that.
0164      */
0165     if (!ASSERT_EQ(read(uffd, &uffd_msg, sizeof(uffd_msg)), sizeof(uffd_msg),
0166                "read uffd block event"))
0167         goto end_join;
0168     if (!ASSERT_EQ(uffd_msg.event, UFFD_EVENT_PAGEFAULT, "read uffd event is pagefault"))
0169         goto end_join;
0170 
0171     /* We know that load_mod_thrd is blocked in the fmod_ret program, the
0172      * module state is still MODULE_STATE_COMING because mod->init hasn't
0173      * returned. This is the time we try to load a program calling kfunc and
0174      * check if we get ENXIO from verifier.
0175      */
0176     skel_fail = config->bpf_open_and_load();
0177     ret = errno;
0178     if (!ASSERT_EQ(skel_fail, NULL, config->str_open)) {
0179         /* Close uffd to unblock load_mod_thrd */
0180         close(uffd);
0181         uffd = -1;
0182         while (atomic_load(blockingp) != 2)
0183             ;
0184         ASSERT_OK(kern_sync_rcu(), "kern_sync_rcu");
0185         config->bpf_destroy(skel_fail);
0186         goto end_join;
0187 
0188     }
0189     ASSERT_EQ(ret, ENXIO, "verifier returns ENXIO");
0190     ASSERT_EQ(skel->data->res_try_get_module, false, "btf_try_get_module == false");
0191 
0192     close(uffd);
0193     uffd = -1;
0194 end_join:
0195     pthread_join(load_mod_thrd, NULL);
0196     if (uffd < 0)
0197         ASSERT_EQ(atomic_load(&state), TS_MODULE_LOAD_FAIL, "load_mod_thrd success");
0198 end_uffd:
0199     if (uffd >= 0)
0200         close(uffd);
0201 end_destroy:
0202     bpf_mod_race__destroy(skel);
0203     ASSERT_OK(kern_sync_rcu(), "kern_sync_rcu");
0204 end_module:
0205     sys_delete_module("bpf_testmod", 0);
0206     ASSERT_OK(load_module("bpf_testmod.ko"), "restore bpf_testmod");
0207 end_mmap:
0208     munmap(fault_addr, 4096);
0209     atomic_store(&state, _TS_INVALID);
0210 }
0211 
0212 static const struct test_config ksym_config = {
0213     .str_open = "ksym_race__open_and_load",
0214     .bpf_open_and_load = (void *)ksym_race__open_and_load,
0215     .bpf_destroy = (void *)ksym_race__destroy,
0216 };
0217 
0218 static const struct test_config kfunc_config = {
0219     .str_open = "kfunc_call_race__open_and_load",
0220     .bpf_open_and_load = (void *)kfunc_call_race__open_and_load,
0221     .bpf_destroy = (void *)kfunc_call_race__destroy,
0222 };
0223 
0224 void serial_test_bpf_mod_race(void)
0225 {
0226     if (test__start_subtest("ksym (used_btfs UAF)"))
0227         test_bpf_mod_race_config(&ksym_config);
0228     if (test__start_subtest("kfunc (kfunc_btf_tab UAF)"))
0229         test_bpf_mod_race_config(&kfunc_config);
0230 }