]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/machine/machined-dbus.c
Merge pull request #2267 from gdamjan/dont-drop-critical
[thirdparty/systemd.git] / src / machine / machined-dbus.c
index 3637815fc9b15e79b35cbc4d209facd48edffe0f..e448dd2035fb108fc87a4731e74a3ae98fd1f0bb 100644 (file)
 #include <unistd.h>
 
 #include "sd-id128.h"
-#include "strv.h"
-#include "path-util.h"
-#include "unit-name.h"
-#include "bus-util.h"
+
+#include "alloc-util.h"
+#include "btrfs-util.h"
 #include "bus-common-errors.h"
+#include "bus-util.h"
 #include "cgroup-util.h"
-#include "btrfs-util.h"
+#include "fd-util.h"
 #include "formats-util.h"
-#include "process-util.h"
+#include "hostname-util.h"
+#include "image-dbus.h"
+#include "machine-dbus.h"
 #include "machine-image.h"
 #include "machine-pool.h"
-#include "image-dbus.h"
 #include "machined.h"
-#include "machine-dbus.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "stdio-util.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "user-util.h"
 
 static int property_get_pool_path(
                 sd_bus *bus,
@@ -78,7 +84,7 @@ static int property_get_pool_usage(
         if (fd >= 0) {
                 BtrfsQuotaInfo q;
 
-                if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
+                if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
                         usage = q.referenced;
         }
 
@@ -114,7 +120,7 @@ static int property_get_pool_limit(
         if (fd >= 0) {
                 BtrfsQuotaInfo q;
 
-                if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
+                if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
                         size = q.referenced_max;
         }
 
@@ -193,8 +199,11 @@ static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd
         if (r < 0)
                 return r;
 
+        if (pid < 0)
+                return -EINVAL;
+
         if (pid == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -219,7 +228,7 @@ static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd
 }
 
 static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Manager *m = userdata;
         Machine *machine;
         Iterator i;
@@ -324,7 +333,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
 
         if (leader == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
 
                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
@@ -545,7 +554,7 @@ static int method_get_machine_os_release(sd_bus_message *message, void *userdata
 }
 
 static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
         Manager *m = userdata;
         Image *image;
@@ -637,6 +646,27 @@ static int method_open_machine_login(sd_bus_message *message, void *userdata, sd
         return bus_machine_method_open_login(message, machine, error);
 }
 
+static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+        Machine *machine;
+        const char *name;
+
+        int r;
+
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return r;
+
+        machine = hashmap_get(m->machines, name);
+        if (!machine)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+
+        return bus_machine_method_open_shell(message, machine, error);
+}
+
 static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         Machine *machine;
@@ -788,6 +818,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
                         message,
                         CAP_SYS_ADMIN,
                         "org.freedesktop.machine1.manage-machines",
+                        NULL,
                         false,
                         UID_INVALID,
                         &m->polkit_registry,
@@ -808,7 +839,9 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
         if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
                 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
 
-        r = btrfs_quota_limit("/var/lib/machines", limit);
+        (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit);
+
+        r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit);
         if (r == -ENOTTY)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
         if (r < 0)
@@ -853,13 +886,16 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
         if (r < 0)
                 return r;
 
-        if (UID_IS_INVALID(uid))
+        if (!uid_is_valid(uid))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
 
         machine = hashmap_get(m->machines, name);
         if (!machine)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
+        if (machine->class != MACHINE_CONTAINER)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
+
         p = procfs_file_alloca(machine->leader, "uid_map");
         f = fopen(p, "re");
         if (!f)
@@ -874,7 +910,7 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
                 if (k < 0 && feof(f))
                         break;
                 if (k != 3) {
-                        if (ferror(f) && errno != 0)
+                        if (ferror(f) && errno > 0)
                                 return -errno;
 
                         return -EIO;
@@ -884,7 +920,7 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
                         continue;
 
                 converted = uid - uid_base + uid_shift;
-                if (UID_IS_INVALID(converted))
+                if (!uid_is_valid(converted))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
 
                 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
@@ -903,7 +939,7 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
         r = sd_bus_message_read(message, "u", &uid);
         if (r < 0)
                 return r;
-        if (UID_IS_INVALID(uid))
+        if (!uid_is_valid(uid))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
         if (uid < 0x10000)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
@@ -912,6 +948,9 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
                 _cleanup_fclose_ FILE *f = NULL;
                 char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
 
+                if (machine->class != MACHINE_CONTAINER)
+                        continue;
+
                 xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
                 f = fopen(p, "re");
                 if (!f) {
@@ -929,7 +968,7 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
                         if (k < 0 && feof(f))
                                 break;
                         if (k != 3) {
-                                if (ferror(f) && errno != 0)
+                                if (ferror(f) && errno > 0)
                                         return -errno;
 
                                 return -EIO;
@@ -939,7 +978,7 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
                                 continue;
 
                         converted = (uid - uid_shift + uid_base);
-                        if (UID_IS_INVALID(converted))
+                        if (!uid_is_valid(converted))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
 
                         o = machine_bus_path(machine);
@@ -965,13 +1004,16 @@ static int method_map_from_machine_group(sd_bus_message *message, void *groupdat
         if (r < 0)
                 return r;
 
-        if (GID_IS_INVALID(gid))
+        if (!gid_is_valid(gid))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
 
         machine = hashmap_get(m->machines, name);
         if (!machine)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
+        if (machine->class != MACHINE_CONTAINER)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
+
         p = procfs_file_alloca(machine->leader, "gid_map");
         f = fopen(p, "re");
         if (!f)
@@ -986,7 +1028,7 @@ static int method_map_from_machine_group(sd_bus_message *message, void *groupdat
                 if (k < 0 && feof(f))
                         break;
                 if (k != 3) {
-                        if (ferror(f) && errno != 0)
+                        if (ferror(f) && errno > 0)
                                 return -errno;
 
                         return -EIO;
@@ -996,7 +1038,7 @@ static int method_map_from_machine_group(sd_bus_message *message, void *groupdat
                         continue;
 
                 converted = gid - gid_base + gid_shift;
-                if (GID_IS_INVALID(converted))
+                if (!gid_is_valid(converted))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
 
                 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
@@ -1015,7 +1057,7 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
         r = sd_bus_message_read(message, "u", &gid);
         if (r < 0)
                 return r;
-        if (GID_IS_INVALID(gid))
+        if (!gid_is_valid(gid))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
         if (gid < 0x10000)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
@@ -1024,6 +1066,9 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
                 _cleanup_fclose_ FILE *f = NULL;
                 char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
 
+                if (machine->class != MACHINE_CONTAINER)
+                        continue;
+
                 xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
                 f = fopen(p, "re");
                 if (!f) {
@@ -1041,7 +1086,7 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
                         if (k < 0 && feof(f))
                                 break;
                         if (k != 3) {
-                                if (ferror(f) && errno != 0)
+                                if (ferror(f) && errno > 0)
                                         return -errno;
 
                                 return -EIO;
@@ -1051,7 +1096,7 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
                                 continue;
 
                         converted = (gid - gid_shift + gid_base);
-                        if (GID_IS_INVALID(converted))
+                        if (!gid_is_valid(converted))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
 
                         o = machine_bus_path(machine);
@@ -1085,6 +1130,7 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
         SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -1116,7 +1162,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
 
         machine = hashmap_get(m->machine_units, unit);
@@ -1124,21 +1170,21 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
                 return 0;
 
         if (streq_ptr(path, machine->scope_job)) {
-                free(machine->scope_job);
-                machine->scope_job = NULL;
+                machine->scope_job = mfree(machine->scope_job);
 
                 if (machine->started) {
                         if (streq(result, "done"))
                                 machine_send_create_reply(machine, NULL);
                         else {
-                                _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+                                _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
 
                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
 
                                 machine_send_create_reply(machine, &e);
                         }
-                } else
-                        machine_save(machine);
+                }
+
+                machine_save(machine);
         }
 
         machine_add_to_gc_queue(machine);
@@ -1147,7 +1193,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
 
 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *unit = NULL;
-        const char *path, *interface;
+        const char *path;
         Manager *m = userdata;
         Machine *machine;
         int r;
@@ -1171,36 +1217,6 @@ int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_err
         if (!machine)
                 return 0;
 
-        r = sd_bus_message_read(message, "s", &interface);
-        if (r < 0) {
-                bus_log_parse_error(r);
-                return 0;
-        }
-
-        if (streq(interface, "org.freedesktop.systemd1.Unit")) {
-                struct properties {
-                        char *active_state;
-                        char *sub_state;
-                } properties = {};
-
-                const struct bus_properties_map map[] = {
-                        { "ActiveState", "s", NULL, offsetof(struct properties, active_state) },
-                        { "SubState",    "s", NULL, offsetof(struct properties, sub_state)    },
-                        {}
-                };
-
-                r = bus_message_map_properties_changed(message, map, &properties);
-                if (r < 0)
-                        bus_log_parse_error(r);
-                else if (streq_ptr(properties.active_state, "inactive") ||
-                         streq_ptr(properties.active_state, "failed") ||
-                         streq_ptr(properties.sub_state, "auto-restart"))
-                        machine_release_unit(machine);
-
-                free(properties.active_state);
-                free(properties.sub_state);
-        }
-
         machine_add_to_gc_queue(machine);
         return 0;
 }
@@ -1224,9 +1240,7 @@ int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *er
         if (!machine)
                 return 0;
 
-        machine_release_unit(machine);
         machine_add_to_gc_queue(machine);
-
         return 0;
 }
 
@@ -1242,7 +1256,7 @@ int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error
         r = sd_bus_message_read(message, "b", &b);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
         if (b)
                 return 0;
@@ -1266,7 +1280,7 @@ int manager_start_scope(
                 sd_bus_error *error,
                 char **job) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
         int r;
 
         assert(manager);
@@ -1311,6 +1325,10 @@ int manager_start_scope(
         if (r < 0)
                 return r;
 
+        r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
+        if (r < 0)
+                return bus_log_create_error(r);
+
         if (more_properties) {
                 r = sd_bus_message_copy(m, more_properties, true);
                 if (r < 0)
@@ -1348,7 +1366,7 @@ int manager_start_scope(
 }
 
 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
@@ -1411,8 +1429,8 @@ int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_erro
 }
 
 int manager_unit_is_active(Manager *manager, const char *unit) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
         const char *state;
         int r;
@@ -1453,8 +1471,8 @@ int manager_unit_is_active(Manager *manager, const char *unit) {
 }
 
 int manager_job_is_active(Manager *manager, const char *path) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
@@ -1487,7 +1505,6 @@ int manager_job_is_active(Manager *manager, const char *path) {
 }
 
 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
-        _cleanup_free_ char *unit = NULL;
         Machine *mm;
         int r;
 
@@ -1495,12 +1512,14 @@ int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
         assert(pid >= 1);
         assert(machine);
 
-        r = cg_pid_get_unit(pid, &unit);
-        if (r < 0)
-                mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
-        else
-                mm = hashmap_get(m->machine_units, unit);
+        mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid));
+        if (!mm) {
+                _cleanup_free_ char *unit = NULL;
 
+                r = cg_pid_get_unit(pid, &unit);
+                if (r >= 0)
+                        mm = hashmap_get(m->machine_units, unit);
+        }
         if (!mm)
                 return 0;
 
@@ -1516,7 +1535,7 @@ int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
 
         machine = hashmap_get(m->machines, name);
         if (!machine) {
-                machine = machine_new(m, name);
+                machine = machine_new(m, _MACHINE_CLASS_INVALID, name);
                 if (!machine)
                         return -ENOMEM;
         }