#include <errno.h>
#include <fcntl.h>
+#include <linux/bpf.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
+// libbpf
+#include <bpf/bpf.h>
+
#include <pakfire/cgroup.h>
#include <pakfire/logging.h>
#include <pakfire/pakfire.h>
#include <pakfire/string.h>
#include <pakfire/util.h>
+static char bpf_log_buffer[BPF_LOG_BUF_SIZE];
+
#define BUFFER_SIZE 64 * 1024
+// Short form of mov, dst_reg = src_reg
+#define BPF_MOV64_IMM(DST, IMM) \
+ ((struct bpf_insn){ \
+ .code = BPF_ALU64 | BPF_MOV | BPF_K, \
+ .dst_reg = DST, \
+ .src_reg = 0, \
+ .off = 0, \
+ .imm = IMM \
+ })
+
+// Program exit
+#define BPF_EXIT_INSN() \
+ ((struct bpf_insn){ \
+ .code = BPF_JMP | BPF_EXIT, \
+ .dst_reg = 0, \
+ .src_reg = 0, \
+ .off = 0, \
+ .imm = 0 \
+ })
+
enum pakfire_cgroup_controllers {
PAKFIRE_CGROUP_CONTROLLER_CPU = (1 << 0),
PAKFIRE_CGROUP_CONTROLLER_MEMORY = (1 << 1),
// File descriptor to cgroup
int fd;
+
+ // FD to the devices filter program
+ int devicesfd;
};
// Returns true if this is the root cgroup
DEBUG(cgroup->pakfire, "Releasing cgroup %s at %p\n",
pakfire_cgroup_name(cgroup), cgroup);
- // Close the file descriptor
+ // Close the file descriptors
if (cgroup->fd > 0)
close(cgroup->fd);
+ if (cgroup->devicesfd > 0)
+ close(cgroup->devicesfd);
pakfire_unref(cgroup->pakfire);
free(cgroup);
}
+static int pakfire_cgroup_setup_devices(struct pakfire_cgroup* cgroup) {
+ LIBBPF_OPTS(bpf_prog_load_opts, opts,
+ // Log Buffer
+ .log_buf = bpf_log_buffer,
+ .log_size = sizeof(bpf_log_buffer),
+ );
+ int r;
+
+ struct bpf_insn program[] = {
+ BPF_MOV64_IMM(BPF_REG_0, 1), // r0 = 1
+ BPF_EXIT_INSN(), // return r0
+ };
+
+ // Load the BPF program
+ r = bpf_prog_load(BPF_PROG_TYPE_CGROUP_DEVICE, NULL, "GPL",
+ program, sizeof(program) / sizeof(*program), &opts);
+ if (r < 0) {
+ ERROR(cgroup->pakfire, "Could not load BPF program: %m\n");
+ return r;
+ }
+
+ // Store the file descriptor
+ cgroup->devicesfd = r;
+
+ // Attach the program to the cgroup
+ r = bpf_prog_attach(cgroup->devicesfd, cgroup->fd,
+ BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI);
+ if (r) {
+ ERROR(cgroup->pakfire, "Could not attach BPF program to cgroup: %m\n");
+ return r;
+ }
+
+ return 0;
+}
+
static int pakfire_cgroup_open_root(struct pakfire_cgroup* cgroup) {
int fd = open(cgroup->root, O_DIRECTORY|O_PATH|O_CLOEXEC);
if (fd < 0) {
goto ERROR;
}
+ // Setup the devices filter
+ r = pakfire_cgroup_setup_devices(c);
+ if (r)
+ goto ERROR;
+
*cgroup = c;
return 0;