diff options
-rw-r--r-- | man/org.freedesktop.systemd1.xml | 72 | ||||
-rw-r--r-- | src/core/dbus-cgroup.c | 112 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 51 |
3 files changed, 235 insertions, 0 deletions
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 7a44c9be9b..3d6f1a39b3 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2482,6 +2482,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -3018,6 +3022,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -3578,6 +3586,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -4265,6 +4277,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -4827,6 +4843,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -5383,6 +5403,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -5972,6 +5996,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -6462,6 +6490,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -6936,6 +6968,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -7646,6 +7682,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -8122,6 +8162,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -8582,6 +8626,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -9145,6 +9193,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -9285,6 +9337,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--Autogenerated cross-references for systemd.directives, do not edit--> <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/> @@ -9429,6 +9485,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <!--End of Autogenerated section--> <refsect2> @@ -9592,6 +9652,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { readonly s ManagedOOMPreference = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly a(ss) BPFProgram = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindAllow = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly a(iqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KillMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -9748,6 +9812,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { <!--property BPFProgram is not documented!--> + <!--property SocketBindAllow is not documented!--> + + <!--property SocketBindDeny is not documented!--> + <!--property KillMode is not documented!--> <!--property KillSignal is not documented!--> @@ -9918,6 +9986,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/> + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/> + + <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/> + <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 60a2ad7816..d7f03d0cfd 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -16,6 +16,7 @@ #include "fd-util.h" #include "fileio.h" #include "limits-util.h" +#include "parse-util.h" #include "path-util.h" #include "percent-util.h" @@ -375,6 +376,32 @@ static int property_get_bpf_foreign_program( return sd_bus_message_close_container(reply); } +static int property_get_socket_bind( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + CGroupSocketBindItem **items = userdata, *i; + int r; + + assert(items); + + r = sd_bus_message_open_container(reply, 'a', "(iqq)"); + if (r < 0) + return r; + + LIST_FOREACH(socket_bind_items, i, *items) { + r = sd_bus_message_append(reply, "(iqq)", i->address_family, i->nr_ports, i->port_min); + 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), @@ -427,6 +454,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = { 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_PROPERTY("SocketBindAllow", "a(iqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_allow), 0), + SD_BUS_PROPERTY("SocketBindDeny", "a(iqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0), SD_BUS_VTABLE_END }; @@ -1849,6 +1878,89 @@ int bus_cgroup_set_property( return 1; } + if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) { + CGroupSocketBindItem **list; + uint16_t nr_ports, port_min; + size_t n = 0; + int family; + + list = streq(name, "SocketBindAllow") ? &c->socket_bind_allow : &c->socket_bind_deny; + + r = sd_bus_message_enter_container(message, 'a', "(iqq)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(iqq)", &family, &nr_ports, &port_min)) > 0) { + + if (!IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects INET or INET6 family, if specified.", name); + + if (port_min + (uint32_t) nr_ports > (1 << 16)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects maximum port value lesser than 65536.", name); + + if (port_min == 0 && nr_ports != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects port range starting with positive value.", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ CGroupSocketBindItem *item = NULL; + + item = new(CGroupSocketBindItem, 1); + if (!item) + return log_oom(); + + *item = (CGroupSocketBindItem) { + .address_family = family, + .nr_ports = nr_ports, + .port_min = port_min + }; + + LIST_PREPEND(socket_bind_items, *list, TAKE_PTR(item)); + } + 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; + CGroupSocketBindItem *item; + size_t size = 0; + + if (n == 0) + cgroup_context_remove_socket_bind(list); + else { + if ((u->manager->cgroup_supported & CGROUP_MASK_BPF_SOCKET_BIND) == 0) + log_full(LOG_DEBUG, + "Unit %s configures source compiled BPF programs " + "but the local system does not support that.\n" + "Starting this unit will fail!", u->id); + } + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fprintf(f, "%s:", name); + + LIST_FOREACH(socket_bind_items, item, *list) + cgroup_context_dump_socket_bind_item(item, f); + + fputc('\n', f); + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + } + + return 1; + } if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB)) return bus_cgroup_set_transient_property(u, c, name, message, flags, error); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index eb28c35924..20d368efca 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -862,6 +862,57 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons return 1; } + if (STR_IN_SET(field, "SocketBindAllow", + "SocketBindDeny")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "a(iqq)", 0); + else { + const char *address_family, *user_port; + _cleanup_free_ char *word = NULL; + int family = AF_UNSPEC; + + 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); + + address_family = eq ? word : NULL; + if (address_family) { + if (!STR_IN_SET(address_family, "IPv4", "IPv6")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only IPv4 and IPv6 protocols are supported"); + + if (streq(address_family, "IPv4")) + family = AF_INET; + else + family = AF_INET6; + } + + user_port = eq ? eq : word; + if (streq(user_port, "any")) { + r = sd_bus_message_append(m, "(sv)", field, "a(iqq)", 1, family, 0, 0); + if (r < 0) + return bus_log_create_error(r); + } else { + uint16_t port_min, port_max; + + r = parse_ip_port_range(user_port, &port_min, &port_max); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Invalid port or port range: %s", user_port); + + r = sd_bus_message_append( + m, "(sv)", field, "a(iqq)", 1, family, port_max - port_min + 1, port_min); + } + } + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + return 0; } |