From: Julia Kartseva Date: Wed, 9 Dec 2020 06:07:30 +0000 (-0800) Subject: dbus-cgroup: add BPFProgram= dbus support X-Git-Tag: v249-rc1~428^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e009a145d4d67e8c9b1a4a7abcb5cc2c9e734ca;p=thirdparty%2Fsystemd.git dbus-cgroup: add BPFProgram= dbus support - Handle BPFProgram= property in string format ":", e.g. egress:/sys/fs/bpf/egress-hook. - Add dbus getter to list foreign bpf programs attached to a cgroup. --- diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 614871bce20..e1b9a5e490e 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2474,6 +2474,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -3008,6 +3010,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + @@ -3566,6 +3570,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + @@ -4251,6 +4257,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -4811,6 +4819,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + @@ -5365,6 +5375,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + @@ -5952,6 +5964,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -6440,6 +6454,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + @@ -6912,6 +6928,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + @@ -7620,6 +7638,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -8094,6 +8114,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + @@ -8552,6 +8574,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + @@ -9113,6 +9137,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -9251,6 +9277,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + @@ -9393,6 +9421,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + @@ -9554,6 +9584,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { readonly u ManagedOOMMemoryPressureLimit = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s ManagedOOMPreference = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(ss) BPFProgram = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KillMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -9708,6 +9740,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + @@ -9876,6 +9910,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 033fd857d66..60a2ad78162 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -5,6 +5,7 @@ #include "af-list.h" #include "alloc-util.h" #include "bpf-firewall.h" +#include "bpf-foreign.h" #include "bus-get-properties.h" #include "cgroup-util.h" #include "cgroup.h" @@ -347,6 +348,33 @@ static int property_get_ip_address_access( return sd_bus_message_close_container(reply); } +static int property_get_bpf_foreign_program( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + CGroupContext *c = userdata; + CGroupBPFForeignProgram *p; + int r; + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + return r; + + LIST_FOREACH(programs, p, c->bpf_foreign_programs) { + const char *attach_type = bpf_cgroup_attach_type_to_string(p->attach_type); + + r = sd_bus_message_append(reply, "(ss)", attach_type, p->bpffs_path); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), @@ -398,6 +426,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0), SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit), 0), SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0), + SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program, 0, 0), SD_BUS_VTABLE_END }; @@ -570,6 +599,85 @@ static int bus_cgroup_set_transient_property( } } + return 1; + } else if (streq(name, "BPFProgram")) { + const char *a, *p; + size_t n = 0; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &a, &p)) > 0) { + int attach_type = bpf_cgroup_attach_type_from_string(a); + if (attach_type < 0) + return sd_bus_error_setf( + error, + SD_BUS_ERROR_INVALID_ARGS, + "%s expects a valid BPF attach type, got '%s'.", + name, a); + + if (!path_is_normalized(p) || !path_is_absolute(p)) + return sd_bus_error_setf( + error, + SD_BUS_ERROR_INVALID_ARGS, + "%s= expects a normalized absolute path.", + name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = cgroup_add_bpf_foreign_program(c, attach_type, p); + if (r < 0) + return r; + } + n++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + CGroupBPFForeignProgram *fp; + size_t size = 0; + + if (n == 0) + while (c->bpf_foreign_programs) + cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs(name, f); + fputs("=\n", f); + + LIST_FOREACH(programs, fp, c->bpf_foreign_programs) + fprintf(f, "%s=%s:%s\n", name, + bpf_cgroup_attach_type_to_string(fp->attach_type), + fp->bpffs_path); + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + + if (!LIST_IS_EMPTY(c->bpf_foreign_programs)) { + r = bpf_foreign_supported(); + if (r < 0) + return r; + if (r == 0) + log_full(LOG_DEBUG, + "Transient unit %s configures a BPF program pinned to BPF " + "filesystem, but the local system does not support that.\n" + "Starting this unit will fail!", u->id); + } + } + return 1; } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 84d4729334c..eb28c359244 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -842,6 +842,26 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons return 1; } + if (streq(field, "BPFProgram")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0); + else { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&eq, &word, ":", 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", field); + + r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, word, eq); + } + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + return 0; } diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index c3c81f03fbd..2fe3d8c509e 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -1694,6 +1694,23 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m return 1; + } else if (streq(name, "BPFProgram")) { + const char *a, *p; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ss)", &a, &p)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s:%s", a, p); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; } break;