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 diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 83c3bac87f..cff2f617fb 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, @@ -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; } /* @@ -87,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); @@ -124,7 +131,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 +145,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 log_unit_error_errno(u, r, "bpf-foreign: Failed to prepare foreign BPF hashmap: %m"); + 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 log_unit_error_errno(u, r, "bpf-foreign: Failed to install foreign BPF programs: %m"); - - return 0; + return ret < 0 ? ret : r; }