cgroups/cgfsng: "atomically" replace bpf device programs

parent 81cba860
...@@ -2485,7 +2485,7 @@ out: ...@@ -2485,7 +2485,7 @@ out:
* Some of the parsing logic comes from the original cgroup device v1 * Some of the parsing logic comes from the original cgroup device v1
* implementation in the kernel. * implementation in the kernel.
*/ */
static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key, static int bpf_device_cgroup_prepare(struct cgroup_ops *ops, const char *key,
const char *val) const char *val)
{ {
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
...@@ -2500,8 +2500,8 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key, ...@@ -2500,8 +2500,8 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key,
char temp[50]; char temp[50];
struct bpf_program *device; struct bpf_program *device;
if (conf->cgroup2_devices) { if (ops->cgroup2_devices) {
device = conf->cgroup2_devices; device = ops->cgroup2_devices;
} else { } else {
device = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE); device = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
if (device && bpf_program_init(device)) { if (device && bpf_program_init(device)) {
...@@ -2514,7 +2514,7 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key, ...@@ -2514,7 +2514,7 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key,
return -1; return -1;
} }
conf->cgroup2_devices = device; ops->cgroup2_devices = device;
if (strcmp("devices.allow", key) == 0) if (strcmp("devices.allow", key) == 0)
device_item.allow = 1; device_item.allow = 1;
...@@ -2637,7 +2637,7 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops, ...@@ -2637,7 +2637,7 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops,
struct lxc_cgroup *cg = iterator->elem; struct lxc_cgroup *cg = iterator->elem;
if (strncmp("devices", cg->subsystem, 7) == 0) { if (strncmp("devices", cg->subsystem, 7) == 0) {
ret = bpf_device_cgroup_prepare(conf, cg->subsystem, ret = bpf_device_cgroup_prepare(ops, cg->subsystem,
cg->value); cg->value);
} else { } else {
fullpath = must_make_path(h->container_full_path, fullpath = must_make_path(h->container_full_path,
...@@ -2662,25 +2662,37 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops, ...@@ -2662,25 +2662,37 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,
{ {
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
int ret; int ret;
struct lxc_conf *conf;
struct hierarchy *h = ops->unified; struct hierarchy *h = ops->unified;
struct bpf_program *device = handler->conf->cgroup2_devices; struct bpf_program *devices_new = ops->cgroup2_devices;
if (!h) if (!h)
return false; return false;
if (!device) if (!devices_new)
return true; return true;
ret = bpf_program_finalize(device); ret = bpf_program_finalize(devices_new);
if (ret) if (ret)
return false; return false;
return bpf_program_cgroup_attach(device, BPF_CGROUP_DEVICE, ret = bpf_program_cgroup_attach(devices_new, BPF_CGROUP_DEVICE,
h->container_full_path, h->container_full_path,
BPF_F_ALLOW_MULTI) == 0; BPF_F_ALLOW_MULTI);
#else if (ret)
return true; return false;
/* Replace old bpf program. */
conf = handler->conf;
if (conf->cgroup2_devices) {
struct bpf_program *old_devices;
old_devices = move_ptr(conf->cgroup2_devices);
conf->cgroup2_devices = move_ptr(ops->cgroup2_devices);
bpf_program_free(old_devices);
}
#endif #endif
return true;
} }
__cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <unistd.h> #include <unistd.h>
#include "cgroup.h" #include "cgroup.h"
#include "cgroup2_devices.h"
#include "conf.h" #include "conf.h"
#include "config.h" #include "config.h"
#include "initutils.h" #include "initutils.h"
...@@ -86,6 +87,9 @@ void cgroup_exit(struct cgroup_ops *ops) ...@@ -86,6 +87,9 @@ void cgroup_exit(struct cgroup_ops *ops)
free(ops->cgroup_pattern); free(ops->cgroup_pattern);
free(ops->container_cgroup); free(ops->container_cgroup);
if (ops->cgroup2_devices)
bpf_program_free(ops->cgroup2_devices);
for (it = ops->hierarchies; it && *it; it++) { for (it = ops->hierarchies; it && *it; it++) {
char **p; char **p;
......
...@@ -119,6 +119,13 @@ struct cgroup_ops { ...@@ -119,6 +119,13 @@ struct cgroup_ops {
struct hierarchy *unified; struct hierarchy *unified;
/* /*
* @cgroup2_devices
* bpf program to limit device access; only applicable to privileged
* containers.
*/
struct bpf_program *cgroup2_devices;
/*
* @cgroup_layout * @cgroup_layout
* - What cgroup layout the container is running with. * - What cgroup layout the container is running with.
* - CGROUP_LAYOUT_UNKNOWN * - CGROUP_LAYOUT_UNKNOWN
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment