conf: record cgroup2 devices in parsed format

parent 6b500cc4
...@@ -2481,21 +2481,60 @@ out: ...@@ -2481,21 +2481,60 @@ out:
return ret; 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 * 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 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) const char *val)
{ {
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
struct device_item { struct device_item device_item = {0};
char type;
int major;
int minor;
char access[100];
int allow;
} device_item = {0};
int count, ret; int count, ret;
char temp[50]; char temp[50];
struct bpf_program *device; struct bpf_program *device;
...@@ -2614,6 +2653,11 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops, const char *key, ...@@ -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.type, device_item.major, device_item.minor,
device_item.access, device_item.allow); device_item.access, device_item.allow);
} }
ret = bpf_list_add_device(conf, &device_item);
if (ret)
return -1;
#endif #endif
return 0; return 0;
} }
...@@ -2637,7 +2681,7 @@ static bool __cg_unified_setup_limits(struct cgroup_ops *ops, ...@@ -2637,7 +2681,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(ops, cg->subsystem, ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem,
cg->value); cg->value);
} else { } else {
fullpath = must_make_path(h->container_full_path, fullpath = must_make_path(h->container_full_path,
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#endif #endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/filter.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
...@@ -24,6 +23,7 @@ ...@@ -24,6 +23,7 @@
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/filter.h>
lxc_log_define(cgroup2_devices, cgroup); lxc_log_define(cgroup2_devices, cgroup);
......
...@@ -2684,6 +2684,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2684,6 +2684,7 @@ struct lxc_conf *lxc_conf_init(void)
new->logfd = -1; new->logfd = -1;
lxc_list_init(&new->cgroup); lxc_list_init(&new->cgroup);
lxc_list_init(&new->cgroup2); lxc_list_init(&new->cgroup2);
lxc_list_init(&new->devices);
lxc_list_init(&new->network); lxc_list_init(&new->network);
lxc_list_init(&new->mount_list); lxc_list_init(&new->mount_list);
lxc_list_init(&new->caps); lxc_list_init(&new->caps);
...@@ -3823,6 +3824,17 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version) ...@@ -3823,6 +3824,17 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version)
return 0; 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) int lxc_clear_limits(struct lxc_conf *c, const char *key)
{ {
struct lxc_list *it, *next; struct lxc_list *it, *next;
...@@ -4045,6 +4057,7 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -4045,6 +4057,7 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_config_keepcaps(conf); lxc_clear_config_keepcaps(conf);
lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC); lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC);
lxc_clear_cgroups(conf, "lxc.cgroup2", CGROUP2_SUPER_MAGIC); lxc_clear_cgroups(conf, "lxc.cgroup2", CGROUP2_SUPER_MAGIC);
lxc_clear_devices(conf);
lxc_clear_cgroup2_devices(conf); lxc_clear_cgroup2_devices(conf);
lxc_clear_hooks(conf, "lxc.hook"); lxc_clear_hooks(conf, "lxc.hook");
lxc_clear_mount_entries(conf); lxc_clear_mount_entries(conf);
......
...@@ -223,6 +223,14 @@ struct lxc_state_client { ...@@ -223,6 +223,14 @@ struct lxc_state_client {
lxc_state_t states[MAX_STATE]; lxc_state_t states[MAX_STATE];
}; };
struct device_item {
char type;
int major;
int minor;
char access[4];
int allow;
};
struct lxc_conf { struct lxc_conf {
/* Pointer to the name of the container. Do not free! */ /* Pointer to the name of the container. Do not free! */
const char *name; const char *name;
...@@ -235,6 +243,8 @@ struct lxc_conf { ...@@ -235,6 +243,8 @@ struct lxc_conf {
struct lxc_list cgroup; struct lxc_list cgroup;
struct lxc_list cgroup2; struct lxc_list cgroup2;
struct bpf_program *cgroup2_devices; struct bpf_program *cgroup2_devices;
/* This should be reimplemented as a hashmap. */
struct lxc_list devices;
}; };
struct { struct {
......
...@@ -512,6 +512,12 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \ ...@@ -512,6 +512,12 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
-1; \ -1; \
}) })
#define log_trace(__ret__, format, ...) \
({ \
TRACE(format, ##__VA_ARGS__); \
__ret__; \
})
extern int lxc_log_fd; extern int lxc_log_fd;
extern int lxc_log_syslog(int facility); extern int lxc_log_syslog(int facility);
......
...@@ -65,4 +65,12 @@ static inline void __auto_close__(int *fd) ...@@ -65,4 +65,12 @@ static inline void __auto_close__(int *fd)
#define __do_fclose __attribute__((__cleanup__(__auto_fclose__))) #define __do_fclose __attribute__((__cleanup__(__auto_fclose__)))
#define __do_closedir __attribute__((__cleanup__(__auto_closedir__))) #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 */ #endif /* __LXC_MEMORY_UTILS_H */
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