diff options
author | Topi Miettinen <toiwoton@gmail.com> | 2022-05-22 14:21:02 +0300 |
---|---|---|
committer | Topi Miettinen <topimiettinen@users.noreply.github.com> | 2022-06-08 16:12:25 +0000 |
commit | c0548df0a2f78f3422d77c77c2149d8a7f50d8f6 (patch) | |
tree | 4e363ae5071b1c60622f3f8e9ffa621bbeff3150 /src/core/cgroup.c | |
parent | ab51fd9dbdc59f9a37acd8acaea3e9088d092bba (diff) | |
download | systemd-c0548df0a2f78f3422d77c77c2149d8a7f50d8f6.tar.gz |
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" }
}
}
```
Diffstat (limited to 'src/core/cgroup.c')
-rw-r--r-- | src/core/cgroup.c | 52 |
1 files changed, 52 insertions, 0 deletions
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); |