Skip to content
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
4 changes: 2 additions & 2 deletions docs/hostisolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ These binaries can be used to demo/test host isolation locally as follows:

1. Build the repository
2. Run `cd <build directory>/target/ebpf`
3. Run `sudo ../../non-GPL/TcLoader/TcLoaderDemo` - packet filter is now attached to ens33
3. Run `sudo ../../non-GPL/TcLoader/TcLoaderDemo <iface>` - packet filter is now attached to `<iface>` (e.g. `ens33`)
4. Run `sudo ../../non-GPL/HostIsolation/KprobeConnectHook/KprobeConnectHookDemo` - connect hook is attached
5. Run `firefox` in another tab - verify that all internet access is blocked
6. Run `pgrep firefox` to get the PID of the browser
7. Run `sudo ../../non-GPL/HostIsolationMapsUtil/UpdatePidsDemo <firefox PID>`
8. Verify that firefox connects to any page
9. Quit KprobeConnectHook with Ctrl+C and run `sudo ../../non-GPL/TcLoader/TcLoaderDemo unload` to detach both eBPF programs
9. Quit KprobeConnectHook with Ctrl+C and run `sudo ../../non-GPL/TcLoader/TcLoaderDemo <iface> unload` to detach both eBPF programs

## Tests

Expand Down
58 changes: 33 additions & 25 deletions non-GPL/HostIsolation/Demos/KprobeConnectHookDemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,26 @@
#include <time.h>
#include <unistd.h>

#include "KprobeConnectHook.skel.h"
#include "KprobeLoader.h"

