]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/dbus-cgroup.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
index 5347525844e27e7e8bfa55bdb79c1eef82529076..4c0b3ddf9c27972efcc9430652891053fc901a17 100644 (file)
 #include "dbus-cgroup.h"
 #include "dbus-util.h"
 #include "errno-util.h"
+#include "escape.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"
@@ -25,7 +27,7 @@
 #include "percent-util.h"
 #include "socket-util.h"
 
-BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
+BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", CGroupTasksMax, cgroup_tasks_max_resolve);
 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_cgroup_pressure_watch, cgroup_pressure_watch, CGroupPressureWatch);
 
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
@@ -279,19 +281,7 @@ static int property_get_device_allow(
                 return r;
 
         LIST_FOREACH(device_allow, a, c->device_allow) {
-                unsigned k = 0;
-                char rwm[4];
-
-                if (a->r)
-                        rwm[k++] = 'r';
-                if (a->w)
-                        rwm[k++] = 'w';
-                if (a->m)
-                        rwm[k++] = 'm';
-
-                rwm[k] = 0;
-
-                r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
+                r = sd_bus_message_append(reply, "(ss)", a->path, cgroup_device_permissions_to_string(a->permissions));
                 if (r < 0)
                         return r;
         }
@@ -423,6 +413,34 @@ 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', "(iiss)");
+        if (r < 0)
+                return r;
+
+        FOREACH_ARRAY(nft_set, c->nft_set_context.sets, c->nft_set_context.n_sets) {
+                r = sd_bus_message_append(reply, "(iiss)", nft_set->source, nft_set->nfproto, nft_set->table, nft_set->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),
@@ -490,6 +508,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_PROPERTY("RestrictNetworkInterfaces", "(bas)", property_get_restrict_network_interfaces, 0, 0),
         SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(CGroupContext, memory_pressure_watch), 0),
         SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, memory_pressure_threshold_usec), 0),
+        SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set, 0, 0),
+        SD_BUS_PROPERTY("CoredumpReceive", "b", bus_property_get_bool, offsetof(CGroupContext, coredump_receive), 0),
         SD_BUS_VTABLE_END
 };
 
@@ -715,7 +735,7 @@ static int bus_cgroup_set_transient_property(
                                                 name);
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                                r = cgroup_add_bpf_foreign_program(c, attach_type, p);
+                                r = cgroup_context_add_bpf_foreign_program(c, attach_type, p);
                                 if (r < 0)
                                         return r;
                         }
@@ -808,6 +828,23 @@ static int bus_cgroup_set_transient_property(
                                 unit_write_settingf(u, flags, name, "MemoryPressureThresholdUSec=%" PRIu64, t);
                 }
 
+                return 1;
+        } else if (streq(name, "CoredumpReceive")) {
+                int b;
+
+                if (!UNIT_VTABLE(u)->can_delegate)
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
+
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
+
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        c->coredump_receive = b;
+
+                        unit_write_settingf(u, flags, name, "CoredumpReceive=%s", yes_no(b));
+                }
+
                 return 1;
         }
 
