diff options
author | Topi Miettinen <toiwoton@gmail.com> | 2022-05-22 13:21:02 +0200 |
---|---|---|
committer | Topi Miettinen <topimiettinen@users.noreply.github.com> | 2022-06-08 18:12:25 +0200 |
commit | c0548df0a2f78f3422d77c77c2149d8a7f50d8f6 (patch) | |
tree | 4e363ae5071b1c60622f3f8e9ffa621bbeff3150 | |
parent | network: firewall integration with NFT sets (diff) | |
download | systemd-c0548df0a2f78f3422d77c77c2149d8a7f50d8f6.tar.xz systemd-c0548df0a2f78f3422d77c77c2149d8a7f50d8f6.zip |
core: firewall integration with ControlGroupNFTSet=
New directive `ControlGroupNFTSet=` provides a method for integrating services
into firewall rules with NFT sets.
Example:
```
table inet filter {
...
set timesyncd {
type cgroupsv2
}
chain ntp_output {
socket cgroupv2 != @timesyncd counter drop
accept
}
...
}
```
/etc/systemd/system/systemd-timesyncd.service.d/override.conf
```
[Service]
ControlGroupNFTSet=inet:filter:timesyncd
```
```
$ sudo nft list set inet filter timesyncd
table inet filter {
set timesyncd {
type cgroupsv2
elements = { "system.slice/systemd-timesyncd.service" }
}
}
```
-rw-r--r-- | man/org.freedesktop.systemd1.xml | 36 | ||||
-rw-r--r-- | man/systemd.resource-control.xml | 29 | ||||
-rw-r--r-- | src/core/cgroup.c | 52 | ||||
-rw-r--r-- | src/core/cgroup.h | 4 | ||||
-rw-r--r-- | src/core/dbus-cgroup.c | 85 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.in | 1 | ||||
-rw-r--r-- | src/core/load-fragment.c | 87 | ||||
-rw-r--r-- | src/core/load-fragment.h | 1 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 3 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.mount | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.scope | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.service | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.slice | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.socket | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.swap | 1 |
15 files changed, 304 insertions, 0 deletions
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 7974833554..6625a74073 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2599,6 +2599,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly a(sb) EnvironmentFiles = [...]; @@ -3170,6 +3172,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -3750,6 +3754,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -4487,6 +4493,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly a(sb) EnvironmentFiles = [...]; @@ -5082,6 +5090,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -5656,6 +5666,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -6282,6 +6294,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly a(sb) EnvironmentFiles = [...]; @@ -6805,6 +6819,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -7297,6 +7313,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -8050,6 +8068,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly as Environment = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly a(sb) EnvironmentFiles = [...]; @@ -8559,6 +8579,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--property EnvironmentFiles is not documented!--> <!--property PassEnvironment is not documented!--> @@ -9037,6 +9059,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <variablelist class="dbus-property" generated="True" extra-ref="Environment"/> <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/> @@ -9648,6 +9672,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { readonly a(iiqq) SocketBindDeny = [...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -9800,6 +9826,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--Autogenerated cross-references for systemd.directives, do not edit--> <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/> @@ -9958,6 +9986,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <!--End of Autogenerated section--> <refsect2> @@ -10138,6 +10168,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly (bas) RestrictNetworkInterfaces = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly a(iss) ControlGroupNFTSet = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s KillMode = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly i KillSignal = ...; @@ -10307,6 +10339,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { <!--property RestrictNetworkInterfaces is not documented!--> + <!--property ControlGroupNFTSet is not documented!--> + <!--property KillMode is not documented!--> <!--property KillSignal is not documented!--> @@ -10493,6 +10527,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { <variablelist class="dbus-property" generated="True" extra-ref="RestrictNetworkInterfaces"/> + <variablelist class="dbus-property" generated="True" extra-ref="ControlGroupNFTSet"/> + <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 1397b886c5..23b2d0f390 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -1173,6 +1173,35 @@ DeviceAllow=/dev/loop-control </para> </listitem> </varlistentry> + <varlistentry> + <term><varname>ControlGroupNFTSet=</varname><replaceable>family</replaceable>:<replaceable>table</replaceable>:<replaceable>set</replaceable></term> + <listitem> + <para>This setting provides a method for integrating dynamic cgroup IDs into firewall rules with + NFT sets. This option expects a whitespace separated list of NFT set definitions. Each definition + consists of a colon-separated tuple of NFT address family (one of <literal>arp</literal>, + <literal>bridge</literal>, <literal>inet</literal>, <literal>ip</literal>, <literal>ip6</literal>, + or <literal>netdev</literal>), table name and set name. The names of tables and sets must conform + to lexical restrictions of NFT table names. When a control group for a unit is realized, the cgroup + ID will be appended to the NFT sets and it will be be removed when the control group is + removed. Failures to manage the sets will be ignored.</para> + + <para>Example: + <programlisting>[Unit] +ControlGroupNFTSet=inet:filter:my_service +</programlisting> + Corresponding NFT rules: + <programlisting>table inet filter { + set my_service { + type cgroupsv2 + } + chain x { + socket cgroupv2 level 2 @my_service accept + drop + } +}</programlisting> + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 9282b1ff20..9a07a73f02 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -19,6 +19,7 @@ #include "devnum-util.h" #include "fd-util.h" #include "fileio.h" +#include "firewall-util.h" #include "in-addr-prefix-util.h" #include "inotify-util.h" #include "io-util.h" @@ -279,6 +280,8 @@ void cgroup_context_done(CGroupContext *c) { cpu_set_reset(&c->startup_cpuset_cpus); cpu_set_reset(&c->cpuset_mems); cpu_set_reset(&c->startup_cpuset_mems); + + c->nft_set_context = nft_set_context_free_many(c->nft_set_context, &c->n_nft_set_contexts); } static int unit_get_kernel_memory_limit(Unit *u, const char *file, uint64_t *ret) { @@ -617,6 +620,11 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { SET_FOREACH(iface, c->restrict_network_interfaces) fprintf(f, "%sRestrictNetworkInterfaces: %s\n", prefix, iface); } + + for (size_t i = 0; i < c->n_nft_set_contexts; i++) + fprintf(f, "%sControlGroupNFTSet: %s:%s:%s\n", prefix, + nfproto_to_string(c->nft_set_context[i].nfproto), + c->nft_set_context[i].table, c->nft_set_context[i].set); } void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) { @@ -1226,6 +1234,46 @@ static void cgroup_apply_firewall(Unit *u) { (void) bpf_firewall_install(u); } +static void cgroup_apply_nft_set(Unit *u) { + int r; + CGroupContext *c; + + assert(u); + + assert_se(c = unit_get_cgroup_context(u)); + + for (size_t i = 0; i < c->n_nft_set_contexts; i++) { + NFTSetContext *s = &c->nft_set_context[i]; + r = nft_set_element_add_uint64(s, u->cgroup_id); + if (r < 0) + log_warning_errno(r, "Adding NFT family %s table %s set %s cgroup %" PRIu64 " failed, ignoring: %m", + nfproto_to_string(s->nfproto), + s->table, + s->set, + u->cgroup_id); + } +} + +static void cgroup_delete_nft_set(Unit *u) { + int r; + CGroupContext *c; + + assert(u); + + assert_se(c = unit_get_cgroup_context(u)); + + for (size_t i = 0; i < c->n_nft_set_contexts; i++) { + NFTSetContext *s = &c->nft_set_context[i]; + r = nft_set_element_del_uint64(s, u->cgroup_id); + if (r < 0) + log_warning_errno(r, "Deleting NFT family %s table %s set %s cgroup %" PRIu64 " failed, ignoring: %m", + nfproto_to_string(s->nfproto), + s->table, + s->set, + u->cgroup_id); + } +} + static void cgroup_apply_socket_bind(Unit *u) { assert(u); @@ -1658,6 +1706,8 @@ static void cgroup_context_apply( if (apply_mask & CGROUP_MASK_BPF_RESTRICT_NETWORK_INTERFACES) cgroup_apply_restrict_network_interfaces(u); + + cgroup_apply_nft_set(u); } static bool unit_get_needs_bpf_firewall(Unit *u) { @@ -2807,6 +2857,8 @@ void unit_prune_cgroup(Unit *u) { (void) lsm_bpf_cleanup(u); /* Remove cgroup from the global LSM BPF map */ #endif + cgroup_delete_nft_set(u); + is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE); r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice); diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 4413eeaaa0..6ac28d7ca7 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -6,6 +6,7 @@ #include "bpf-lsm.h" #include "cgroup-util.h" #include "cpu-set-util.h" +#include "firewall-util.h" #include "list.h" #include "time-util.h" @@ -194,6 +195,9 @@ struct CGroupContext { ManagedOOMMode moom_mem_pressure; uint32_t moom_mem_pressure_limit; /* Normalized to 2^32-1 == 100% */ ManagedOOMPreference moom_preference; + + NFTSetContext *nft_set_context; + size_t n_nft_set_contexts; }; /* Used when querying IP accounting data */ diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 9a31355a4d..6070c21c4c 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -15,6 +15,7 @@ #include "errno-util.h" #include "fd-util.h" #include "fileio.h" +#include "firewall-util.h" #include "in-addr-prefix-util.h" #include "ip-protocol-list.h" #include "limits-util.h" @@ -443,6 +444,36 @@ static int property_get_restrict_network_interfaces( return sd_bus_message_close_container(reply); } +static int property_get_cgroup_nft_set( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + int r; + CGroupContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(iss)"); + if (r < 0) + return r; + + for (size_t i = 0; i < c->n_nft_set_contexts; i++) { + NFTSetContext *s = &c->nft_set_context[i]; + + r = sd_bus_message_append(reply, "(iss)", s->nfproto, s->table, s->set); + 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), @@ -500,6 +531,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("SocketBindAllow", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_allow), 0), SD_BUS_PROPERTY("SocketBindDeny", "a(iiqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0), SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0), + SD_BUS_PROPERTY("ControlGroupNFTSet", "a(iss)", property_get_cgroup_nft_set, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; @@ -2062,5 +2094,58 @@ int bus_cgroup_set_property( if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB)) return bus_cgroup_set_transient_property(u, c, name, message, flags, error); + if (streq(name, "ControlGroupNFTSet")) { + int nfproto; + const char *table, *set; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(iss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(iss)", &nfproto, &table, &set)) > 0) { + const char *nfproto_name; + + nfproto_name = nfproto_to_string(nfproto); + if (!nfproto_name) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid protocol %d.", nfproto); + + if (nft_identifier_bad(table)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NFT table name %s.", table); + + if (nft_identifier_bad(set)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NFT set name %s.", set); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = nft_set_context_add(&c->nft_set_context, &c->n_nft_set_contexts, nfproto, table, set); + if (r < 0) + return r; + + unit_write_settingf( + u, flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s:%s:%s", + name, + nfproto_name, + table, + set); + } + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (empty) { + c->nft_set_context = nft_set_context_free_many(c->nft_set_context, &c->n_nft_set_contexts); + unit_write_settingf(u, flags, name, "%s=", name); + } + + return 1; + } + return 0; } diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 7817c20c0b..0db24268d1 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -241,6 +241,7 @@ {{type}}.SocketBindAllow, config_parse_cgroup_socket_bind, 0, offsetof({{type}}, cgroup_context.socket_bind_allow) {{type}}.SocketBindDeny, config_parse_cgroup_socket_bind, 0, offsetof({{type}}, cgroup_context.socket_bind_deny) {{type}}.RestrictNetworkInterfaces, config_parse_restrict_network_interfaces, 0, offsetof({{type}}, cgroup_context) +{{type}}.ControlGroupNFTSet, config_parse_cgroup_nft_set, 0, offsetof({{type}}, cgroup_context) {%- endmacro -%} %{ diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 3ff6eae8fc..12c1af7933 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -35,8 +35,10 @@ #include "env-util.h" #include "errno-list.h" #include "escape.h" +#include "execute.h" #include "fd-util.h" #include "fileio.h" +#include "firewall-util.h" #include "fs-util.h" #include "hexdecoct.h" #include "io-util.h" @@ -6520,3 +6522,88 @@ int config_parse_tty_size( return config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata); } + +static int config_parse_nft_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + NFTSetContext **c, + size_t *n, + Unit *u) { + _cleanup_free_ char *family_str = NULL, *table = NULL, *set = NULL, *table_resolved = NULL, *set_resolved = NULL; + int nfproto, r; + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *c = nft_set_context_free_many(*c, n); + return 0; + } + + for (const char *p = rvalue;;) { + r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE, &family_str, &table, &set, NULL); + if (r == -ENOMEM) + return log_oom(); + if (r == 0) + break; + if (r != 3) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse NFT set, ignoring: %s", p); + return 0; + } + + nfproto = nfproto_from_string(family_str); + if (nfproto < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown NFT protocol family, ignoring: %s", family_str); + return 0; + } + + r = unit_path_printf(u, table, &table_resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", table); + return 0; + } + + if (nft_identifier_bad(table_resolved)) + return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid table name %s, ignoring", table); + + r = unit_path_printf(u, set, &set_resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", set); + return 0; + } + + if (nft_identifier_bad(set_resolved)) + return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid set name %s, ignoring", set); + + r = nft_set_context_add(c, n, nfproto, table_resolved, set_resolved); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_cgroup_nft_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + CGroupContext *c = data; + Unit *u = userdata; + + return config_parse_nft_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &c->nft_set_context, &c->n_nft_set_contexts, u); +} diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 26b8de28f7..3632b5b096 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -150,6 +150,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_socket_bind); CONFIG_PARSER_PROTOTYPE(config_parse_restrict_network_interfaces); CONFIG_PARSER_PROTOTYPE(config_parse_watchdog_sec); CONFIG_PARSER_PROTOTYPE(config_parse_tty_size); +CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index a326ca30a9..e1584c2e8d 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -891,6 +891,9 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons return 1; } + if (streq(field, "ControlGroupNFTSet")) + return bus_append_nft_set(m, field, eq); + return 0; } diff --git a/test/fuzz/fuzz-unit-file/directives.mount b/test/fuzz/fuzz-unit-file/directives.mount index 0a44328e5c..2b3331a411 100644 --- a/test/fuzz/fuzz-unit-file/directives.mount +++ b/test/fuzz/fuzz-unit-file/directives.mount @@ -28,6 +28,7 @@ Capabilities= CapabilityBoundingSet= ConfigurationDirectory= ConfigurationDirectoryMode= +ControlGroupNFTSet= CoredumpFilter= DefaultMemoryLow= DefaultMemoryMin= diff --git a/test/fuzz/fuzz-unit-file/directives.scope b/test/fuzz/fuzz-unit-file/directives.scope index 4552d0b403..c4d579065a 100644 --- a/test/fuzz/fuzz-unit-file/directives.scope +++ b/test/fuzz/fuzz-unit-file/directives.scope @@ -8,6 +8,7 @@ BlockIODeviceWeight= BlockIOReadBandwidth= BlockIOWeight= BlockIOWriteBandwidth= +ControlGroupNFTSet= CPUAccounting= CPUQuota= CPUQuotaPeriodSec= diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 3c33d947fe..30e6936d12 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -72,6 +72,7 @@ ConditionSecurity= ConditionUser= ConditionVirtualization= Conflicts= +ControlGroupNFTSet= DefaultDependencies= Description= Documentation= diff --git a/test/fuzz/fuzz-unit-file/directives.slice b/test/fuzz/fuzz-unit-file/directives.slice index ab77070c5e..749f1795e3 100644 --- a/test/fuzz/fuzz-unit-file/directives.slice +++ b/test/fuzz/fuzz-unit-file/directives.slice @@ -8,6 +8,7 @@ BlockIODeviceWeight= BlockIOReadBandwidth= BlockIOWeight= BlockIOWriteBandwidth= +ControlGroupNFTSet= CPUAccounting= CPUQuota= CPUQuotaPeriodSec= diff --git a/test/fuzz/fuzz-unit-file/directives.socket b/test/fuzz/fuzz-unit-file/directives.socket index 90358fc11a..1b1ddf8c9c 100644 --- a/test/fuzz/fuzz-unit-file/directives.socket +++ b/test/fuzz/fuzz-unit-file/directives.socket @@ -33,6 +33,7 @@ Capabilities= CapabilityBoundingSet= ConfigurationDirectory= ConfigurationDirectoryMode= +ControlGroupNFTSet= CoredumpFilter= DefaultMemoryLow= DefaultMemoryMin= diff --git a/test/fuzz/fuzz-unit-file/directives.swap b/test/fuzz/fuzz-unit-file/directives.swap index 5d057fa630..186dedbf3e 100644 --- a/test/fuzz/fuzz-unit-file/directives.swap +++ b/test/fuzz/fuzz-unit-file/directives.swap @@ -28,6 +28,7 @@ Capabilities= CapabilityBoundingSet= ConfigurationDirectory= ConfigurationDirectoryMode= +ControlGroupNFTSet= CoredumpFilter= DefaultMemoryLow= DefaultMemoryMin= |