Skip to content

Commit

Permalink
runtime: enable syscall server to load and run cross boundary program…
Browse files Browse the repository at this point in the history
…s. (#117)

* impl run_with_kernel

* add prog relocate

* update syscall context

---------

Co-authored-by: victoryang00 <[email protected]>
  • Loading branch information
yunwei37 and victoryang00 authored Dec 2, 2023
1 parent 2bcf61f commit c31904c
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 29 deletions.
2 changes: 2 additions & 0 deletions daemon/user/bpftime_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ int bpftime_driver::bpftime_maps_create_server(int kernel_id)
SPDLOG_INFO("create map in kernel id {}", kernel_id);
return kernel_id;
}

int bpftime_driver::bpftime_attach_perf_to_bpf_fd_server(int server_pid,
int perf_fd,
int bpf_prog_fd)
Expand All @@ -256,6 +257,7 @@ int bpftime_driver::bpftime_attach_perf_to_bpf_fd_server(int server_pid,
}
return bpftime_attach_perf_to_bpf_server(server_pid, perf_fd, prog_id);
}

int bpftime_driver::bpftime_attach_perf_to_bpf_server(int server_pid,
int perf_fd,
int kernel_bpf_id)
Expand Down
2 changes: 1 addition & 1 deletion example/malloc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ LD_PRELOAD=build/runtime/syscall-server/libbpftime-syscall-server.so example/mal
client

```sh
LD_PRELOAD=build/runtime/agent/libbpftime-agent.so example/malloc/test
LD_PRELOAD=build/runtime/agent/libbpftime-agent.so example/malloc/victim
```
2 changes: 1 addition & 1 deletion runtime/include/bpftime_shm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ void *bpftime_get_ringbuf_producer_page(int ringbuf_fd);
int bpftime_is_ringbuf_map(int fd);
int bpftime_is_array_map(int fd);
int bpftime_is_epoll_handler(int fd);

int bpftime_is_perf_event_fd(int fd);
int bpftime_is_prog_fd(int fd);
int bpftime_is_map_fd(int fd);

Expand Down
4 changes: 4 additions & 0 deletions runtime/src/bpftime_shm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ int bpftime_is_map_fd(int fd)
return shm_holder.global_shared_memory.is_map_fd(fd);
}

int bpftime_is_perf_event_fd(int fd) {
return shm_holder.global_shared_memory.is_perf_event_handler_fd(fd);
}

int bpftime_is_prog_fd(int fd)
{
return shm_holder.global_shared_memory.is_prog_fd(fd);
Expand Down
25 changes: 14 additions & 11 deletions runtime/src/bpftime_shm_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ int bpftime_shm::add_uprobe(int fd, int pid, const char *name, uint64_t offset,
// if fd is negative, we need to create a new fd for allocating
fd = open_fake_fd();
}
SPDLOG_DEBUG("Set fd {} to uprobe, pid={}, name={}, offset={}", fd,
pid, name, offset);
SPDLOG_DEBUG("Set fd {} to uprobe, pid={}, name={}, offset={}", fd, pid,
name, offset);
return manager->set_handler(
fd,
bpftime::bpf_perf_event_handler{ retprobe, offset, pid, name,
Expand All @@ -157,7 +157,7 @@ int bpftime_shm::add_uprobe_override(int fd, int pid, const char *name,
fd = open_fake_fd();
}
SPDLOG_DEBUG("Set fd {} to ureplace, pid={}, name={}, offset={}", fd,
pid, name, offset);
pid, name, offset);
if (is_replace) {
return manager->set_handler(
fd,
Expand All @@ -168,9 +168,9 @@ int bpftime_shm::add_uprobe_override(int fd, int pid, const char *name,
} else {
return manager->set_handler(
fd,
bpf_perf_event_handler(bpf_event_type::BPF_TYPE_UPROBE_OVERRIDE,
offset, pid, name, segment,
true),
bpf_perf_event_handler(
bpf_event_type::BPF_TYPE_UPROBE_OVERRIDE,
offset, pid, name, segment, true),
segment);
}
}
Expand Down Expand Up @@ -210,8 +210,7 @@ int bpftime_shm::attach_perf_to_bpf(int perf_fd, int bpf_fd)

int bpftime_shm::add_bpf_prog_attach_target(int perf_fd, int bpf_fd)
{
SPDLOG_DEBUG("Try attaching prog fd {} to perf fd {}", bpf_fd,
perf_fd);
SPDLOG_DEBUG("Try attaching prog fd {} to perf fd {}", bpf_fd, perf_fd);
if (!is_prog_fd(bpf_fd)) {
SPDLOG_ERROR("Fd {} is not a prog fd", bpf_fd);
errno = ENOENT;
Expand Down Expand Up @@ -307,12 +306,12 @@ int bpftime_shm::add_ringbuf_to_epoll(int ringbuf_fd, int epoll_fd,
epoll_inst.files.emplace_back(val->create_impl_weak_ptr(),
extra_data);
SPDLOG_DEBUG("Ringbuf {} added to epoll {}", ringbuf_fd,
epoll_fd);
epoll_fd);
return 0;
} else {
errno = EINVAL;
SPDLOG_ERROR("Map fd {} is expected to be an ringbuf map",
ringbuf_fd);
ringbuf_fd);
return -1;
}
}
Expand Down Expand Up @@ -595,7 +594,7 @@ bpftime_shm::bpftime_shm(bpftime::shm_open_type type)
: bpftime_shm(bpftime::get_global_shm_name(), type)
{
SPDLOG_INFO("Global shm constructed. shm_open_type {} for {}",
(int)type, bpftime::get_global_shm_name());
(int)type, bpftime::get_global_shm_name());
}

int bpftime_shm::add_bpf_map(int fd, const char *name,
Expand Down Expand Up @@ -631,6 +630,10 @@ const handler_manager *bpftime_shm::get_manager() const

bool bpftime_shm::is_perf_event_handler_fd(int fd) const
{
if (manager == nullptr || fd < 0 ||
(std::size_t)fd >= manager->size()) {
return false;
}
auto &handler = get_handler(fd);
return std::holds_alternative<bpf_perf_event_handler>(handler);
}
Expand Down
39 changes: 39 additions & 0 deletions runtime/syscall-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# syscall_server.so

Use as a LD_PRELOAD to intercept bpf syscalls and mock them in userspace, or trace them and make kernel eBPF run with userspace eBPF.

## Run with userspace eBPF

The default behavior is to run with userspace eBPF. Using userspace eBPF means using userspace eBPF maps in shared memory, using userspace eBPF verifier and userspace eBPF runtime.

server

```sh
LD_PRELOAD=build/runtime/syscall-server/libbpftime-syscall-server.so example/malloc/malloc
```

client

```sh
LD_PRELOAD=build/runtime/agent/libbpftime-agent.so example/malloc/victim
```

## run with kernel

Set the environment variable `BPFTIME_RUN_WITH_KERNEL` to `true` to make the kernel eBPF run with userspace eBPF. This means using kernel eBPF maps instead of userspace eBPF maps, and using kernel eBPF verifier instead of userspace eBPF verifier.

```sh
BPFTIME_RUN_WITH_KERNEL=true
```

example start tracing:

```sh
SPDLOG_LEVEL=Debug BPFTIME_RUN_WITH_KERNEL=true LD_PRELOAD=build/runtime/syscall-server/libbpftime-syscall-server.so example/malloc/malloc
```

example run target program:

```sh
SPDLOG_LEVEL=Debug LD_PRELOAD=build/runtime/agent/libbpftime-agent.so example/malloc/victim
```
Loading

0 comments on commit c31904c

Please sign in to comment.