summaryrefslogtreecommitdiff
path: root/src/core/dbus-execute.c
diff options
context:
space:
mode:
authorTopi Miettinen <toiwoton@gmail.com>2022-05-22 15:17:24 +0300
committerTopi Miettinen <topimiettinen@users.noreply.github.com>2022-06-08 16:12:25 +0000
commit46c3b1ff887e096f89cb1eae9b2567c5dd4272d3 (patch)
treef834624ca67c0a8b8dbf586dcbb6b1a3a14045c0 /src/core/dbus-execute.c
parentc0548df0a2f78f3422d77c77c2149d8a7f50d8f6 (diff)
downloadsystemd-46c3b1ff887e096f89cb1eae9b2567c5dd4272d3.tar.gz
core: firewall integration with DynamicUserNFTSet=
New directive `DynamicUserNFTSet=` provides a method for integrating configuration of dynamic users into firewall rules with NFT sets. Example: ``` table inet filter { set u { typeof meta skuid } chain service_output { meta skuid != @u drop accept } } ``` ``` /etc/systemd/system/dunft.service [Service] DynamicUser=yes DynamicUserNFTSet=inet:filter:u ExecStart=/bin/sleep 1000 [Install] WantedBy=multi-user.target ``` ``` $ sudo nft list set inet filter u table inet filter { set u { typeof meta skuid elements = { 64864 } } } $ ps -n --format user,group,pid,command -p `pgrep sleep` USER GROUP PID COMMAND 64864 64864 55158 /bin/sleep 1000 ```
Diffstat (limited to 'src/core/dbus-execute.c')
-rw-r--r--src/core/dbus-execute.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index a4c37307d2..a3e54e6411 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -22,6 +22,7 @@
#include "execute.h"
#include "fd-util.h"
#include "fileio.h"
+#include "firewall-util.h"
#include "hexdecoct.h"
#include "io-util.h"
#include "ioprio-util.h"
@@ -1138,6 +1139,37 @@ static int bus_property_get_exec_dir_symlink(
return sd_bus_message_close_container(reply);
}
+static int property_get_dynamic_user_nft_set(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+ int r;
+
+ 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_dynamic_user_nft_set_contexts; i++) {
+ NFTSetContext *s = &c->dynamic_user_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_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1232,6 +1264,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DynamicUserNFTSet", "a(iss)", property_get_dynamic_user_nft_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SetCredentialEncrypted", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -3503,6 +3536,58 @@ int bus_exec_context_set_transient_property(
return 1;
+ } else if (streq(name, "DynamicUserNFTSet")) {
+ 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->dynamic_user_nft_set_context, &c->n_dynamic_user_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->dynamic_user_nft_set_context = nft_set_context_free_many(c->dynamic_user_nft_set_context, &c->n_dynamic_user_nft_set_contexts);
+ unit_write_settingf(u, flags, name, "%s=", name);
+ }
+
+ return 1;
+
} else if ((suffix = startswith(name, "Limit"))) {
const char *soft = NULL;
int ri;