From: Christian Brauner Date: Sat, 30 Nov 2019 15:05:44 +0000 (+0100) Subject: conf: record cgroup2 devices in parsed format X-Git-Tag: lxc-4.0.0~90^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4bfb655ea8d9f824571b970927c4eefb9c97f902;p=thirdparty%2Flxc.git conf: record cgroup2 devices in parsed format Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index e2332abd1..4b4a6a92a 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -2481,21 +2481,60 @@ out: return ret; } +static int bpf_list_add_device(struct lxc_conf *conf, struct device_item *device) +{ + __do_free struct lxc_list *list_elem = NULL; + __do_free struct device_item *new_device = NULL; + struct lxc_list *it; + + lxc_list_for_each(it, &conf->devices) { + struct device_item *cur = it->elem; + + if (cur->type != device->type) + continue; + if (cur->major != device->major) + continue; + if (cur->minor != device->minor) + continue; + if (strcmp(cur->access, device->access)) + continue; + + /* + * The rule is switched from allow to deny or vica versa so + * don't bother allocating just flip the existing one. + */ + if (cur->allow != device->allow) { + cur->allow = device->allow; + return log_trace(0, "Reusing existing rule of bpf device program: type %c, major %d, minor %d, access %s, allow %d", + cur->type, cur->major, cur->minor, + cur->access, cur->allow); + } + } + + list_elem = malloc(sizeof(*list_elem)); + if (!list_elem) + return error_log_errno(ENOMEM, "Failed to allocate new device list"); + + new_device = memdup(device, sizeof(struct device_item)); + if (!new_device) + return error_log_errno(ENOMEM, "Failed to allocate new device item"); + + lxc_list_add_elem(list_elem, move_ptr(new_device)); + lxc_list_add_tail(&conf->devices, move_ptr(list_elem)); + + return 0; +} + /* * Some of the parsing logic comes from the original cgroup device v1 * implementation in the kernel. */ -static int bpf_device_cgroup_prepare(struct cgroup_ops *ops, const char *key, +static int bpf_device_cgroup_prepare(struct cgroup_ops *ops, + struct lxc_conf *conf, const char *key, const char *val) { #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX - struct device_item { - char type; - int major; - int minor; - char access[100]; - int allow; - } device_item = {0}; + struct device_item device_item = {0}; int count, ret; char temp[50]; struct bpf_program *device; @@ -2614,6 +2653,11 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops, const char *key, device_item.type, device_item.major, device_item.minor, device_item.access, device_item.allow); } + + ret = bpf_list_add_device(conf, &device_item); + if (ret) + return -1; + #endif return 0; } @@ -2637,7 +2681,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(ops, cg->subsystem, + ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem, cg->value); } else { fullpath = must_make_path(h->container_full_path, diff --git a/src/lxc/cgroups/cgroup2_devices.c b/src/lxc/cgroups/cgroup2_devices.c index d44ab3282..762fd14f6 100644 --- a/src/lxc/cgroups/cgroup2_devices.c +++ b/src/lxc/cgroups/cgroup2_devices.c @@ -7,7 +7,6 @@ #endif #include #include -#include #include #include #include @@ -24,6 +23,7 @@ #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #include +#include lxc_log_define(cgroup2_devices, cgroup); diff --git a/src/lxc/conf.c b/src/lxc/conf.c index c03b66383..1cb074b51 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2736,6 +2736,7 @@ struct lxc_conf *lxc_conf_init(void) new->logfd = -1; lxc_list_init(&new->cgroup); lxc_list_init(&new->cgroup2); + lxc_list_init(&new->devices); lxc_list_init(&new->network); lxc_list_init(&new->mount_list); lxc_list_init(&new->caps); @@ -3883,6 +3884,17 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version) return 0; } +static void lxc_clear_devices(struct lxc_conf *conf) +{ + struct lxc_list *list = &conf->devices; + struct lxc_list *it, *next; + + lxc_list_for_each_safe(it, list, next) { + lxc_list_del(it); + free(it); + } +} + int lxc_clear_limits(struct lxc_conf *c, const char *key) { struct lxc_list *it, *next; @@ -4119,6 +4131,7 @@ void lxc_conf_free(struct lxc_conf *conf) lxc_clear_config_keepcaps(conf); lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC); lxc_clear_cgroups(conf, "lxc.cgroup2", CGROUP2_SUPER_MAGIC); + lxc_clear_devices(conf); lxc_clear_cgroup2_devices(conf); lxc_clear_hooks(conf, "lxc.hook"); lxc_clear_mount_entries(conf); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 741ac4f09..44d7934fe 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -230,6 +230,14 @@ struct lxc_state_client { lxc_state_t states[MAX_STATE]; }; +struct device_item { + char type; + int major; + int minor; + char access[4]; + int allow; +}; + struct lxc_conf { /* Pointer to the name of the container. Do not free! */ const char *name; @@ -242,6 +250,8 @@ struct lxc_conf { struct lxc_list cgroup; struct lxc_list cgroup2; struct bpf_program *cgroup2_devices; + /* This should be reimplemented as a hashmap. */ + struct lxc_list devices; }; struct { diff --git a/src/lxc/log.h b/src/lxc/log.h index 3c5be95c3..8e4591964 100644 --- a/src/lxc/log.h +++ b/src/lxc/log.h @@ -512,6 +512,12 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \ -1; \ }) +#define log_trace(__ret__, format, ...) \ + ({ \ + TRACE(format, ##__VA_ARGS__); \ + __ret__; \ + }) + extern int lxc_log_fd; extern int lxc_log_syslog(int facility); diff --git a/src/lxc/memory_utils.h b/src/lxc/memory_utils.h index b5220c189..660e147b7 100644 --- a/src/lxc/memory_utils.h +++ b/src/lxc/memory_utils.h @@ -71,4 +71,12 @@ static inline void __auto_close__(int *fd) #define __do_fclose __attribute__((__cleanup__(__auto_fclose__))) #define __do_closedir __attribute__((__cleanup__(__auto_closedir__))) +static inline void *memdup(const void *data, size_t len) +{ + void *copy = NULL; + + copy = len ? malloc(len) : NULL; + return copy ? memcpy(copy, data, len) : NULL; +} + #endif /* __LXC_MEMORY_UTILS_H */