From 722411cb42fcf14a98cc79b4f222312d7803a723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E5=BE=AE?= <1067852565@qq.com> Date: Mon, 20 Nov 2023 20:05:46 -0800 Subject: [PATCH] docs: add documents of how to use JIT (#98) * fix lock for array * add spinlock * use pthread spinlock --- daemon/kernel/bpf_tracer.bpf.c | 6 ++-- daemon/user/handle_bpf_event.cpp | 2 +- documents/usage.md | 8 ++++++ example/sslsniff/README.md | 31 +++++++++++++++++++-- runtime/src/bpf_map/userspace/array_map.hpp | 2 +- runtime/src/bpf_map/userspace/hash_map.cpp | 2 ++ runtime/src/bpf_map/userspace/hash_map.hpp | 7 ++--- runtime/src/bpftime_shm_internal.hpp | 1 + runtime/src/handler/map_handler.cpp | 21 +++++--------- runtime/src/handler/map_handler.hpp | 30 ++++++++++++++++---- 10 files changed, 80 insertions(+), 30 deletions(-) diff --git a/daemon/kernel/bpf_tracer.bpf.c b/daemon/kernel/bpf_tracer.bpf.c index 11dda8c3..b1364aab 100644 --- a/daemon/kernel/bpf_tracer.bpf.c +++ b/daemon/kernel/bpf_tracer.bpf.c @@ -398,11 +398,13 @@ process_perf_event_open_enter(struct trace_event_raw_sys_enter *ctx) return 0; } bpf_probe_read_user(&new_attr_buffer, sizeof(new_attr_buffer), attr); - struct perf_event_attr* new_attr_pointer = &new_attr_buffer; + struct perf_event_attr *new_attr_pointer = + (struct perf_event_attr *)&new_attr_buffer; if (new_attr_pointer->type == uprobe_perf_type) { // found uprobe if (enable_replace_uprobe) { - if (can_hook_uprobe_at(new_attr_pointer->probe_offset)) { + if (can_hook_uprobe_at( + new_attr_pointer->probe_offset)) { u64 old_offset = new_attr_pointer->probe_offset; new_attr_pointer->probe_offset = 0; long size = bpf_probe_read_user_str( diff --git a/daemon/user/handle_bpf_event.cpp b/daemon/user/handle_bpf_event.cpp index 605c2016..b6d62ee3 100644 --- a/daemon/user/handle_bpf_event.cpp +++ b/daemon/user/handle_bpf_event.cpp @@ -283,7 +283,7 @@ int bpf_event_handler::handle_perf_event_open(const struct event *e) spdlog::debug("handle_perf_event"); const char *type_id_str = "UNKNOWN TYPE"; unsigned int perf_type = e->perf_event_data.attr.type; - if (perf_type >= 0 && perf_type < (sizeof(perf_type_id_strings) / + if (perf_type < (sizeof(perf_type_id_strings) / sizeof(perf_type_id_strings[0]))) { type_id_str = perf_type_id_strings[perf_type]; } diff --git a/documents/usage.md b/documents/usage.md index 509f0e8a..43a2298a 100644 --- a/documents/usage.md +++ b/documents/usage.md @@ -2,6 +2,14 @@ It's at a very early stage and may contain bugs on more platforms and eBPF programs. +## Run with JIT enabled + +Set `BPFTIME_USE_JIT=true` in the server to enable JIT, for example, when running the server: + +```sh +LD_PRELOAD=~/.bpftime/libbpftime-syscall-server.so BPFTIME_USE_JIT=true example/malloc/malloc +``` + ## Uprobe and uretprobe With `bpftime`, you can build eBPF applications using familiar tools like clang and libbpf, and execute them in userspace. For instance, the `malloc` eBPF program traces malloc calls using uprobe and aggregates the counts using a hash map. diff --git a/example/sslsniff/README.md b/example/sslsniff/README.md index 609c46a1..c83cba9f 100644 --- a/example/sslsniff/README.md +++ b/example/sslsniff/README.md @@ -1,5 +1,32 @@ # sslsniff -Not working because we refactored the runtime. +## Run the probe -TODO: make the ring buffer work again. +```sh +sudo LD_PRELOAD=build/runtime/syscall-server/libbpftime-syscal +l-server.so example/sslsniff/sslsniff +``` + +## run the example + +```sh +sudo LD_PRELOAD=build/runtime/agent/libbpftime-agent.so wget https://www.google.com +``` + +## Output + +```txt +----- DATA ----- +gle.erd={jsr:1,bv:1904,de:true}; +var h=this||self;var k,l=null!=(k=h.mei)?k:1,n,p=null!=(n=h.sdo)?n:!0,q=0,r,t=google.erd,v=t.jsr;google.ml=function(a,b,d,m,e){e=void 0===e?2:e;b&&(r=a&&a.message);void 0===d&&(d={});d.cad="ple_"+google.ple+".aple_"+google.aple;if(google.dl)return google.dl(a,e,d),null;if(0>v){window.console&&console.error(a,d);if(-2===v)throw a;b=!1}else b=!a||!a.message||"Error loading script"===a.message||q>=l&&!m?!1:!0;if(!b)return null;q++;d=d||{};b=encodeURIComponent;var c="/gen_204?atyp=i&ei="+b(google.kEI);google.kEXPI&&(c+="&jexpid="+b(google.kEXPI));c+="&srcpg="+b(google.sn)+"&jsr="+b(t.jsr)+"&bver="+ +b(t.bv);var f=a.lineNumber;void 0!==f&&(c+="&line="+f);var g=a.fileName;g&&(0=l&&(window.onerror=null)};})();
Search Images Maps Play YouTube News Gmail Drive +----- END DATA ----- +``` \ No newline at end of file diff --git a/runtime/src/bpf_map/userspace/array_map.hpp b/runtime/src/bpf_map/userspace/array_map.hpp index fdd6350c..e6b0fc6a 100644 --- a/runtime/src/bpf_map/userspace/array_map.hpp +++ b/runtime/src/bpf_map/userspace/array_map.hpp @@ -17,7 +17,7 @@ class array_map_impl { uint32_t _max_entries; public: - const static bool should_lock = true; + const static bool should_lock = false; array_map_impl(boost::interprocess::managed_shared_memory &memory, uint32_t value_size, uint32_t max_entries); diff --git a/runtime/src/bpf_map/userspace/hash_map.cpp b/runtime/src/bpf_map/userspace/hash_map.cpp index 446c71ba..3f217eb9 100644 --- a/runtime/src/bpf_map/userspace/hash_map.cpp +++ b/runtime/src/bpf_map/userspace/hash_map.cpp @@ -11,6 +11,7 @@ namespace bpftime { + hash_map_impl::hash_map_impl(managed_shared_memory &memory, uint32_t key_size, uint32_t value_size) : map_impl(10, bytes_vec_hasher(), std::equal_to(), @@ -20,6 +21,7 @@ hash_map_impl::hash_map_impl(managed_shared_memory &memory, uint32_t key_size, value_vec(value_size, memory.get_segment_manager()) { } + void *hash_map_impl::elem_lookup(const void *key) { spdlog::trace("Peform elem lookup of hash map"); diff --git a/runtime/src/bpf_map/userspace/hash_map.hpp b/runtime/src/bpf_map/userspace/hash_map.hpp index 8a7ce9eb..fdc51c7c 100644 --- a/runtime/src/bpf_map/userspace/hash_map.hpp +++ b/runtime/src/bpf_map/userspace/hash_map.hpp @@ -18,16 +18,15 @@ namespace bpftime using namespace boost::interprocess; - // implementation of hash map class hash_map_impl { using bi_map_value_ty = std::pair; using bi_map_allocator = allocator; - using shm_hash_map = boost::unordered_map< - bytes_vec, bytes_vec, bytes_vec_hasher, - std::equal_to, bi_map_allocator>; + using shm_hash_map = + boost::unordered_map, bi_map_allocator>; shm_hash_map map_impl; uint32_t _key_size; uint32_t _value_size; diff --git a/runtime/src/bpftime_shm_internal.hpp b/runtime/src/bpftime_shm_internal.hpp index cb597348..2b8c5c52 100644 --- a/runtime/src/bpftime_shm_internal.hpp +++ b/runtime/src/bpftime_shm_internal.hpp @@ -14,6 +14,7 @@ #include "bpftime_config.hpp" #include #include + namespace bpftime { diff --git a/runtime/src/handler/map_handler.cpp b/runtime/src/handler/map_handler.cpp index 31612c87..cce76db1 100644 --- a/runtime/src/handler/map_handler.cpp +++ b/runtime/src/handler/map_handler.cpp @@ -55,8 +55,7 @@ const void *bpf_map_handler::map_lookup_elem(const void *key, { const auto do_lookup = [&](auto *impl) -> const void * { if (impl->should_lock) { - sharable_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_lookup(key); } else { return impl->elem_lookup(key); @@ -64,8 +63,7 @@ const void *bpf_map_handler::map_lookup_elem(const void *key, }; const auto do_lookup_userspace = [&](auto *impl) -> const void * { if (impl->should_lock) { - sharable_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_lookup_userspace(key); } else { return impl->elem_lookup_userspace(key); @@ -133,8 +131,7 @@ long bpf_map_handler::map_update_elem(const void *key, const void *value, { const auto do_update = [&](auto *impl) -> long { if (impl->should_lock) { - scoped_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_update(key, value, flags); } else { return impl->elem_update(key, value, flags); @@ -143,8 +140,7 @@ long bpf_map_handler::map_update_elem(const void *key, const void *value, const auto do_update_userspace = [&](auto *impl) -> long { if (impl->should_lock) { - scoped_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_update_userspace(key, value, flags); } else { return impl->elem_update_userspace(key, value, flags); @@ -211,8 +207,7 @@ int bpf_map_handler::bpf_map_get_next_key(const void *key, void *next_key, { const auto do_get_next_key = [&](auto *impl) -> int { if (impl->should_lock) { - sharable_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->map_get_next_key(key, next_key); } else { return impl->map_get_next_key(key, next_key); @@ -277,8 +272,7 @@ long bpf_map_handler::map_delete_elem(const void *key, { const auto do_delete = [&](auto *impl) -> long { if (impl->should_lock) { - scoped_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_delete(key); } else { return impl->elem_delete(key); @@ -286,8 +280,7 @@ long bpf_map_handler::map_delete_elem(const void *key, }; const auto do_delete_userspace = [&](auto *impl) -> long { if (impl->should_lock) { - scoped_lock guard( - *map_mutex); + bpftime_lock_guard guard(map_lock); return impl->elem_delete_userspace(key); } else { return impl->elem_delete_userspace(key); diff --git a/runtime/src/handler/map_handler.hpp b/runtime/src/handler/map_handler.hpp index f81eac87..e8b32aab 100644 --- a/runtime/src/handler/map_handler.hpp +++ b/runtime/src/handler/map_handler.hpp @@ -30,6 +30,28 @@ using boost_shm_string = using sharable_mutex_ptr = boost::interprocess::managed_unique_ptr< boost::interprocess::interprocess_sharable_mutex, boost::interprocess::managed_shared_memory>::type; + +// lock guad for RAII +class bpftime_lock_guard { + private: + volatile pthread_spinlock_t &spinlock; + + public: + explicit bpftime_lock_guard(volatile pthread_spinlock_t &spinlock) + : spinlock(spinlock) + { + pthread_spin_lock(&spinlock); + } + ~bpftime_lock_guard() + { + pthread_spin_unlock(&spinlock); + } + + // Delete copy constructor and assignment operator + bpftime_lock_guard(const bpftime_lock_guard &) = delete; + bpftime_lock_guard &operator=(const bpftime_lock_guard &) = delete; +}; + // bpf map handler // all map data will be put on shared memory, so it can be accessed by // different processes @@ -52,16 +74,12 @@ class bpf_map_handler { boost::interprocess::managed_shared_memory &mem) : type((bpf_map_type)type), name(char_allocator(mem.get_segment_manager())), - map_mutex(boost::interprocess::make_managed_unique_ptr( - mem.construct( - boost::interprocess::anonymous_instance)(), - mem)), map_impl_ptr(nullptr), max_entries(max_ents), flags(flags), key_size(key_size), value_size(value_size) { spdlog::debug("Create map with type {}", type); + pthread_spin_init(&map_lock, 0); this->name = name; } bpf_map_handler(const bpf_map_handler &) = delete; @@ -171,7 +189,7 @@ class bpf_map_handler { private: std::string get_container_name(); - mutable sharable_mutex_ptr map_mutex; + mutable pthread_spinlock_t map_lock; // The underlying data structure of the map general_map_impl_ptr map_impl_ptr; uint32_t max_entries = 0;