[systemd-devel] [PATCH 4/7] machined: Add getter for machine's journal directory descriptor

Krzesimir Nowak krzesimir at endocode.com
Mon Jun 1 08:29:00 PDT 2015


Sometimes machine's journal is not accessible by path, so we can ask
machined to provide a descriptor to it.
---
 src/machine/machined-dbus.c                    | 112 +++++++++++++++++++++++++
 src/machine/org.freedesktop.machine1.policy.in |  10 +++
 2 files changed, 122 insertions(+)

diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 0e971a6..ea5f6f7 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -37,6 +37,7 @@
 #include "machined.h"
 #include "machine-dbus.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static int property_get_pool_path(
                 sd_bus *bus,
@@ -840,6 +841,116 @@ static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bu
         return bus_image_method_set_limit(message, i, error);
 }
 
+static int get_journal_fd_child(int socket_fd, int mntns_fd, int root_fd) {
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        r = namespace_enter(-1, mntns_fd, -1, root_fd);
+        if (r < 0)
+                return r;
+
+        fd = open("/var/log/journal", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+        if (fd < 0)
+                return -errno;
+
+        r = send_fd(socket_fd, fd);
+        return r;
+}
+
+static int get_journal_fd_parent(int socket_fd, pid_t child, sd_bus_error *error, int* journal_fd) {
+        int r;
+        siginfo_t si;
+
+        r = wait_for_terminate(child, &si);
+        if (r < 0)
+                return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
+        if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+
+        r = receive_fd(socket_fd, journal_fd);
+        if (r < 0)
+                return sd_bus_error_set_errnof(error, r, "Failed to receive journal fd: %m");
+
+        return 0;
+}
+
+static int get_journal_fd(Machine *machine, sd_bus_error *error, int *journal_fd) {
+        _cleanup_close_pair_ int pair[2] = { -1, -1 };
+        _cleanup_close_ int mntns_fd = -1, root_fd = -1, fd = -1;
+        pid_t child;
+        int r;
+
+        assert(machine);
+        assert(error);
+        assert(journal_fd);
+
+        r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair);
+        if (r < 0)
+                return sd_bus_error_set_errnof(error, errno, "Failed to create pair of sockets: %m");
+
+        r = namespace_open(machine->leader, NULL, &mntns_fd, NULL, &root_fd);
+        if (r < 0)
+                return sd_bus_error_set_errnof(error, r, "Failed to open leader's namespace(): %m");
+
+        child = fork();
+        if (child < 0)
+                return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
+
+        if (child == 0) {
+                pair[0] = safe_close(pair[0]);
+                r = get_journal_fd_child(pair[1], mntns_fd, root_fd);
+                pair[1] = safe_close(pair[1]);
+                if (r < 0)
+                        _exit(EXIT_FAILURE);
+                _exit(EXIT_SUCCESS);
+        }
+
+        pair[1] = safe_close(pair[1]);
+        r = get_journal_fd_parent(pair[0], child, error, journal_fd);
+        return r;
+}
+
+static int method_get_journal(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        Manager *m = userdata;
+        const char *name;
+        int r;
+        Machine *machine;
+        _cleanup_close_ int journal_fd = -1;
+
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return r;
+
+        r = bus_verify_polkit_async(
+                        message,
+                        CAP_SYS_ADMIN,
+                        "org.freedesktop.machine1.get-journal",
+                        false,
+                        UID_INVALID,
+                        &m->polkit_registry,
+                        error);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 1; /* Will call us back */
+
+        if (!machine_name_is_valid(name))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
+
+        machine = hashmap_get(m->machines, name);
+        if (!machine)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+
+        r = get_journal_fd(machine, error, &journal_fd);
+        if (r < 0)
+                return r;
+
+        return sd_bus_reply_method_return(message, "h", journal_fd);
+}
+
 const sd_bus_vtable manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
@@ -869,6 +980,7 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("GetJournal", "s", "h", method_get_journal, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_SIGNAL("MachineNew", "so", 0),
         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
         SD_BUS_VTABLE_END
diff --git a/src/machine/org.freedesktop.machine1.policy.in b/src/machine/org.freedesktop.machine1.policy.in
index 02714e8..d3a6ebb 100644
--- a/src/machine/org.freedesktop.machine1.policy.in
+++ b/src/machine/org.freedesktop.machine1.policy.in
@@ -46,4 +46,14 @@
                 </defaults>
         </action>
 
+        <action id="org.freedesktop.machine1.get-journal">
+                <_description>Get local container's journal descriptor</_description>
+                <_message>Authentication is required to get local container's journal descriptor.</_message>
+                <defaults>
+                        <allow_any>auth_admin</allow_any>
+                        <allow_inactive>auth_admin</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
 </policyconfig>
-- 
2.1.0



More information about the systemd-devel mailing list