__cgfsng_ops static bool cgfsng_devices_activate(struct cgroup_ops *ops, struct lxc_handler *handler)
{
- __do_bpf_program_free struct bpf_program *prog = NULL;
- int ret;
struct lxc_conf *conf;
struct hierarchy *unified;
- struct lxc_list *it;
- struct bpf_program *prog_old;
if (!ops)
return ret_set_errno(false, ENOENT);
!unified->container_full_path || lxc_list_empty(&conf->devices))
return true;
- prog = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
- if (!prog)
- return log_error_errno(false, ENOMEM, "Failed to create new bpf program");
-
- ret = bpf_program_init(prog);
- if (ret)
- return log_error_errno(false, ENOMEM, "Failed to initialize bpf program");
-
- bpf_device_set_type(prog, &conf->devices);
- TRACE("Device bpf %s all devices by default",
- bpf_device_block_all(prog) ? "blocks" : "allows");
-
- lxc_list_for_each(it, &conf->devices) {
- struct device_item *cur = it->elem;
-
- if (!bpf_device_add(prog, cur)) {
- TRACE("Skipping type %c, major %d, minor %d, access %s, allow %d",
- cur->type, cur->major, cur->minor, cur->access,
- cur->allow);
- continue;
- }
-
- ret = bpf_program_append_device(prog, cur);
- if (ret)
- return log_error_errno(false, ENOMEM, "Failed to add new rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d",
- cur->type,
- cur->major,
- cur->minor,
- cur->access,
- cur->allow,
- cur->global_rule);
- TRACE("Added rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d, global_rule %d",
- cur->type,
- cur->major,
- cur->minor,
- cur->access,
- cur->allow,
- cur->global_rule);
- }
-
- ret = bpf_program_finalize(prog);
- if (ret)
- return log_error_errno(false, ENOMEM, "Failed to finalize bpf program");
-
- ret = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE,
- unified->cgfd_limit, -EBADF,
- BPF_F_ALLOW_MULTI);
- if (ret)
- return log_error_errno(false, ENOMEM, "Failed to attach bpf program");
-
- /* Replace old bpf program. */
- prog_old = move_ptr(ops->cgroup2_devices);
- ops->cgroup2_devices = move_ptr(prog);
- prog = move_ptr(prog_old);
- return true;
+ return bpf_cgroup_devices_attach(ops, &conf->devices);
}
static bool __cgfsng_delegate_controllers(struct cgroup_ops *ops, const char *cgroup)
return log_trace(true, "The bpf device cgroup is supported");
}
+
+static struct bpf_program *__bpf_cgroup_devices(struct lxc_list *devices)
+{
+ __do_bpf_program_free struct bpf_program *prog = NULL;
+ int ret;
+ struct lxc_list *it;
+
+ prog = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
+ if (!prog)
+ return syserrno(NULL, "Failed to create new bpf program");
+
+ ret = bpf_program_init(prog);
+ if (ret)
+ return syserrno(NULL, "Failed to initialize bpf program");
+
+ bpf_device_set_type(prog, devices);
+ TRACE("Device bpf %s all devices by default",
+ bpf_device_block_all(prog) ? "blocks" : "allows");
+
+ lxc_list_for_each(it, devices) {
+ struct device_item *cur = it->elem;
+
+ if (!bpf_device_add(prog, cur)) {
+ TRACE("Skipping rule: type %c, major %d, minor %d, access %s, allow %d",
+ cur->type, cur->major, cur->minor, cur->access, cur->allow);
+ continue;
+ }
+
+ ret = bpf_program_append_device(prog, cur);
+ if (ret)
+ return syserrno(NULL, "Failed adding rule: type %c, major %d, minor %d, access %s, allow %d",
+ cur->type, cur->major, cur->minor, cur->access, cur->allow);
+
+ TRACE("Added rule to bpf device program: type %c, major %d, minor %d, access %s, allow %d",
+ cur->type, cur->major, cur->minor, cur->access, cur->allow);
+ }
+
+ ret = bpf_program_finalize(prog);
+ if (ret)
+ return syserrno(NULL, "Failed to finalize bpf program");
+
+ return move_ptr(prog);
+}
+
+bool bpf_cgroup_devices_attach(struct cgroup_ops *ops, struct lxc_list *devices)
+{
+ __do_bpf_program_free struct bpf_program *prog = NULL;
+ int ret;
+
+ prog = __bpf_cgroup_devices(devices);
+ if (!prog)
+ return syserrno(false, "Failed to create bpf program");
+
+ ret = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE,
+ ops->unified->cgfd_limit, -EBADF,
+ BPF_F_ALLOW_MULTI);
+ if (ret)
+ return syserrno(false, "Failed to attach bpf program");
+
+ /* Replace old bpf program. */
+ swap(prog, ops->cgroup2_devices);
+ return log_trace(true, "Attached bpf program");
+}
__hidden extern bool bpf_devices_cgroup_supported(void);
__hidden extern int bpf_list_add_device(struct lxc_conf *conf, struct device_item *device);
+__hidden extern bool bpf_cgroup_devices_attach(struct cgroup_ops *ops,
+ struct lxc_list *devices);
define_cleanup_function(struct bpf_program *, bpf_program_free);
#define __do_bpf_program_free call_cleaner(bpf_program_free)