@@ -994,7 +1031,7 @@ static int bus_cgroup_set_cpu_weight(
 static int bus_cgroup_set_tasks_max(
                 Unit *u,
                 const char *name,
-                TasksMax *p,
+                CGroupTasksMax *p,
                 sd_bus_message *message,
                 UnitWriteFlags flags,
                 sd_bus_error *error) {
@@ -1013,7 +1050,7 @@ static int bus_cgroup_set_tasks_max(
                                          "Value specified in %s is out of range", name);
 
         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                *p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */
+                *p = (CGroupTasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */
                 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
 
                 if (v == CGROUP_LIMIT_MAX)
@@ -1030,7 +1067,7 @@ static int bus_cgroup_set_tasks_max(
 static int bus_cgroup_set_tasks_max_scale(
                 Unit *u,
                 const char *name,
-                TasksMax *p,
+                CGroupTasksMax *p,
                 sd_bus_message *message,
                 UnitWriteFlags flags,
                 sd_bus_error *error) {
@@ -1049,7 +1086,7 @@ static int bus_cgroup_set_tasks_max_scale(
                                          "Value specified in %s is out of range", name);
 
         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                *p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
+                *p = (CGroupTasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
                 unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
 
                 uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX);
@@ -1779,41 +1816,23 @@ int bus_cgroup_set_property(
                         return r;
 
                 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
+                        CGroupDevicePermissions p;
 
                         if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
 
                         if (isempty(rwm))
-                                rwm = "rwm";
-                        else if (!in_charset(rwm, "rwm"))
-                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
+                                p = _CGROUP_DEVICE_PERMISSIONS_ALL;
+                        else {
+                                p = cgroup_device_permissions_from_string(rwm);
+                                if (p < 0)
+                                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
+                        }
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                                CGroupDeviceAllow *a = NULL;
-
-                                LIST_FOREACH(device_allow, b, c->device_allow)
-                                        if (path_equal(b->path, path)) {
-                                                a = b;
-                                                break;
-                                        }
-
-                                if (!a) {
-                                        a = new0(CGroupDeviceAllow, 1);
-                                        if (!a)
-                                                return -ENOMEM;
-
-                                        a->path = strdup(path);
-                                        if (!a->path) {
-                                                free(a);
-                                                return -ENOMEM;
-                                        }
-
-                                        LIST_PREPEND(device_allow, c->device_allow, a);
-                                }
-
-                                a->r = strchr(rwm, 'r');
-                                a->w = strchr(rwm, 'w');
-                                a->m = strchr(rwm, 'm');
+                                r = cgroup_context_add_or_update_device_allow(c, path, p);
+                                if (r < 0)
+                                        return r;
                         }
 
                         n++;
@@ -1842,7 +1861,7 @@ int bus_cgroup_set_property(
 
                         fputs("DeviceAllow=\n", f);
                         LIST_FOREACH(device_allow, a, c->device_allow)
-                                fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
+                                fprintf(f, "DeviceAllow=%s %s\n", a->path, cgroup_device_permissions_to_string(a->permissions));
 
                         r = memstream_finalize(&m, &buf, NULL);
                         if (r < 0)
@@ -2169,7 +2188,7 @@ int bus_cgroup_set_property(
                                 c->restrict_network_interfaces_is_allow_list = is_allow_list;
 
                         STRV_FOREACH(s, l) {
-                                if (!ifname_valid(*s)) {
+                                if (!ifname_valid_full(*s, IFNAME_VALID_ALTERNATIVE)) {
                                         log_full(LOG_WARNING, "Invalid interface name, ignoring: %s", *s);
                                         continue;
                                 }
@@ -2192,6 +2211,75 @@ int bus_cgroup_set_property(
                 return 1;
         }
 
+        if (streq(name, "NFTSet")) {
+                int source, nfproto;
+                const char *table, *set;
+                bool empty = true;
+
+                r = sd_bus_message_enter_container(message, 'a', "(iiss)");
+                if (r < 0)
+                        return r;
+
+                while ((r = sd_bus_message_read(message, "(iiss)", &source, &nfproto, &table, &set)) > 0) {
+                        const char *source_name, *nfproto_name;
+
+                        if (!IN_SET(source, NFT_SET_SOURCE_CGROUP, NFT_SET_SOURCE_USER, NFT_SET_SOURCE_GROUP))
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid source %d.", source);
+
+                        source_name = nft_set_source_to_string(source);
+                        assert(source_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_valid(table)) {
+                                _cleanup_free_ char *esc = NULL;
+
+                                esc = cescape(table);
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NFT table name %s.", strna(esc));
+                        }
+
+                        if (!nft_identifier_valid(set)) {
+                                _cleanup_free_ char *esc = NULL;
+
+                                esc = cescape(set);
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NFT set name %s.", strna(esc));
+                        }
+
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                                r = nft_set_add(&c->nft_set_context, source, nfproto, table, set);
+                                if (r < 0)
+                                        return r;
+
+                                unit_write_settingf(
+                                                u, flags|UNIT_ESCAPE_SPECIFIERS, name,
+                                                "%s=%s:%s:%s:%s",
+                                                name,
+                                                source_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 && !UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        nft_set_context_clear(&c->nft_set_context);
+                        unit_write_settingf(u, flags, name, "%s=", name);
+                }
+
+                return 1;
+        }
+
+        /* must be last */
         if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
                 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);