]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
bpf: enable helpers to let caller replace existing bpf programs
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 18 Feb 2021 09:19:27 +0000 (10:19 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 18 Feb 2021 09:50:45 +0000 (10:50 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/cgroups/cgroup2_devices.c
src/lxc/cgroups/cgroup2_devices.h
src/lxc/commands.c

index 26e8cb569b906d99b086098ae596c165c86479e9..5382befe583a2d0bfd2906875d2226053c29101d 100644 (file)
@@ -3229,7 +3229,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");
index 435cc0dc2e3db8d2622d2c9bd53b12584e44dee7..d9ef697e219541c7b3da50323efab44983552968 100644 (file)
@@ -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;
 }
 
index 56eea75a83d22e2ecb4222e92c60586645318c62..c0edea825f5212d42d3b0cf06095083bc837505d 100644 (file)
@@ -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);
index cc9a1b3c626bfe24f93d8276c90a29a48c78bb9f..2fbe73f71d9d2ef879e83a7945d7043d08fc9abc 100644 (file)
@@ -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;