From d512831a3ec93f6f29ccb21cb68f416114270840 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 26 Jun 2023 13:03:39 +0200 Subject: [PATCH 1/4] bpf-foreign: remove duplicate various occasions of duplicate logging --- src/core/bpf-foreign.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 83c3bac87f..0271f1b325 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -24,7 +24,7 @@ static int bpf_foreign_key_new(uint32_t prog_id, p = new(BPFForeignKey, 1); if (!p) - return log_oom(); + return -ENOMEM; *p = (BPFForeignKey) { .prog_id = prog_id, @@ -139,12 +139,12 @@ int bpf_foreign_install(Unit *u) { LIST_FOREACH(programs, p, cc->bpf_foreign_programs) { r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path); if (r < 0) - return log_unit_error_errno(u, r, "bpf-foreign: Failed to prepare foreign BPF hashmap: %m"); + return r; } r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI); if (r < 0) - return log_unit_error_errno(u, r, "bpf-foreign: Failed to install foreign BPF programs: %m"); + return r; return 0; } From f81450f2415f8fd77fc8edb3b4baab966aefa9fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 26 Jun 2023 13:04:59 +0200 Subject: [PATCH 2/4] bpf-foreign: if one program fails, still load the next Let's make sure that if we load one program we don't prematurely fail, and continue with the others still. --- src/core/bpf-foreign.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 0271f1b325..4ee76abfc1 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -56,17 +56,20 @@ DEFINE_PRIVATE_HASH_OPS_FULL(bpf_foreign_by_key_hash_ops, static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, uint32_t attach_flags) { const BPFForeignKey *key; BPFProgram *prog; - int r; + int r, ret = 0; assert(u); HASHMAP_FOREACH_KEY(prog, key, foreign_by_key) { r = bpf_program_cgroup_attach(prog, key->attach_type, path, attach_flags); - if (r < 0) - return log_unit_error_errno(u, r, "bpf-foreign: Attaching foreign BPF program to cgroup %s failed: %m", path); + if (r < 0) { + log_unit_error_errno(u, r, "bpf-foreign: Attaching foreign BPF program to cgroup %s failed: %m", path); + if (ret >= 0) + ret = r; + } } - return 0; + return ret; } /* @@ -124,7 +127,7 @@ static int bpf_foreign_prepare( int bpf_foreign_install(Unit *u) { _cleanup_free_ char *cgroup_path = NULL; CGroupContext *cc; - int r; + int r, ret = 0; assert(u); @@ -138,13 +141,10 @@ int bpf_foreign_install(Unit *u) { LIST_FOREACH(programs, p, cc->bpf_foreign_programs) { r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path); - if (r < 0) - return r; + if (r < 0 && ret >= 0) + ret = r; } r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI); - if (r < 0) - return r; - - return 0; + return ret < 0 ? ret : r; } From 228459f5d7da200537895edf82260a79e6e99947 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 26 Jun 2023 13:05:56 +0200 Subject: [PATCH 3/4] bpf-foreign: add an explicit, explanatory message when reference BPF program is not loaded yet --- src/core/bpf-foreign.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 4ee76abfc1..cff2f617fb 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -90,6 +90,10 @@ static int bpf_foreign_prepare( assert(bpffs_path); r = path_is_fs_type(bpffs_path, BPF_FS_MAGIC); + if (r == -ENOENT) { + log_unit_warning_errno(u, r, "bpf-foreign: foreign program %s does not exist, skipping.", bpffs_path); + return 0; + } if (r < 0) return log_unit_error_errno(u, r, "bpf-foreign: Failed to determine filesystem type of %s: %m", bpffs_path); From a27e6fb71bf70f27347b0e1167b2de32c4dc6637 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 26 Jun 2023 13:16:11 +0200 Subject: [PATCH 4/4] man: rework BPFForeign= documentation a bit Various assorted changes, among them make clear that a missing BPF program is not reason to abort unit activation. --- man/systemd.resource-control.xml | 51 ++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 1cd0beea04..57ebb8e1ea 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -1003,24 +1003,22 @@ RestrictNetworkInterfaces=~eth1 - BPFProgram=type:program-path + BPFProgram=type:program-path - Add a custom cgroup BPF program. + BPFProgram= allows attaching custom BPF programs to the cgroup of a + unit. (This generalizes the functionality exposed via IPEgressFilterPath= and + and IPIngressFilterPath= for other hooks.) Cgroup-bpf hooks in the form of BPF + programs loaded to the BPF filesystem are attached with cgroup-bpf attach flags determined by the + unit. For details about attachment types and flags see bpf.h. Also + refer to the general BPF documentation. - BPFProgram= allows attaching BPF hooks to the cgroup of a systemd unit. - (This generalizes the functionality exposed via IPEgressFilterPath= for egress and - IPIngressFilterPath= for ingress.) - Cgroup-bpf hooks in the form of BPF programs loaded to the BPF filesystem are attached with cgroup-bpf attach - flags determined by the unit. For details about attachment types and flags see . - For general BPF documentation please refer to . + The specification of BPF program consists of a pair of BPF program type and program path in + the file system, with : as the separator: + type:program-path. - The specification of BPF program consists of a type followed by a - program-path with : as the separator: - type:program-path. - - type is the string name of BPF attach type also used in - bpftool. type can be one of egress, + The BPF program type is equivalent to the BPF attach type used in + bpftool. It may be one of egress, ingress, sock_create, sock_ops, device, bind4, bind6, connect4, connect6, post_bind4, @@ -1028,21 +1026,28 @@ RestrictNetworkInterfaces=~eth1 sysctl, recvmsg4, recvmsg6, getsockopt, setsockopt. - Setting BPFProgram= to an empty value makes previous assignments ineffective. - Multiple assignments of the same type:program-path - value have the same effect as a single assignment: the program with the path program-path - will be attached to cgroup hook type just once. + The specified program path must be an absolute path referencing a BPF program inode in the + bpffs file system (which generally means it must begin with /sys/fs/bpf/). If + a specified program does not exist (i.e. has not been uploaded to the BPF subsystem of the kernel + yet), it will not be installed but unit activation will continue (a warning will be printed to the + logs). + + Setting BPFProgram= to an empty value makes previous assignments + ineffective. + + Multiple assignments of the same program type/path pair have the same effect as a single + assignment: the program will be attached just once. + If BPF egress pinned to program-path path is already being handled by IPEgressFilterPath=, BPFProgram= assignment will be considered valid and BPFProgram= will be attached to a cgroup. Similarly for ingress hook and IPIngressFilterPath= assignment. - BPF programs passed with BPFProgram= are attached to the cgroup of a unit with BPF - attach flag multi, that allows further attachments of the same + BPF programs passed with BPFProgram= are attached to the cgroup of a unit + with BPF attach flag multi, that allows further attachments of the same type within cgroup hierarchy topped by the unit cgroup. - Examples: -BPFProgram=egress:/sys/fs/bpf/egress-hook + Examples:BPFProgram=egress:/sys/fs/bpf/egress-hook BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook