diff options
author | Julia Kartseva <hex@fb.com> | 2020-09-17 00:58:04 +0200 |
---|---|---|
committer | Julia Kartseva <hex@fb.com> | 2021-04-10 05:28:47 +0200 |
commit | f23f0ead1f5ef135e4d271b5f9d8eab978665695 (patch) | |
tree | 057f7f400b8df97a665d0d2b025d10a28cc31986 /src/shared/bpf-program.c | |
parent | bpf-firewall: attach with BPF_F_ALLOW_MULTI if kernel supports (diff) | |
download | systemd-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.c | 80 |
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; +}; |