]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared: add bpf-program helpers
authorJulia Kartseva <hex@fb.com>
Wed, 16 Sep 2020 22:58:04 +0000 (15:58 -0700)
committerJulia Kartseva <hex@fb.com>
Sat, 10 Apr 2021 03:28:47 +0000 (20:28 -0700)
Add helpers to:
- Create new BPFProgram instance from a path in bpf
filesystem and bpf attach type;
- Pin a program to bpf fs;
- Get BPF program ID by BPF program FD.

src/shared/bpf-program.c
src/shared/bpf-program.h

index 10239142af30898fc556b476fa553868d10fc530..d67ada23b0cf1d205f7b517ce8a8cfc728bc5fc0 100644 (file)
 #include "missing_syscall.h"
 #include "path-util.h"
 
+ /* struct bpf_prog_info info must be initialized since its value is both input and output
+  * for BPF_OBJ_GET_INFO_BY_FD syscall. */
+static int bpf_program_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, uint32_t info_len) {
+        union bpf_attr attr;
+
+        /* Explicitly memset to zero since some compilers may produce non-zero-initialized padding when
+         * structured initialization is used.
+         * Refer to https://github.com/systemd/systemd/issues/18164
+         */
+        zero(attr);
+        attr.info.bpf_fd = prog_fd;
+        attr.info.info_len = info_len;
+        attr.info.info = PTR_TO_UINT64(info);
+
+        if (bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)) < 0)
+                return -errno;
+
+        return 0;
+}
+
 int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
         _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
 
@@ -28,6 +48,38 @@ int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
         return 0;
 }
 
+int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret) {
+        _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
+        struct bpf_prog_info info = {};
+        int r;
+
+        assert(path);
+        assert(ret);
+
+        p = new(BPFProgram, 1);
+        if (!p)
+                return -ENOMEM;
+
+        *p = (BPFProgram) {
+                .prog_type = BPF_PROG_TYPE_UNSPEC,
+                .n_ref = 1,
+                .kernel_fd = -1,
+        };
+
+        r = bpf_program_load_from_bpf_fs(p, path);
+        if (r < 0)
+                return r;
+
+        r = bpf_program_get_info_by_fd(p->kernel_fd, &info, sizeof(info));
+        if (r < 0)
+                return r;
+
+        p->prog_type = info.type;
+        *ret = TAKE_PTR(p);
+
+        return 0;
+}
+
 static BPFProgram *bpf_program_free(BPFProgram *p) {
         assert(p);
 
@@ -254,3 +306,31 @@ int bpf_map_lookup_element(int fd, const void *key, void *value) {
 
         return 0;
 }
+
+int bpf_program_pin(int prog_fd, const char *bpffs_path) {
+        union bpf_attr attr;
+
+        zero(attr);
+        attr.pathname = PTR_TO_UINT64((void *) bpffs_path);
+        attr.bpf_fd = prog_fd;
+
+        if (bpf(BPF_OBJ_PIN, &attr, sizeof(attr)) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int bpf_program_get_id_by_fd(int prog_fd, uint32_t *ret_id) {
+        struct bpf_prog_info info = {};
+        int r;
+
+        assert(ret_id);
+
+        r = bpf_program_get_info_by_fd(prog_fd, &info, sizeof(info));
+        if (r < 0)
+                return r;
+
+        *ret_id = info.id;
+
+        return 0;
+};
index eef77f9d8e1a6dde7c7be9bf836ce8f9eabc3998..243cef923fa6c0a884e307cb9fa98c9acda20512 100644 (file)
@@ -26,8 +26,9 @@ struct BPFProgram {
 };
 
 int bpf_program_new(uint32_t prog_type, BPFProgram **ret);
-BPFProgram *bpf_program_unref(BPFProgram *p);
+int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret);
 BPFProgram *bpf_program_ref(BPFProgram *p);
+BPFProgram *bpf_program_unref(BPFProgram *p);
 
 int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count);
 int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size);
@@ -35,6 +36,8 @@ int bpf_program_load_from_bpf_fs(BPFProgram *p, const char *path);
 
 int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path, uint32_t flags);
 int bpf_program_cgroup_detach(BPFProgram *p);
+int bpf_program_pin(int prog_fd, const char *bpffs_path);
+int bpf_program_get_id_by_fd(int prog_fd, uint32_t *ret_id);
 
 int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags);
 int bpf_map_update_element(int fd, const void *key, void *value);