]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/machine/machine-dbus.c
docs/DAEMON_SOCKET_ACTIVATION
[thirdparty/systemd.git] / src / machine / machine-dbus.c
index 75f397dd6bac8ee27f9d9c6389b7a6968fc1eb54..a4f04c0b86df39abb7a4a5d7594b28a7247036bf 100644 (file)
@@ -19,7 +19,7 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "in-addr-util.h"
-#include "io-util.h"
+#include "iovec-util.h"
 #include "local-addresses.h"
 #include "machine-dbus.h"
 #include "machine.h"
@@ -73,11 +73,8 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_KILL,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -106,11 +103,8 @@ int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_KILL,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -157,11 +151,8 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_KILL,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -223,9 +214,9 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
         }
 
         case MACHINE_CONTAINER: {
-                _cleanup_close_pair_ int pair[2] = { -1, -1 };
+                _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
                 _cleanup_free_ char *us = NULL, *them = NULL;
-                _cleanup_close_ int netns_fd = -1;
+                _cleanup_close_ int netns_fd = -EBADF;
                 const char *p;
                 pid_t child;
 
@@ -233,7 +224,7 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
                 if (r < 0)
                         return r;
 
-                p = procfs_file_alloca(m->leader, "ns/net");
+                p = procfs_file_alloca(m->leader.pid, "ns/net");
                 r = readlink_malloc(p, &them);
                 if (r < 0)
                         return r;
@@ -241,14 +232,19 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
                 if (streq(us, them))
                         return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
 
-                r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL);
+                r = namespace_open(m->leader.pid,
+                                   /* ret_pidns_fd = */ NULL,
+                                   /* ret_mntns_fd = */ NULL,
+                                   &netns_fd,
+                                   /* ret_userns_fd = */ NULL,
+                                   /* ret_root_fd = */ NULL);
                 if (r < 0)
                         return r;
 
                 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
                         return -errno;
 
-                r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+                r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
                                    -1, -1, netns_fd, -1, -1, &child);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
@@ -351,6 +347,27 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
         return sd_bus_send(NULL, reply, NULL);
 }
 
+int bus_machine_method_get_ssh_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        Machine *m = ASSERT_PTR(userdata);
+        int r;
+
+        assert(message);
+
+        r = sd_bus_message_new_method_return(message, &reply);
+        if (r < 0)
+                return r;
+
+        if (!m->ssh_address || !m->ssh_private_key_path)
+                return -ENOENT;
+
+        r = sd_bus_message_append(reply, "ss", m->ssh_address, m->ssh_private_key_path);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(NULL, reply, NULL);
+}
+
 #define EXIT_NOT_FOUND 2
 
 int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -370,25 +387,30 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
                 break;
 
         case MACHINE_CONTAINER: {
-                _cleanup_close_ int mntns_fd = -1, root_fd = -1, pidns_fd = -1;
-                _cleanup_close_pair_ int pair[2] = { -1, -1 };
+                _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
+                _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
                 _cleanup_fclose_ FILE *f = NULL;
                 pid_t child;
 
-                r = namespace_open(m->leader, &pidns_fd, &mntns_fd, NULL, NULL, &root_fd);
+                r = namespace_open(m->leader.pid,
+                                   &pidns_fd,
+                                   &mntns_fd,
+                                   /* ret_netns_fd = */ NULL,
+                                   /* ret_userns_fd = */ NULL,
+                                   &root_fd);
                 if (r < 0)
                         return r;
 
                 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
                         return -errno;
 
-                r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+                r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
                                    pidns_fd, mntns_fd, -1, -1, root_fd,
                                    &child);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
                 if (r == 0) {
-                        int fd = -1;
+                        int fd = -EBADF;
 
                         pair[0] = safe_close(pair[0]);
 
@@ -436,7 +458,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
 int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *pty_name = NULL;
-        _cleanup_close_ int master = -1;
+        _cleanup_close_ int master = -EBADF;
         Machine *m = ASSERT_PTR(userdata);
         int r;
 
@@ -449,11 +471,8 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -496,13 +515,13 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
                 if (r < 0)
                         return r;
 
-                if (asprintf(&address, "x-machine-unix:pid=%" PID_PRI, m->leader) < 0)
+                if (asprintf(&address, "x-machine-unix:pid=%" PID_PRI, m->leader.pid) < 0)
                         return -ENOMEM;
 
                 bus->address = address;
                 bus->bus_client = true;
                 bus->trusted = false;
-                bus->is_system = true;
+                bus->runtime_scope = RUNTIME_SCOPE_SYSTEM;
 
                 r = sd_bus_start(bus);
                 if (r == -ENOENT)
@@ -525,7 +544,7 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_free_ char *pty_name = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
-        _cleanup_close_ int master = -1;
+        _cleanup_close_ int master = -EBADF;
         sd_bus *container_bus = NULL;
         Machine *m = ASSERT_PTR(userdata);
         const char *p, *getty;
@@ -541,11 +560,8 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -588,8 +604,9 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
         _cleanup_free_ char *pty_name = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
         sd_bus *container_bus = NULL;
-        _cleanup_close_ int master = -1, slave = -1;
+        _cleanup_close_ int master = -EBADF, slave = -EBADF;
         _cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
+        _cleanup_free_ char *command_line = NULL;
         Machine *m = ASSERT_PTR(userdata);
         const char *p, *unit, *user, *path, *description, *utmp_id;
         int r;
@@ -642,20 +659,21 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
         if (!strv_env_is_valid(env))
                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
 
+        command_line = strv_join(args, " ");
+        if (!command_line)
+                return -ENOMEM;
         const char *details[] = {
                 "machine", m->name,
                 "user", user,
                 "program", path,
+                "command_line", command_line,
                 NULL
         };
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -856,11 +874,8 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -875,10 +890,13 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
                 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied.");
 
         propagate_directory = strjoina("/run/systemd/nspawn/propagate/", m->name);
-        r = bind_mount_in_namespace(m->leader,
-                                    propagate_directory,
-                                    "/run/host/incoming/",
-                                    src, dest, read_only, make_file_or_directory);
+        r = bind_mount_in_namespace(
+                        &m->leader,
+                        propagate_directory,
+                        "/run/host/incoming/",
+                        src, dest,
+                        read_only,
+                        make_file_or_directory);
         if (r < 0)
                 return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in machine's namespace: %m", src, dest);
 
@@ -888,9 +906,9 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
 int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *host_basename = NULL, *container_basename = NULL;
         const char *src, *dest, *host_path, *container_path;
-        _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
+        _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
         CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS;
-        _cleanup_close_ int hostfd = -1;
+        _cleanup_close_ int hostfd = -EBADF;
         Machine *m = ASSERT_PTR(userdata);
         bool copy_from;
         pid_t child;
@@ -941,11 +959,8 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -992,7 +1007,7 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
 
                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
 
-                q = procfs_file_alloca(m->leader, "ns/mnt");
+                q = procfs_file_alloca(m->leader.pid, "ns/mnt");
                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
                 if (mntfd < 0) {
                         r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
@@ -1010,13 +1025,13 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
                         goto child_fail;
                 }
 
-                /* Run the actual copy operation. Note that when an UID shift is set we'll either clamp the UID/GID to
+                /* Run the actual copy operation. Note that when a UID shift is set we'll either clamp the UID/GID to
                  * 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy
                  * the UID/GIDs as they are. */
                 if (copy_from)
-                        r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL);
+                        r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL, NULL);
                 else
