From dc5437c78bbfe02d7bc0d8adad25575aeaf75c28 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Nov 2019 14:47:37 +0100 Subject: [PATCH] journald: add ability to activate by varlink socket If we have exit on idle, then operations such as "journalctl --namespace=foo --rotate" should work even if the journal daemon is currently not running. (Note that we don't do activation by varlink for the main instance of journald, I am not sure the deadlocks it might introduce are worth it) --- src/core/unit.c | 10 +++++++++- src/journal/journald-server.c | 26 +++++++++++++++++--------- units/meson.build | 1 + units/systemd-journald-varlink@.socket | 18 ++++++++++++++++++ units/systemd-journald@.service.in | 4 ++-- 5 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 units/systemd-journald-varlink@.socket diff --git a/src/core/unit.c b/src/core/unit.c index 40897023355..6b97c35ffa1 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1067,7 +1067,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { * is run first. */ if (c->log_namespace) { - _cleanup_free_ char *socket_unit = NULL; + _cleanup_free_ char *socket_unit = NULL, *varlink_socket_unit = NULL; r = unit_name_build_from_type("systemd-journald", c->log_namespace, UNIT_SOCKET, &socket_unit); if (r < 0) @@ -1076,6 +1076,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, socket_unit, true, UNIT_DEPENDENCY_FILE); if (r < 0) return r; + + r = unit_name_build_from_type("systemd-journald-varlink", c->log_namespace, UNIT_SOCKET, &varlink_socket_unit); + if (r < 0) + return r; + + r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, varlink_socket_unit, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; } else r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, true, UNIT_DEPENDENCY_FILE); if (r < 0) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 3c2f55941be..eb124aa73f4 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -2036,8 +2036,7 @@ static void vl_disconnect(VarlinkServer *server, Varlink *link, void *userdata) (void) server_start_or_stop_idle_timer(s); /* maybe we are idle now */ } -static int server_open_varlink(Server *s) { - const char *fn; +static int server_open_varlink(Server *s, const char *socket, int fd) { int r; assert(s); @@ -2065,9 +2064,10 @@ static int server_open_varlink(Server *s) { if (r < 0) return r; - fn = strjoina(s->runtime_directory, "/io.systemd.journal"); - - r = varlink_server_listen_address(s->varlink_server, fn, 0600); + if (fd < 0) + r = varlink_server_listen_address(s->varlink_server, socket, 0600); + else + r = varlink_server_listen_fd(s->varlink_server, fd); if (r < 0) return r; @@ -2186,10 +2186,10 @@ static int set_namespace(Server *s, const char *namespace) { } int server_init(Server *s, const char *namespace) { - const char *native_socket, *syslog_socket, *stdout_socket, *e; + const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e; _cleanup_fdset_free_ FDSet *fds = NULL; + int n, r, fd, varlink_fd = -1; bool no_sockets; - int n, r, fd; assert(s); @@ -2291,6 +2291,7 @@ int server_init(Server *s, const char *namespace) { native_socket = strjoina(s->runtime_directory, "/socket"); stdout_socket = strjoina(s->runtime_directory, "/stdout"); syslog_socket = strjoina(s->runtime_directory, "/dev-log"); + varlink_socket = strjoina(s->runtime_directory, "/io.systemd.journal"); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { @@ -2318,6 +2319,13 @@ int server_init(Server *s, const char *namespace) { s->syslog_fd = fd; + } else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, varlink_socket, 0) > 0) { + + if (varlink_fd >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many varlink sockets passed."); + + varlink_fd = fd; } else if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { if (s->audit_fd >= 0) @@ -2348,7 +2356,7 @@ int server_init(Server *s, const char *namespace) { fds = fdset_free(fds); } - no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0; + no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0 && varlink_fd < 0; /* always open stdout, syslog, native, and kmsg sockets */ @@ -2379,7 +2387,7 @@ int server_init(Server *s, const char *namespace) { return r; } - r = server_open_varlink(s); + r = server_open_varlink(s, varlink_socket, varlink_fd); if (r < 0) return r; diff --git a/units/meson.build b/units/meson.build index c0b69566d14..0dc85ac64a3 100644 --- a/units/meson.build +++ b/units/meson.build @@ -115,6 +115,7 @@ units = [ ['systemd-machine-id-commit.service', '', 'sysinit.target.wants/'], ['systemd-journald@.socket', ''], + ['systemd-journald-varlink@.socket', ''], ['systemd-networkd.socket', 'ENABLE_NETWORKD'], ['systemd-poweroff.service', ''], ['systemd-reboot.service', ''], diff --git a/units/systemd-journald-varlink@.socket b/units/systemd-journald-varlink@.socket new file mode 100644 index 00000000000..b6730c2fa5a --- /dev/null +++ b/units/systemd-journald-varlink@.socket @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Journal Varlink Socket for Namespace %i +Documentation=man:systemd-journald.service(8) man:journald.conf(5) +StopWhenUnneeded=yes + +[Socket] +Service=systemd-journald@%i.service +ListenStream=/run/systemd/journal.%i/io.systemd.journal +SocketMode=0600 diff --git a/units/systemd-journald@.service.in b/units/systemd-journald@.service.in index 43082fa41b8..e7ea9193280 100644 --- a/units/systemd-journald@.service.in +++ b/units/systemd-journald@.service.in @@ -10,8 +10,8 @@ [Unit] Description=Journal Service for Namespace %i Documentation=man:systemd-journald.service(8) man:journald.conf(5) -Requires=systemd-journald@%i.socket -After=systemd-journald@%i.socket +Requires=systemd-journald@%i.socket systemd-journald-varlink@%i.socket +After=systemd-journald@%i.socket systemd-journald-varlink@%i.socket [Service] CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE