1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3 4 #include <test_progs.h> 5 #include "testing_helpers.h" 6 #include "livepatch_trampoline.skel.h" 7 8 static int load_livepatch(void) 9 { 10 char path[4096]; 11 12 /* CI will set KBUILD_OUTPUT */ 13 snprintf(path, sizeof(path), "%s/samples/livepatch/livepatch-sample.ko", 14 getenv("KBUILD_OUTPUT") ? : "../../../.."); 15 16 return load_module(path, env_verbosity > VERBOSE_NONE); 17 } 18 19 static void unload_livepatch(void) 20 { 21 /* Disable the livepatch before unloading the module */ 22 system("echo 0 > /sys/kernel/livepatch/livepatch_sample/enabled"); 23 24 unload_module("livepatch_sample", env_verbosity > VERBOSE_NONE); 25 } 26 27 static void read_proc_cmdline(void) 28 { 29 char buf[4096]; 30 int fd, ret; 31 32 fd = open("/proc/cmdline", O_RDONLY); 33 if (!ASSERT_OK_FD(fd, "open /proc/cmdline")) 34 return; 35 36 ret = read(fd, buf, sizeof(buf)); 37 if (!ASSERT_GT(ret, 0, "read /proc/cmdline")) 38 goto out; 39 40 ASSERT_OK(strncmp(buf, "this has been live patched", 26), "strncmp"); 41 42 out: 43 close(fd); 44 } 45 46 static void __test_livepatch_trampoline(bool fexit_first) 47 { 48 struct livepatch_trampoline *skel = NULL; 49 int err; 50 51 skel = livepatch_trampoline__open_and_load(); 52 if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 53 goto out; 54 55 skel->bss->my_pid = getpid(); 56 57 if (!fexit_first) { 58 /* fentry program is loaded first by default */ 59 err = livepatch_trampoline__attach(skel); 60 if (!ASSERT_OK(err, "skel_attach")) 61 goto out; 62 } else { 63 /* Manually load fexit program first. */ 64 skel->links.fexit_cmdline = bpf_program__attach(skel->progs.fexit_cmdline); 65 if (!ASSERT_OK_PTR(skel->links.fexit_cmdline, "attach_fexit")) 66 goto out; 67 68 skel->links.fentry_cmdline = bpf_program__attach(skel->progs.fentry_cmdline); 69 if (!ASSERT_OK_PTR(skel->links.fentry_cmdline, "attach_fentry")) 70 goto out; 71 } 72 73 read_proc_cmdline(); 74 75 ASSERT_EQ(skel->bss->fentry_hit, 1, "fentry_hit"); 76 ASSERT_EQ(skel->bss->fexit_hit, 1, "fexit_hit"); 77 out: 78 livepatch_trampoline__destroy(skel); 79 } 80 81 void test_livepatch_trampoline(void) 82 { 83 int retry_cnt = 0; 84 85 retry: 86 if (load_livepatch()) { 87 if (retry_cnt) { 88 ASSERT_OK(1, "load_livepatch"); 89 goto out; 90 } 91 /* 92 * Something else (previous run of the same test?) loaded 93 * the KLP module. Unload the KLP module and retry. 94 */ 95 unload_livepatch(); 96 retry_cnt++; 97 goto retry; 98 } 99 100 if (test__start_subtest("fentry_first")) 101 __test_livepatch_trampoline(false); 102 103 if (test__start_subtest("fexit_first")) 104 __test_livepatch_trampoline(true); 105 out: 106 unload_livepatch(); 107 } 108