-                        r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL);
+                        r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL, NULL);
 
                 hostfd = safe_close(hostfd);
                 containerfd = safe_close(containerfd);
@@ -1042,13 +1057,13 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
                 (void) sigkill_wait(child);
                 return r;
         }
-        errno_pipe_fd[0] = -1;
+        errno_pipe_fd[0] = -EBADF;
 
         return 1;
 }
 
 int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         Machine *m = ASSERT_PTR(userdata);
         int r;
 
@@ -1062,11 +1077,8 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
 
         r = bus_verify_polkit_async(
                         message,
-                        CAP_SYS_ADMIN,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        false,
-                        UID_INVALID,
                         &m->manager->polkit_registry,
                         error);
         if (r < 0)
@@ -1084,23 +1096,28 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
                 break;
 
         case MACHINE_CONTAINER: {
-                _cleanup_close_ int mntns_fd = -1, root_fd = -1;
-                _cleanup_close_pair_ int pair[2] = { -1, -1 };
+                _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF;
+                _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
                 pid_t child;
 
-                r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
+                r = namespace_open(m->leader.pid,
+                                   /* ret_pidns_fd = */ NULL,
+                                   &mntns_fd,
+                                   /* ret_netns_fd = */ NULL,
+                                   /* ret_userns_fd = */ NULL,
+                                   &root_fd);
                 if (r < 0)
                         return r;
 
                 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
                         return -errno;
 
-                r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+                r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
                                    -1, mntns_fd, -1, -1, root_fd, &child);
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
                 if (r == 0) {
-                        _cleanup_close_ int dfd = -1;
+                        _cleanup_close_ int dfd = -EBADF;
 
                         pair[0] = safe_close(pair[0]);
 
@@ -1261,10 +1278,13 @@ static const sd_bus_vtable machine_vtable[] = {
         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
-        SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader.pid), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("VSockCID", "u", NULL, offsetof(Machine, vsock_cid), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("SSHAddress", "s", NULL, offsetof(Machine, ssh_address), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("SSHPrivateKeyPath", "s", NULL, offsetof(Machine, ssh_private_key_path), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
 
         SD_BUS_METHOD("Terminate",
@@ -1282,6 +1302,11 @@ static const sd_bus_vtable machine_vtable[] = {
                                 SD_BUS_RESULT("a(iay)", addresses),
                                 bus_machine_method_get_addresses,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("GetSSHInfo",
+                                SD_BUS_NO_ARGS,
+                                SD_BUS_RESULT("s", ssh_address, "s", ssh_private_key_path),
+                                bus_machine_method_get_ssh_info,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("GetOSRelease",
                                 SD_BUS_NO_ARGS,
                                 SD_BUS_RESULT("a{ss}", fields),