Skip to content

Commit

Permalink
ebpf: replace the existing program on update
Browse files Browse the repository at this point in the history
on a container update, make sure the existing eBPF program is
completely replaced.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed May 6, 2020
1 parent 077bebb commit d9aeb6b
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 10 deletions.
45 changes: 37 additions & 8 deletions src/libcrun/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1561,13 +1561,32 @@ libcrun_cgroup_killall (char *path, libcrun_error_t *err)
return libcrun_cgroup_killall_signal (path, SIGKILL, err);
}

static char *
get_bpf_pin_path (const char *path)
{
char *pin_path = NULL;
int i;

while (*path == '/')
path++;

xasprintf (&pin_path, "/sys/fs/bpf/crun-%s", path);

for (i = strlen ("/sys/fs/bpf/"); pin_path[i]; i++)
if (pin_path[i] == '/' || pin_path[i] == '.')
pin_path[i] = '-';

return pin_path;
}

int
libcrun_cgroup_destroy (const char *id, char *path, int systemd_cgroup, libcrun_error_t *err)
{
int ret;
size_t i;
int mode;
const cgroups_subsystem_t *subsystems;
cleanup_free char *pin_path = NULL;

(void) id;
(void) systemd_cgroup;
Expand Down Expand Up @@ -1618,6 +1637,9 @@ libcrun_cgroup_destroy (const char *id, char *path, int systemd_cgroup, libcrun_
}
}

pin_path = get_bpf_pin_path (path);
unlink (pin_path);

return 0;
}

Expand Down Expand Up @@ -1966,10 +1988,11 @@ write_devices_resources_v1 (int dirfd, runtime_spec_schema_defs_linux_device_cgr
}

static int
write_devices_resources_v2_internal (int dirfd, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
write_devices_resources_v2_internal (const char *path, int dirfd, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
{
int i, ret;
cleanup_free struct bpf_program *program = NULL;
cleanup_free char *pin_path = NULL;
struct default_dev_s {
char type;
int major;
Expand Down Expand Up @@ -2026,21 +2049,23 @@ write_devices_resources_v2_internal (int dirfd, runtime_spec_schema_defs_linux_d
if (UNLIKELY (program == NULL))
return -1;

ret = libcrun_ebpf_load (program, dirfd, NULL, err);
pin_path = get_bpf_pin_path (path);

ret = libcrun_ebpf_load (program, dirfd, pin_path, err);
if (ret < 0)
return ret;

return 0;
}

static int
write_devices_resources_v2 (int dirfd, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
write_devices_resources_v2 (const char *path, int dirfd, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
{
int ret;
size_t i;
bool can_skip = true;

ret = write_devices_resources_v2_internal (dirfd, devs, devs_len, err);
ret = write_devices_resources_v2_internal (path, dirfd, devs, devs_len, err);
if (LIKELY (ret == 0))
return 0;

Expand Down Expand Up @@ -2071,10 +2096,10 @@ write_devices_resources_v2 (int dirfd, runtime_spec_schema_defs_linux_device_cgr


static int
write_devices_resources (int dirfd, bool cgroup2, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
write_devices_resources (const char *path, int dirfd, bool cgroup2, runtime_spec_schema_defs_linux_device_cgroup **devs, size_t devs_len, libcrun_error_t *err)
{
if (cgroup2)
return write_devices_resources_v2 (dirfd, devs, devs_len, err);
return write_devices_resources_v2 (path, dirfd, devs, devs_len, err);

return write_devices_resources_v1 (dirfd, devs, devs_len, err);
}
Expand Down Expand Up @@ -2406,7 +2431,9 @@ update_cgroup_v1_resources (runtime_spec_schema_config_linux_resources *resource
if (UNLIKELY (dirfd_devs < 0))
return crun_make_error (err, errno, "open %s", path_to_devs);

ret = write_devices_resources (dirfd_devs, false,
ret = write_devices_resources (path,
dirfd_devs,
false,
resources->devices,
resources->devices_len,
err);
Expand Down Expand Up @@ -2500,7 +2527,9 @@ update_cgroup_v2_resources (runtime_spec_schema_config_linux_resources *resource

if (resources->devices_len)
{
ret = write_devices_resources (cgroup_dirfd, true,
ret = write_devices_resources (path,
cgroup_dirfd,
true,
resources->devices,
resources->devices_len,
err);
Expand Down
31 changes: 29 additions & 2 deletions src/libcrun/ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#include <fcntl.h>

#ifdef HAVE_EBPF
# include <linux/bpf.h>
Expand Down Expand Up @@ -299,7 +300,9 @@ libcrun_ebpf_load (struct bpf_program *program, int dirfd, const char *pin, libc
#ifndef HAVE_EBPF
return crun_make_error (err, 0, "eBPF not supported");
#else
int fd, ret;
cleanup_close int fd = -1;
cleanup_close int replacefd = -1;
int ret;
union bpf_attr attr;
struct rlimit limit;

Expand Down Expand Up @@ -329,14 +332,36 @@ libcrun_ebpf_load (struct bpf_program *program, int dirfd, const char *pin, libc

fd = bpf (BPF_PROG_LOAD, &attr, sizeof (attr));
if (fd < 0)
return crun_make_error (err, errno, "bpf create %s", log);
return crun_make_error (err, errno, "bpf create `%s`", log);
}

if (pin)
{
union bpf_attr attr_open;

memset (&attr_open, 0, sizeof (attr_open));
attr_open.pathname = (uint64_t) pin;

replacefd = bpf (BPF_OBJ_GET, &attr_open, sizeof (attr_open));
#ifdef BPF_F_REPLACE
if (replacefd < 0 && errno != ENOENT)
return crun_make_error (err, errno, "open `%s`", pin);
#else
if (replacefd >= 0)
return crun_make_error (err, 0, "eBPF program already configured");
#endif
}

memset (&attr, 0, sizeof (attr));
attr.attach_type = BPF_CGROUP_DEVICE;
attr.target_fd = dirfd;
attr.attach_bpf_fd = fd;
#ifdef BPF_F_REPLACE
attr.attach_flags = BPF_F_ALLOW_MULTI | ((replacefd >= 0) ? BPF_F_REPLACE : 0);
attr.replace_bpf_fd = replacefd;
#else
attr.attach_flags = BPF_F_ALLOW_MULTI;
#endif

ret = bpf (BPF_PROG_ATTACH, &attr, sizeof (attr));
if (ret < 0)
Expand All @@ -345,6 +370,8 @@ libcrun_ebpf_load (struct bpf_program *program, int dirfd, const char *pin, libc
/* Optionally pin the program to the specified path. */
if (pin)
{
unlink (pin);

memset (&attr, 0, sizeof (attr));
attr.pathname = (uint64_t) pin;
attr.bpf_fd = fd;
Expand Down

0 comments on commit d9aeb6b

Please sign in to comment.