// try to load and attach an eBPF kprobe program with a specified load_method
static int try_load_ebpf_kprobe(const char *ebpf_file,
enum ebpf_load_method load_method,
struct bpf_object **bpf_obj,
struct bpf_link **bpf_link)
static int try_load_ebpf_kprobe(enum ebpf_load_method load_method,
struct KprobeConnectHook_bpf **ctx_out)
{
struct bpf_object *obj = NULL;
struct bpf_link *link = NULL;
int rv = 0;
struct KprobeConnectHook_bpf *ctx = NULL;
int rv = 0;

obj = ebpf_open_object_file(ebpf_file);
if (!obj) {
printf("failed to open BPF object\n");
ctx = KprobeConnectHook_bpf__open();
if (!ctx || !ctx->obj || libbpf_get_error(ctx->obj)) {
printf("failed to open BPF skeleton\n");
rv = -1;
goto cleanup;
}
printf("BPF FILE OPENED\n");
printf("BPF SKELETON OPENED\n");

// pin allowed_IPs map when program is loaded
rv = ebpf_map_set_pin_path(obj, EBPF_ALLOWED_IPS_MAP_NAME, EBPF_ALLOWED_IPS_MAP_PATH);
rv = ebpf_map_set_pin_path(ctx->obj, EBPF_ALLOWED_IPS_MAP_NAME, EBPF_ALLOWED_IPS_MAP_PATH);
if (rv) {
printf("failed to init " EBPF_ALLOWED_IPS_MAP_NAME " BPF map\n");
rv = -1;
Expand All @@ -51,7 +49,7 @@ static int try_load_ebpf_kprobe(const char *ebpf_file,
printf("BPF ALLOWED_IPS MAP LOADED\n");

// pin allowed_pids map when program is loaded
rv = ebpf_map_set_pin_path(obj, EBPF_ALLOWED_PIDS_MAP_NAME, EBPF_ALLOWED_PIDS_MAP_PATH);
rv = ebpf_map_set_pin_path(ctx->obj, EBPF_ALLOWED_PIDS_MAP_NAME, EBPF_ALLOWED_PIDS_MAP_PATH);
if (rv) {
printf("failed to init " EBPF_ALLOWED_PIDS_MAP_NAME " BPF map\n");
rv = -1;
Expand All @@ -71,9 +69,23 @@ static int try_load_ebpf_kprobe(const char *ebpf_file,
goto cleanup;
}

link = ebpf_load_and_attach_kprobe(obj, "tcp_v4_connect", load_method);
if (!link) {
printf("failed to load and attach kprobe\n");
rv = ebpf_object_set_kernel_version(ctx->obj, load_method);
if (rv != 0) {
printf("failed to set kernel version\n");
rv = -1;
goto cleanup;
}

rv = KprobeConnectHook_bpf__load(ctx);
if (rv != 0) {
printf("failed to load kprobe skeleton\n");
rv = -1;
goto cleanup;
}

rv = KprobeConnectHook_bpf__attach(ctx);
if (rv != 0) {
printf("failed to attach kprobe skeleton\n");
rv = -1;
goto cleanup;
}
Expand All @@ -83,19 +95,16 @@ static int try_load_ebpf_kprobe(const char *ebpf_file,

cleanup:
if (rv) {
bpf_object__close(obj);
bpf_link__destroy(link);
KprobeConnectHook_bpf__destroy(ctx);
} else {
*bpf_obj = obj;
*bpf_link = link;
*ctx_out = ctx;
}
return rv;
}

int main(int argc, char **argv)
{
struct bpf_object *obj = NULL;
struct bpf_link *link = NULL;
struct KprobeConnectHook_bpf *ctx = NULL;
enum ebpf_load_method load_method = EBPF_METHOD_NO_OVERRIDE;
struct rlimit rl = {};
int rv = -1;
Expand Down Expand Up @@ -123,7 +132,7 @@ int main(int argc, char **argv)
rv = -1;
while (rv && load_method < EBPF_MAX_LOAD_METHODS) {
printf("trying loading method %d\n", load_method);
rv = try_load_ebpf_kprobe("./KprobeConnectHook.bpf.o", load_method, &obj, &link);
rv = try_load_ebpf_kprobe(load_method, &ctx);
load_method++;
}

Expand All @@ -137,7 +146,6 @@ int main(int argc, char **argv)

cleanup:
// release libbpf resources
bpf_object__close(obj);
bpf_link__destroy(link);
KprobeConnectHook_bpf__destroy(ctx);
return rv;
}
68 changes: 44 additions & 24 deletions non-GPL/HostIsolation/Demos/TcLoaderDemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,51 +27,71 @@
#include <sys/stat.h>
#include <unistd.h>

#include "TcFilter.skel.h"
#include "TcLoader.h"

/* UPDATE ACCORDINGLY */
#define IFNAME_TO_ATTACH_TO "ens33"
#define EBPF_OBJ_FILE_NAME "TcFilter.bpf.o"

int main(int argc, char **argv)
{
struct netlink_ctx nl_ctx;
struct bpf_program *prog = NULL;
struct bpf_program *p = NULL;
struct bpf_object *obj = NULL;
struct TcFilter_bpf *ctx = NULL;
struct bpf_map *map = NULL;
const char *map_name = NULL;
char buf[256] = {0};
int prog_fd_dupd = 0;
int rv = -1;
const char *ifname = NULL;
bool unload_only = false;

memset(&nl_ctx, 0, sizeof(nl_ctx));

if (argc < 2) {
fprintf(stderr, "Usage: %s <interface> [unload]\n", argv[0]);
return -1;
}

ifname = argv[1];
if (argc >= 3) {
if (!strcmp(argv[2], "unload")) {
unload_only = true;
} else {
fprintf(stderr, "Unknown argument: %s\n", argv[2]);
fprintf(stderr, "Usage: %s <interface> [unload]\n", argv[0]);
return -1;
}
}
if (argc > 3) {
fprintf(stderr, "Too many arguments\n");
fprintf(stderr, "Usage: %s <interface> [unload]\n", argv[0]);
return -1;
}

/* do the same things as 'tc qdisc del dev <iface> clsact' */
if (netlink_qdisc_del(IFNAME_TO_ATTACH_TO) != 0) {
if (netlink_qdisc_del(ifname) != 0) {
fprintf(stderr, "failed to del qdisc\n");
} else {
printf("DELETED QDISC\n");
printf("DELETED QDISC (%s)\n", ifname);
}

/* if 'unload' is passed as arg, only delete qdisc */
if ((argc > 1) && !strcmp(argv[1], "unload")) {
if (unload_only) {
rv = 0;
goto out;
}

/* 'tc qdisc add dev <iface> clsact' */
if (netlink_qdisc_add(IFNAME_TO_ATTACH_TO) != 0) {
if (netlink_qdisc_add(ifname) != 0) {
fprintf(stderr, "failed to add qdisc\n");
rv = -1;
goto out;
}

printf("ADDED QDISC\n");
printf("ADDED QDISC (%s)\n", ifname);

/* 'tc filter add dev <iface> egress bpf da obj <ebpf_file> sec .text' */
/* finished when netlink_filter_add_end() is called */
if (netlink_filter_add_begin(&nl_ctx, IFNAME_TO_ATTACH_TO) != 0) {
if (netlink_filter_add_begin(&nl_ctx, ifname) != 0) {
fprintf(stderr, "filter_add_begin() failed\n");
rv = -1;
goto out;
Expand All @@ -95,24 +115,24 @@ int main(int argc, char **argv)
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts, .relaxed_maps = true,
.pin_root_path = EBPF_MAP_DIRECTORY, );

obj = bpf_object__open_file(EBPF_OBJ_FILE_NAME, &open_opts);
if (!obj || libbpf_get_error(obj)) {
fprintf(stderr, "failed to open BPF object\n");
bpf_object__close(obj);
ctx = TcFilter_bpf__open_opts(&open_opts);
if (!ctx || !ctx->obj || libbpf_get_error(ctx->obj)) {
fprintf(stderr, "failed to open BPF skeleton\n");
TcFilter_bpf__destroy(ctx);
rv = -1;
goto out;
}
printf("BPF FILE OPENED\n");
printf("BPF SKELETON OPENED\n");

bpf_object__for_each_program(p, obj)
bpf_object__for_each_program(p, ctx->obj)
{
bpf_program__set_type(p, BPF_PROG_TYPE_SCHED_CLS);
bpf_program__set_ifindex(p, 0); //?
if (!prog) {
prog = p;
}
}
bpf_object__for_each_map(map, obj)
bpf_object__for_each_map(map, ctx->obj)
{
bpf_map__set_ifindex(map, 0); //?
map_name = bpf_map__name(map);
Expand All @@ -127,10 +147,10 @@ int main(int argc, char **argv)
}
}

rv = bpf_object__load(obj);
rv = TcFilter_bpf__load(ctx);
if (rv) {
fprintf(stderr, "failed to load BPF program\n");
bpf_object__close(obj);
TcFilter_bpf__destroy(ctx);
rv = -1;
goto out;
}
Expand All @@ -139,16 +159,16 @@ int main(int argc, char **argv)
prog_fd_dupd = fcntl(bpf_program__fd(prog), F_DUPFD_CLOEXEC, 1);
if (prog_fd_dupd < 0) {
perror("bad prog_fd_dupd");
bpf_object__close(obj);
TcFilter_bpf__destroy(ctx);
rv = -1;
goto out;
}

bpf_object__close(obj);
obj = NULL;
TcFilter_bpf__destroy(ctx);
ctx = NULL;

/* tc filter add continued */
if (netlink_filter_add_end(prog_fd_dupd, &nl_ctx, EBPF_OBJ_FILE_NAME) != 0) {
if (netlink_filter_add_end(prog_fd_dupd, &nl_ctx) != 0) {
fprintf(stderr, "filter_add_end() failed\n");
close(prog_fd_dupd);
rv = -1;
Expand Down
60 changes: 11 additions & 49 deletions non-GPL/HostIsolation/Lib/KprobeLoader.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,28 +166,6 @@ static unsigned int get_kernel_version(enum ebpf_load_method method)
return code;
}

struct bpf_object *ebpf_open_object_file(const char *file_path)
{
struct bpf_object *obj = NULL;

if (!file_path) {
ebpf_log("error: file path is NULL\n");
obj = NULL;
goto cleanup;
}

obj = bpf_object__open_file(file_path, NULL);
if (!obj || libbpf_get_error(obj)) {
ebpf_log("failed to open BPF object\n");
bpf_object__close(obj);
obj = NULL;
goto cleanup;
}

cleanup:
return obj;
}

int ebpf_map_set_pin_path(struct bpf_object *obj, const char *map_name, const char *map_path)
{
struct bpf_map *map = NULL;
Expand Down Expand Up @@ -217,14 +195,17 @@ int ebpf_map_set_pin_path(struct bpf_object *obj, const char *map_name, const ch
return rv;
}

struct bpf_link *ebpf_load_and_attach_kprobe(struct bpf_object *obj,
const char *program_name,
enum ebpf_load_method load_method)
int ebpf_object_set_kernel_version(struct bpf_object *obj, enum ebpf_load_method load_method)
{
struct bpf_program *prog = NULL;
struct bpf_link *link = NULL;
int rv = 0;
unsigned int kernel_version = 0;

if (!obj) {
ebpf_log("ebpf_object_set_kernel_version error: NULL parameter\n");
rv = -1;
goto cleanup;
}

// Load may fail if an incorrect kernel version number was passed to the
// bpf() syscall (old Linux kernels verify that, while newer kernels ignore
// it). Try one of the methods of getting the kernel version, set it in
Expand All @@ -234,30 +215,11 @@ struct bpf_link *ebpf_load_and_attach_kprobe(struct bpf_object *obj,
ebpf_log("got kernel_version=%d according to method=%d\n", kernel_version, load_method);
if (bpf_object__set_kversion(obj, kernel_version) != 0) {
ebpf_log("failed to set kversion\n");
rv = -1;
goto cleanup;
}
}

if (bpf_object__load(obj) < 0) {
ebpf_log("failed to load BPF program\n");
link = NULL;
goto cleanup;
}

prog = bpf_object__find_program_by_name(obj, program_name);
if (!prog || libbpf_get_error(prog)) {
ebpf_log("failed to find BPF program by name\n");
link = NULL;
goto cleanup;
}

link = bpf_program__attach(prog);
if (!link || libbpf_get_error(link)) {
ebpf_log("failed to attach BPF program\n");
bpf_link__destroy(link);
link = NULL;
goto cleanup;
}

cleanup:
return link;
return rv;
}
Loading