From a9598f8cd6c9469d724cd9ee871bffd6ee685ad0 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Wed, 28 Aug 2024 01:34:17 +0800 Subject: [PATCH] almost working --- runtime/syscall-server/syscall-server.version | 2 +- runtime/syscall-server/syscall_context.cpp | 31 +++++++++++++ runtime/syscall-server/syscall_context.hpp | 11 ++++- .../syscall-server/syscall_server_main.cpp | 45 +++++++++++++++++-- 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/runtime/syscall-server/syscall-server.version b/runtime/syscall-server/syscall-server.version index b386f9d0..00cf6f8a 100644 --- a/runtime/syscall-server/syscall-server.version +++ b/runtime/syscall-server/syscall-server.version @@ -1,4 +1,4 @@ { - global: epoll_wait; epoll_ctl; epoll_create1; ioctl; mmap64; mmap; close; syscall; munmap; + global: epoll_wait; epoll_ctl; epoll_create1; ioctl; mmap64; mmap; close; syscall; munmap; open; openat; read; fopen; fopen64; _IO_new_fopen; local: *; }; diff --git a/runtime/syscall-server/syscall_context.cpp b/runtime/syscall-server/syscall_context.cpp index 343a7c4d..95feefff 100644 --- a/runtime/syscall-server/syscall_context.cpp +++ b/runtime/syscall-server/syscall_context.cpp @@ -5,6 +5,7 @@ */ #include "bpftime_logger.hpp" #include "bpftime_shm.hpp" +#include #include #include "syscall_context.hpp" #include "handler/map_handler.hpp" @@ -810,3 +811,33 @@ int syscall_context::handle_munmap(void *addr, size_t size) return orig_munmap_fn(addr, size); } } + +FILE *syscall_context::handle_fopen(const char *pathname, const char *flags) +{ + if (!enable_mock) + return orig_fopen_fn(pathname, flags); + try_startup(); + if (auto mocker = create_mocked_file_based_on_full_path(pathname); + mocker) { + bpftime_lock_guard _guard(this->mocked_file_lock); + char filename_buf[] = "/tmp/bpftime-mock.XXXXXX"; + int fake_fd = mkstemp(filename_buf); + if (fake_fd < 0) { + SPDLOG_WARN("Unable to create mock fd: {}", errno); + return orig_fopen_fn(pathname, flags); + } + auto itr = + this->mocked_files.emplace(fake_fd, std::move(*mocker)) + .first; + FILE *replacement_fp = fopen(filename_buf, "r"); + + itr->second->replacement_file = replacement_fp; + auto size_written = write(fake_fd, itr->second->buf.c_str(), + itr->second->buf.size()); + SPDLOG_DEBUG( + "Created fake fd {}, replacement fp {:x}, written {} bytes", + fake_fd, (uintptr_t)replacement_fp, size_written); + return replacement_fp; + } + return orig_fopen_fn(pathname, flags); +} diff --git a/runtime/syscall-server/syscall_context.hpp b/runtime/syscall-server/syscall_context.hpp index a6614b2b..c20e4b4d 100644 --- a/runtime/syscall-server/syscall_context.hpp +++ b/runtime/syscall-server/syscall_context.hpp @@ -32,6 +32,7 @@ struct mocked_file_provider { int cursor = 0; std::string buf; pthread_spinlock_t access_lock; + FILE *replacement_file = nullptr; mocked_file_provider(std::string buf) : buf(buf) { pthread_spin_init(&access_lock, 0); @@ -60,6 +61,8 @@ class syscall_context { using openat_fn = int (*)(int, const char *, int, ...); using open_fn = int (*)(const char *, int, ...); using read_fn = ssize_t (*)(int fd, void *buf, size_t count); + using fopen_fn = FILE *(*)(const char *, const char *); + close_fn orig_close_fn = nullptr; mmap64_fn orig_mmap64_fn = nullptr; ioctl_fn orig_ioctl_fn = nullptr; @@ -71,6 +74,8 @@ class syscall_context { open_fn orig_open_fn = nullptr; mmap_fn orig_mmap_fn = nullptr; read_fn orig_read_fn = nullptr; + fopen_fn orig_fopen_fn = nullptr; + std::unordered_set mocked_mmap_values; pthread_spinlock_t mocked_file_lock; std::unordered_map > @@ -91,6 +96,8 @@ class syscall_context { (mmap_fn)dlsym(RTLD_NEXT, "mmap"); orig_openat_fn = (openat_fn)dlsym(RTLD_NEXT, "openat"); orig_open_fn = (open_fn)dlsym(RTLD_NEXT, "open"); + orig_fopen_fn = (fopen_fn)dlsym(RTLD_NEXT, "fopen"); + // To avoid polluting other child processes, // unset the LD_PRELOAD env var after syscall context being // initialized @@ -103,7 +110,8 @@ class syscall_context { (uintptr_t)orig_ioctl_fn, (uintptr_t)orig_syscall_fn, (uintptr_t)orig_mmap64_fn, (uintptr_t)orig_close_fn, (uintptr_t)orig_munmap_fn, (uintptr_t)orig_mmap_fn, - (uintptr_t)orig_openat_fn, (uintptr_t)orig_open_fn); + (uintptr_t)orig_openat_fn, (uintptr_t)orig_open_fn, + (uintptr_t)orig_fopen_fn); } int create_kernel_bpf_map(int fd); @@ -153,6 +161,7 @@ class syscall_context { unsigned short mode); int handle_open(const char *file, int oflag, unsigned short mode); ssize_t handle_read(int fd, void *buf, size_t count); + FILE *handle_fopen(const char *pathname, const char *flags); }; #endif diff --git a/runtime/syscall-server/syscall_server_main.cpp b/runtime/syscall-server/syscall_server_main.cpp index a6d5d703..37f190a3 100644 --- a/runtime/syscall-server/syscall_server_main.cpp +++ b/runtime/syscall-server/syscall_server_main.cpp @@ -4,7 +4,8 @@ * All rights reserved. */ #include "syscall_context.hpp" -#include "bpftime_shm.hpp" +#include +#include #if __linux__ #include "linux/bpf.h" #include @@ -16,8 +17,6 @@ #include #include #include -using namespace bpftime; - // global context for bpf syscall server static syscall_context context; @@ -123,6 +122,46 @@ extern "C" ssize_t read(int fd, void *buf, size_t count) { return context.handle_read(fd, buf, count); } + +extern "C" FILE *fopen(const char *pathname, const char *flags) +{ + SPDLOG_DEBUG("fopen {} {}", pathname, flags); + return context.handle_fopen(pathname, flags); +} +extern "C" FILE *fopen64(const char *pathname, const char *flags) +{ + SPDLOG_DEBUG("fopen64 {} {}", pathname, flags); + return context.handle_fopen(pathname, flags); +} +extern "C" FILE *_IO_new_fopen(const char *pathname, const char *flags) +{ + SPDLOG_DEBUG("_IO_new_fopen {} {}", pathname, flags); + return context.handle_fopen(pathname, flags); +} +// extern "C" int fclose(FILE *f) +// { +// SPDLOG_DEBUG("fclose {:x}", (uintptr_t)f); +// return context.handle_fclose(f); +// } +// extern "C" int fscanf(FILE *fp, const char *fmt, ...) +// { +// SPDLOG_DEBUG("fscanf {:x} {}", (uintptr_t)fp, fmt); +// va_list args; +// va_start(args, fmt); +// int result = context.handle_fscanf(fp, fmt, args); +// va_end(args); +// return result; +// } + +// extern "C" int __isoc99_fscanf(FILE *fp, const char *fmt, ...) +// { +// SPDLOG_DEBUG("__isoc99_fscanf {:x} {}", (uintptr_t)fp, fmt); +// va_list args; +// va_start(args, fmt); +// int result = context.handle_fscanf(fp, fmt, args); +// va_end(args); +// return result; +// } #if __linux__ extern "C" long syscall(long sysno, ...) {