summaryrefslogtreecommitdiffstats
path: root/src/shared/bpf-program.c
diff options
context:
space:
mode:
authorJulia Kartseva <hex@fb.com>2020-09-17 00:58:04 +0200
committerJulia Kartseva <hex@fb.com>2021-04-10 05:28:47 +0200
commitf23f0ead1f5ef135e4d271b5f9d8eab978665695 (patch)
tree057f7f400b8df97a665d0d2b025d10a28cc31986 /src/shared/bpf-program.c
parentbpf-firewall: attach with BPF_F_ALLOW_MULTI if kernel supports (diff)
downloadsystemd-f23f0ead1f5ef135e4d271b5f9d8eab978665695.tar.xz
systemd-f23f0ead1f5ef135e4d271b5f9d8eab978665695.zip
shared: add bpf-program helpers
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.
Diffstat (limited to 'src/shared/bpf-program.c')
-rw-r--r--src/shared/bpf-program.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c
index 10239142af..d67ada23b0 100644
--- a/src/shared/bpf-program.c
+++ b/src/shared/bpf-program.c
@@ -12,6 +12,26 @@
#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;
+};