1784cdf93SMykyta Yatsenko // SPDX-License-Identifier: GPL-2.0 2784cdf93SMykyta Yatsenko /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3784cdf93SMykyta Yatsenko 4784cdf93SMykyta Yatsenko #include <test_progs.h> 5784cdf93SMykyta Yatsenko #include <network_helpers.h> 6784cdf93SMykyta Yatsenko #include "file_reader.skel.h" 7784cdf93SMykyta Yatsenko #include "file_reader_fail.skel.h" 8784cdf93SMykyta Yatsenko #include <dlfcn.h> 9784cdf93SMykyta Yatsenko #include <sys/mman.h> 10784cdf93SMykyta Yatsenko 11784cdf93SMykyta Yatsenko const char *user_ptr = "hello world"; 12784cdf93SMykyta Yatsenko char file_contents[256000]; 13784cdf93SMykyta Yatsenko 14784cdf93SMykyta Yatsenko void *get_executable_base_addr(void) 15784cdf93SMykyta Yatsenko { 16784cdf93SMykyta Yatsenko Dl_info info; 17784cdf93SMykyta Yatsenko 18784cdf93SMykyta Yatsenko if (!dladdr((void *)&get_executable_base_addr, &info)) { 19784cdf93SMykyta Yatsenko fprintf(stderr, "dladdr failed\n"); 20784cdf93SMykyta Yatsenko return NULL; 21784cdf93SMykyta Yatsenko } 22784cdf93SMykyta Yatsenko 23784cdf93SMykyta Yatsenko return info.dli_fbase; 24784cdf93SMykyta Yatsenko } 25784cdf93SMykyta Yatsenko 26784cdf93SMykyta Yatsenko static int initialize_file_contents(void) 27784cdf93SMykyta Yatsenko { 28784cdf93SMykyta Yatsenko int fd, page_sz = sysconf(_SC_PAGESIZE); 29784cdf93SMykyta Yatsenko ssize_t n = 0, cur, off; 30784cdf93SMykyta Yatsenko void *addr; 31784cdf93SMykyta Yatsenko 32784cdf93SMykyta Yatsenko fd = open("/proc/self/exe", O_RDONLY); 33784cdf93SMykyta Yatsenko if (!ASSERT_OK_FD(fd, "Open /proc/self/exe\n")) 34784cdf93SMykyta Yatsenko return 1; 35784cdf93SMykyta Yatsenko 36784cdf93SMykyta Yatsenko do { 37784cdf93SMykyta Yatsenko cur = read(fd, file_contents + n, sizeof(file_contents) - n); 38784cdf93SMykyta Yatsenko if (!ASSERT_GT(cur, 0, "read success")) 39784cdf93SMykyta Yatsenko break; 40784cdf93SMykyta Yatsenko n += cur; 41784cdf93SMykyta Yatsenko } while (n < sizeof(file_contents)); 42784cdf93SMykyta Yatsenko 43784cdf93SMykyta Yatsenko close(fd); 44784cdf93SMykyta Yatsenko 45784cdf93SMykyta Yatsenko if (!ASSERT_EQ(n, sizeof(file_contents), "Read /proc/self/exe\n")) 46784cdf93SMykyta Yatsenko return 1; 47784cdf93SMykyta Yatsenko 48784cdf93SMykyta Yatsenko addr = get_executable_base_addr(); 49784cdf93SMykyta Yatsenko if (!ASSERT_NEQ(addr, NULL, "get executable address")) 50784cdf93SMykyta Yatsenko return 1; 51784cdf93SMykyta Yatsenko 52784cdf93SMykyta Yatsenko /* page-align base file address */ 53784cdf93SMykyta Yatsenko addr = (void *)((unsigned long)addr & ~(page_sz - 1)); 54784cdf93SMykyta Yatsenko 55*5913e936SMykyta Yatsenko /* 56*5913e936SMykyta Yatsenko * Page out range 0..512K, use 0..256K for positive tests and 57*5913e936SMykyta Yatsenko * 256K..512K for negative tests expecting page faults 58*5913e936SMykyta Yatsenko */ 59*5913e936SMykyta Yatsenko for (off = 0; off < sizeof(file_contents) * 2; off += page_sz) { 60784cdf93SMykyta Yatsenko if (!ASSERT_OK(madvise(addr + off, page_sz, MADV_PAGEOUT), 61784cdf93SMykyta Yatsenko "madvise pageout")) 62784cdf93SMykyta Yatsenko return errno; 63784cdf93SMykyta Yatsenko } 64784cdf93SMykyta Yatsenko 65784cdf93SMykyta Yatsenko return 0; 66784cdf93SMykyta Yatsenko } 67784cdf93SMykyta Yatsenko 68784cdf93SMykyta Yatsenko static void run_test(const char *prog_name) 69784cdf93SMykyta Yatsenko { 70784cdf93SMykyta Yatsenko struct file_reader *skel; 71784cdf93SMykyta Yatsenko struct bpf_program *prog; 72784cdf93SMykyta Yatsenko int err, fd; 73784cdf93SMykyta Yatsenko 74784cdf93SMykyta Yatsenko err = initialize_file_contents(); 75784cdf93SMykyta Yatsenko if (!ASSERT_OK(err, "initialize file contents")) 76784cdf93SMykyta Yatsenko return; 77784cdf93SMykyta Yatsenko 78784cdf93SMykyta Yatsenko skel = file_reader__open(); 79784cdf93SMykyta Yatsenko if (!ASSERT_OK_PTR(skel, "file_reader__open")) 80784cdf93SMykyta Yatsenko return; 81784cdf93SMykyta Yatsenko 82784cdf93SMykyta Yatsenko bpf_object__for_each_program(prog, skel->obj) { 83784cdf93SMykyta Yatsenko bpf_program__set_autoload(prog, strcmp(bpf_program__name(prog), prog_name) == 0); 84784cdf93SMykyta Yatsenko } 85784cdf93SMykyta Yatsenko 86784cdf93SMykyta Yatsenko memcpy(skel->bss->user_buf, file_contents, sizeof(file_contents)); 87784cdf93SMykyta Yatsenko skel->bss->pid = getpid(); 88784cdf93SMykyta Yatsenko 89784cdf93SMykyta Yatsenko err = file_reader__load(skel); 90784cdf93SMykyta Yatsenko if (!ASSERT_OK(err, "file_reader__load")) 91784cdf93SMykyta Yatsenko goto cleanup; 92784cdf93SMykyta Yatsenko 93784cdf93SMykyta Yatsenko err = file_reader__attach(skel); 94784cdf93SMykyta Yatsenko if (!ASSERT_OK(err, "file_reader__attach")) 95784cdf93SMykyta Yatsenko goto cleanup; 96784cdf93SMykyta Yatsenko 97784cdf93SMykyta Yatsenko fd = open("/proc/self/exe", O_RDONLY); 98784cdf93SMykyta Yatsenko if (fd >= 0) 99784cdf93SMykyta Yatsenko close(fd); 100784cdf93SMykyta Yatsenko 101784cdf93SMykyta Yatsenko ASSERT_EQ(skel->bss->err, 0, "err"); 102784cdf93SMykyta Yatsenko ASSERT_EQ(skel->bss->run_success, 1, "run_success"); 103784cdf93SMykyta Yatsenko cleanup: 104784cdf93SMykyta Yatsenko file_reader__destroy(skel); 105784cdf93SMykyta Yatsenko } 106784cdf93SMykyta Yatsenko 107784cdf93SMykyta Yatsenko void test_file_reader(void) 108784cdf93SMykyta Yatsenko { 109784cdf93SMykyta Yatsenko if (test__start_subtest("on_open_expect_fault")) 110784cdf93SMykyta Yatsenko run_test("on_open_expect_fault"); 111784cdf93SMykyta Yatsenko 112784cdf93SMykyta Yatsenko if (test__start_subtest("on_open_validate_file_read")) 113784cdf93SMykyta Yatsenko run_test("on_open_validate_file_read"); 114784cdf93SMykyta Yatsenko 115784cdf93SMykyta Yatsenko if (test__start_subtest("negative")) 116784cdf93SMykyta Yatsenko RUN_TESTS(file_reader_fail); 117784cdf93SMykyta Yatsenko } 118