From: Christian Brauner Date: Sat, 30 Nov 2019 14:21:00 +0000 (+0100) Subject: cgroups/cgfsng: "atomically" replace bpf device programs X-Git-Tag: lxc-4.0.0~90^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cce5a3d71696b402ae7316f569085c759435690b;p=thirdparty%2Flxc.git cgroups/cgfsng: "atomically" replace bpf device programs Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index e6f6c0c74..e2332abd1 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -2485,7 +2485,7 @@ out: * Some of the parsing logic comes from the original cgroup device v1 * 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) { #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX @@ -2500,8 +2500,8 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key, char temp[50]; struct bpf_program *device; - if (conf->cgroup2_devices) { - device = conf->cgroup2_devices; + if (ops->cgroup2_devices) { + device = ops->cgroup2_devices; } else { device = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE); if (device && bpf_program_init(device)) { @@ -2514,7 +2514,7 @@ static int bpf_device_cgroup_prepare(struct lxc_conf *conf, const char *key, return -1; } - conf->cgroup2_devices = device; + ops->cgroup2_devices = device; if (strcmp("devices.allow", key) == 0) device_item.allow = 1; @@ -2637,7 +2637,7 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops, struct lxc_cgroup *cg = iterator->elem; 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); } else { fullpath = must_make_path(h->container_full_path, @@ -2662,25 +2662,37 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops, { #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX int ret; + struct lxc_conf *conf; struct hierarchy *h = ops->unified; - struct bpf_program *device = handler->conf->cgroup2_devices; + struct bpf_program *devices_new = ops->cgroup2_devices; if (!h) return false; - if (!device) + if (!devices_new) return true; - ret = bpf_program_finalize(device); + ret = bpf_program_finalize(devices_new); if (ret) return false; - return bpf_program_cgroup_attach(device, BPF_CGROUP_DEVICE, - h->container_full_path, - BPF_F_ALLOW_MULTI) == 0; -#else - return true; + ret = bpf_program_cgroup_attach(devices_new, BPF_CGROUP_DEVICE, + h->container_full_path, + BPF_F_ALLOW_MULTI); + if (ret) + 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 + return true; } __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops, diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c index 5443bd961..b6244241f 100644 --- a/src/lxc/cgroups/cgroup.c +++ b/src/lxc/cgroups/cgroup.c @@ -30,6 +30,7 @@ #include #include "cgroup.h" +#include "cgroup2_devices.h" #include "conf.h" #include "config.h" #include "initutils.h" @@ -86,6 +87,9 @@ void cgroup_exit(struct cgroup_ops *ops) free(ops->cgroup_pattern); free(ops->container_cgroup); + if (ops->cgroup2_devices) + bpf_program_free(ops->cgroup2_devices); + for (it = ops->hierarchies; it && *it; it++) { char **p; diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h index bb6c91cce..47a155007 100644 --- a/src/lxc/cgroups/cgroup.h +++ b/src/lxc/cgroups/cgroup.h @@ -118,6 +118,13 @@ struct cgroup_ops { /* Pointer to the unified hierarchy. Do not free! */ struct hierarchy *unified; + /* + * @cgroup2_devices + * bpf program to limit device access; only applicable to privileged + * containers. + */ + struct bpf_program *cgroup2_devices; + /* * @cgroup_layout * - What cgroup layout the container is running with.