Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: add mpk support #86

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/test-runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ jobs:

- name: test runtime
run: make unit-test

- name: build runtime with mpk enable
run: |
make clean
cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=0 \
-DCMAKE_BUILD_TYPE:STRING=Release \
-DBPFTIME_ENABLE_LTO=0 -DBPFTIME_ENABLE_MPK=1
cmake --build build --config Release
- name: test runtime with mpk
run: make unit-test
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ documents/dlsym/dlsym
documents/elfoffset/myprogram
documents/elfoffset/*.txt
documents/elfoffset/maps
Catch2
libebpf.off.txt
test/pyvenv.cfg
ecli
Expand Down
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
"name": "(gdb) runtime",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/example/malloc/test",
"program": "${workspaceFolder}/example/malloc/victim",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}/build/runtime/test/",
"cwd": "${workspaceFolder}/",
"environment": [
{
"name": "LD_PRELOAD",
"value": "/home/yunwei/bpftime/build/runtime/agent/libbpftime-agent.so"
"value": "${workspaceFolder}/build/runtime/agent/libbpftime-agent.so"
},
// {
// "name": "LD_PRELOAD",
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

`bpftime`, a full-featured, high-performance eBPF runtime designed to operate in userspace. It offers fast Uprobe and Syscall hook capabilities: Userspace uprobe can be **10x faster than kernel uprobe!** and can programmatically **hook all syscalls of a process** safely and efficiently.

📦 [Features](#key-features) \
📦 [Key Features](#key-features) \
🔨 [Quick Start](#quick-start) \
⌨️ [Linux Plumbers 23 talk](https://lpc.events/event/17/contributions/1639/) \
📖 [Slides](https://github.com/eunomia-bpf/bpftime/tree/master/documents/userspace-ebpf-bpftime-lpc.pdf) \
Expand Down Expand Up @@ -144,12 +144,12 @@ see [arxiv preprint: https://arxiv.org/abs/2311.07923](https://arxiv.org/abs/231

How is the performance of `userspace uprobe` compared to `kernel uprobes`?

| Probe/Tracepoint Types | Kernel (ns) | Userspace (ns) | Insn Count |
|------------------------|-------------:|---------------:|---------------:|
| Uprobe | 3224.172760 | 314.569110 | 4 |
| Uretprobe | 3996.799580 | 381.270270 | 2 |
| Syscall Tracepoint | 151.82801 | 232.57691 | 4 |
| Embedding runtime | Not avaliable | 110.008430 | 4 |
| Probe/Tracepoint Types | Kernel (ns) | Userspace (ns) |
|------------------------|-------------:|---------------:|
| Uprobe | 3224.172760 | 314.569110 |
| Uretprobe | 3996.799580 | 381.270270 |
| Syscall Tracepoint | 151.82801 | 232.57691 |
| Embedding runtime | Not avaliable | 110.008430 |

It can be attached to functions in running process just like the kernel uprobe does.

Expand Down
5 changes: 5 additions & 0 deletions runtime/include/bpftime_shm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ void bpftime_destroy_global_shm();
// remove the global shared memory from system
void bpftime_remove_global_shm();

// enable memory protect, e.g. mpk
void bpftime_protect_enable();
// disable memory protect
void bpftime_protect_disable();

// import the global shared memory from json file
int bpftime_import_global_shm_from_json(const char *filename);
// export the global shared memory to json file
Expand Down
2 changes: 2 additions & 0 deletions runtime/src/attach/bpf_attach_ctx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ bool bpf_attach_ctx::check_syscall_trace_setup(int pid)
{
return shm_holder.global_shared_memory.check_syscall_trace_setup(pid);
}

// Set whether a certain pid was already equipped with syscall tracer
// Using a set stored in the shared memory
void bpf_attach_ctx::set_syscall_trace_setup(int pid, bool whether)
Expand Down Expand Up @@ -519,4 +520,5 @@ bpf_attach_ctx::bpf_attach_ctx(void)
spdlog::debug("Initialzing frida gum");
current_id = CURRENT_ID_OFFSET;
}

} // namespace bpftime
4 changes: 4 additions & 0 deletions runtime/src/bpf_map/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# bpf maps source

- shared: maps between kernel and userspace
- userspace: maps runs only in userspace
4 changes: 4 additions & 0 deletions runtime/src/bpftime_prog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ int bpftime_prog::bpftime_prog_exec(void *memory, size_t memory_size,
{
uint64_t val = 0;
int res = 0;
// set share memory read and write able
bpftime_protect_disable();
spdlog::debug(
"Calling bpftime_prog::bpftime_prog_exec, memory={:x}, memory_size={}, return_val={:x}, prog_name={}",
(uintptr_t)memory, memory_size, (uintptr_t)return_val,
Expand All @@ -88,6 +90,8 @@ int bpftime_prog::bpftime_prog_exec(void *memory, size_t memory_size,
}
}
*return_val = val;
// set share memory read only
bpftime_protect_enable();
return res;
}

Expand Down
13 changes: 13 additions & 0 deletions runtime/src/bpftime_shm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ long bpftime_map_delete_elem(int fd, const void *key)
{
return shm_holder.global_shared_memory.bpf_delete_elem(fd, key, true);
}

int bpftime_map_get_next_key(int fd, const void *key, void *next_key)
{
return shm_holder.global_shared_memory.bpf_map_get_next_key(
Expand Down Expand Up @@ -156,6 +157,18 @@ int bpftime_is_ringbuf_map(int fd)
return shm_holder.global_shared_memory.is_ringbuf_map_fd(fd);
}

void bpftime_protect_enable() {
#if BPFTIME_ENABLE_MPK
return shm_holder.global_shared_memory.enable_mpk();
#endif
}

void bpftime_protect_disable() {
#if BPFTIME_ENABLE_MPK
return shm_holder.global_shared_memory.disable_mpk();
#endif
}

int bpftime_is_map_fd(int fd)
{
return shm_holder.global_shared_memory.is_map_fd(fd);
Expand Down
40 changes: 40 additions & 0 deletions runtime/src/bpftime_shm_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <sys/epoll.h>
#include <unistd.h>
#include <variant>
#include <sys/mman.h>

static bool global_shm_initialized = false;

Expand Down Expand Up @@ -432,6 +433,28 @@ void bpftime_shm::close_fd(int fd)
}
}

#if BPFTIME_ENABLE_MPK
void bpftime_shm::enable_mpk()
{
if (manager == nullptr|| !is_mpk_init) {
return;
}
if (pkey_set(pkey, PKEY_DISABLE_WRITE) == -1) {
spdlog::error("pkey_set read only failed");
}
}

void bpftime_shm::disable_mpk()
{
if (manager == nullptr || !is_mpk_init) {
return;
}
if (pkey_set(pkey, 0) == -1) {
spdlog::error("pkey_set disable failed");
}
}
#endif

bool bpftime_shm::is_exist_fake_fd(int fd) const
{
if (manager == nullptr || fd < 0 ||
Expand Down Expand Up @@ -518,6 +541,23 @@ bpftime_shm::bpftime_shm(const char *shm_name, shm_open_type type)
"NOT creating global shm. This is only for testing purpose.");
return;
}

#if BPFTIME_ENABLE_MPK
// init mpk key
pkey = pkey_alloc(0, PKEY_DISABLE_WRITE);
if (pkey == -1) {
spdlog::error("pkey_alloc failed");
return;
}

// protect shm segment
if (pkey_mprotect(segment.get_address(), segment.get_size(),
PROT_READ | PROT_WRITE, pkey) == -1) {
spdlog::error("pkey_mprotect failed");
return;
}
is_mpk_init = true;
#endif
}

bpftime_shm::bpftime_shm(bpftime::shm_open_type type)
Expand Down
11 changes: 11 additions & 0 deletions runtime/src/bpftime_shm_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class bpftime_shm {
// Configuration for the agent. e.g, which helpers are enabled
struct bpftime::agent_config *agent_config = nullptr;

#if BPFTIME_ENABLE_MPK
// mpk key for protect shm
bool is_mpk_init = false;
int pkey = 0;
#endif

public:
// Get the configuration object
const struct agent_config &get_agent_config()
Expand Down Expand Up @@ -126,6 +132,11 @@ class bpftime_shm {
void close_fd(int fd);
bool is_exist_fake_fd(int fd) const;

#if BPFTIME_ENABLE_MPK
void enable_mpk();
void disable_mpk();
#endif

// initialize the shared memory globally
bpftime_shm(bpftime::shm_open_type type);
// initialize the shared memory with a given name
Expand Down