1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-04 21:47:31 +03:00

Merge pull request #28159 from poettering/bpf-foreign-warnings

bpf-foreign: tweaks
This commit is contained in:
Lennart Poettering 2023-06-26 18:02:47 +02:00 committed by GitHub
commit ccfeda0268
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 35 deletions

View File

@ -1003,24 +1003,22 @@ RestrictNetworkInterfaces=~eth1</programlisting>
</varlistentry>
<varlistentry>
<term><varname>BPFProgram=<replaceable>type</replaceable><constant>:</constant><replaceable>program-path</replaceable></varname></term>
<term><varname>BPFProgram=<replaceable>type</replaceable>:<replaceable>program-path</replaceable></varname></term>
<listitem>
<para>Add a custom cgroup BPF program.</para>
<para><varname>BPFProgram=</varname> allows attaching custom BPF programs to the cgroup of a
unit. (This generalizes the functionality exposed via <varname>IPEgressFilterPath=</varname> and
and <varname>IPIngressFilterPath=</varname> 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 <ulink
url="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/bpf.h"><filename>bpf.h</filename></ulink>. Also
refer to the general <ulink url="https://docs.kernel.org/bpf/">BPF documentation</ulink>.</para>
<para><varname>BPFProgram=</varname> allows attaching BPF hooks to the cgroup of a systemd unit.
(This generalizes the functionality exposed via <varname>IPEgressFilterPath=</varname> for egress and
<varname>IPIngressFilterPath=</varname> 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 <ulink
url="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/bpf.h"/>.
For general BPF documentation please refer to <ulink url="https://docs.kernel.org/bpf/index.html"/>.</para>
<para>The specification of BPF program consists of a pair of BPF program type and program path in
the file system, with <literal>:</literal> as the separator:
<replaceable>type</replaceable>:<replaceable>program-path</replaceable>.</para>
<para>The specification of BPF program consists of a <replaceable>type</replaceable> followed by a
<replaceable>program-path</replaceable> with <literal>:</literal> as the separator:
<replaceable>type</replaceable><constant>:</constant><replaceable>program-path</replaceable>.</para>
<para><replaceable>type</replaceable> is the string name of BPF attach type also used in
<command>bpftool</command>. <replaceable>type</replaceable> can be one of <constant>egress</constant>,
<para>The BPF program type is equivalent to the BPF attach type used in
<command>bpftool</command>. It may be one of <constant>egress</constant>,
<constant>ingress</constant>, <constant>sock_create</constant>, <constant>sock_ops</constant>,
<constant>device</constant>, <constant>bind4</constant>, <constant>bind6</constant>,
<constant>connect4</constant>, <constant>connect6</constant>, <constant>post_bind4</constant>,
@ -1028,21 +1026,28 @@ RestrictNetworkInterfaces=~eth1</programlisting>
<constant>sysctl</constant>, <constant>recvmsg4</constant>, <constant>recvmsg6</constant>,
<constant>getsockopt</constant>, <constant>setsockopt</constant>.</para>
<para>Setting <varname>BPFProgram=</varname> to an empty value makes previous assignments ineffective.</para>
<para>Multiple assignments of the same <replaceable>type</replaceable>:<replaceable>program-path</replaceable>
value have the same effect as a single assignment: the program with the path <replaceable>program-path</replaceable>
will be attached to cgroup hook <replaceable>type</replaceable> just once.</para>
<para>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 <filename>/sys/fs/bpf/</filename>). 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).</para>
<para>Setting <varname>BPFProgram=</varname> to an empty value makes previous assignments
ineffective.</para>
<para>Multiple assignments of the same program type/path pair have the same effect as a single
assignment: the program will be attached just once.</para>
<para>If BPF <constant>egress</constant> pinned to <replaceable>program-path</replaceable> path is already being
handled by <varname>IPEgressFilterPath=</varname>, <varname>BPFProgram=</varname>
assignment will be considered valid and <varname>BPFProgram=</varname> will be attached to a cgroup.
Similarly for <constant>ingress</constant> hook and <varname>IPIngressFilterPath=</varname> assignment.</para>
<para>BPF programs passed with <varname>BPFProgram=</varname> are attached to the cgroup of a unit with BPF
attach flag <constant>multi</constant>, that allows further attachments of the same
<para>BPF programs passed with <varname>BPFProgram=</varname> are attached to the cgroup of a unit
with BPF attach flag <constant>multi</constant>, that allows further attachments of the same
<replaceable>type</replaceable> within cgroup hierarchy topped by the unit cgroup.</para>
<para>Examples:<programlisting>
BPFProgram=egress:/sys/fs/bpf/egress-hook
<para>Examples:<programlisting>BPFProgram=egress:/sys/fs/bpf/egress-hook
BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook
</programlisting></para>
</listitem>

View File

@ -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;
}