bpf: enable helpers to let caller replace existing bpf programs

parent 54c17d39
......@@ -3227,7 +3227,7 @@ __cgfsng_ops static bool cgfsng_devices_activate(struct cgroup_ops *ops, struct
return log_error_errno(false, ENOMEM, "Failed to finalize bpf program");
ret = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE,
unified->cgfd_limit,
unified->cgfd_limit, -EBADF,
BPF_F_ALLOW_MULTI);
if (ret)
return log_error_errno(false, ENOMEM, "Failed to attach bpf program");
......
......@@ -363,7 +363,7 @@ static int bpf_program_load_kernel(struct bpf_program *prog)
}
int bpf_program_cgroup_attach(struct bpf_program *prog, int type, int fd_cgroup,
uint32_t flags)
int replace_bpf_fd, uint32_t flags)
{
__do_close int fd_cgroup_dup = -EBADF;
int ret;
......@@ -372,20 +372,34 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type, int fd_cgroup,
if (fd_cgroup < 0)
return ret_errno(EBADF);
if (flags & ~(BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI))
return log_error_errno(-1, EINVAL, "Invalid flags for bpf program");
if (flags & ~(BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI | BPF_F_REPLACE))
return syserrno_set(-EINVAL, "Invalid flags for bpf program");
if (((flags & BPF_F_REPLACE) && replace_bpf_fd < 0) ||
(replace_bpf_fd >= 0 && !(flags & BPF_F_REPLACE)))
return syserrno_set(-EINVAL, "Requested to replace bpf program with invalid parameters");
/*
* Don't allow the bpf program to be overwritten for now. If we ever
* allow this we need to verify that the attach_flags of the current
* bpf program and the attach_flags of the new program match.
*/
if (flags & BPF_F_ALLOW_OVERRIDE)
INFO("Allowing to override bpf program");
if (prog->fd_cgroup >= 0) {
if (prog->attached_type != type)
return log_error_errno(-1, EBUSY, "Wrong type for bpf program");
if (prog->attached_flags != flags)
/*
* For BPF_F_ALLOW_OVERRIDE the flags of the new and old
* program must match.
*/
if ((flags & BPF_F_ALLOW_OVERRIDE) && (prog->attached_flags != flags))
return log_error_errno(-1, EBUSY, "Wrong flags for bpf program");
if (flags != BPF_F_ALLOW_OVERRIDE)
return 0;
}
/* Leave the caller's fd alone. */
fd_cgroup_dup = dup_cloexec(fd_cgroup);
if (fd_cgroup_dup < 0)
return -errno;
......@@ -401,15 +415,19 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type, int fd_cgroup,
.attach_flags = flags,
};
if (flags & BPF_F_REPLACE)
attr->replace_bpf_fd = replace_bpf_fd;
ret = bpf(BPF_PROG_ATTACH, attr, sizeof(*attr));
if (ret < 0)
return log_error_errno(-1, errno, "Failed to attach bpf program");
return syserrno_set(-errno, "Failed to attach bpf program");
close_move_fd(prog->fd_cgroup, fd_cgroup_dup);
prog->attached_type = type;
prog->attached_flags = flags;
TRACE("Loaded and attached bpf program to cgroup %d", prog->fd_cgroup);
TRACE("Attached bpf program to cgroup %d%s", prog->fd_cgroup,
(flags & BPF_F_REPLACE) ? " and replaced old bpf program" : "");
return 0;
}
......
......@@ -61,7 +61,8 @@ __hidden extern int bpf_program_init(struct bpf_program *prog);
__hidden extern int bpf_program_append_device(struct bpf_program *prog, struct device_item *device);
__hidden extern int bpf_program_finalize(struct bpf_program *prog);
__hidden extern int bpf_program_cgroup_attach(struct bpf_program *prog, int type,
int fd_cgroup, uint32_t flags);
int fd_cgroup, int replace_bpf_fd,
uint32_t flags);
__hidden extern int bpf_program_cgroup_detach(struct bpf_program *prog);
__hidden extern void bpf_program_free(struct bpf_program *prog);
__hidden extern void bpf_device_program_free(struct cgroup_ops *ops);
......
......@@ -1250,7 +1250,7 @@ static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *re
goto respond;
ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE,
unified->cgfd_mon, BPF_F_ALLOW_MULTI);
unified->cgfd_mon, -EBADF, BPF_F_ALLOW_MULTI);
if (ret)
goto respond;
......
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