mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
Merge pull request #31218 from CodethinkLabs/vmspawn/journal_forwarding
vmspawn: support journal forwarding
This commit is contained in:
commit
92d1419eb8
@ -288,7 +288,7 @@
|
||||
large individual journal files may grow at most. This influences the granularity in which disk space
|
||||
is made available through rotation, i.e. deletion of historic data. Defaults to one eighth of the
|
||||
values configured with <varname>SystemMaxUse=</varname> and <varname>RuntimeMaxUse=</varname> capped
|
||||
to 128M, so that usually seven rotated journal files are kept as history. If the journal compact
|
||||
to 128M, so that usually seven rotated journal files are kept as history. If the journal compact
|
||||
mode is enabled (enabled by default), the maximum file size is capped to 4G.</para>
|
||||
|
||||
<para>Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes (equal to
|
||||
@ -368,11 +368,13 @@
|
||||
<term><varname>ForwardToKMsg=</varname></term>
|
||||
<term><varname>ForwardToConsole=</varname></term>
|
||||
<term><varname>ForwardToWall=</varname></term>
|
||||
<term><varname>ForwardToSocket=</varname></term>
|
||||
|
||||
<listitem><para>Control whether log messages received by the journal daemon shall be forwarded to a
|
||||
traditional syslog daemon, to the kernel log buffer (kmsg), to the system console, or sent as wall
|
||||
messages to all logged-in users. These options take boolean arguments. If forwarding to syslog is
|
||||
enabled but nothing reads messages from the socket, forwarding to syslog has no effect. By default,
|
||||
traditional syslog daemon, to the kernel log buffer (kmsg), to the system console, sent as wall
|
||||
messages to all logged-in users or sent over a socket. These options take boolean arguments except
|
||||
for <literal>ForwardToSocket=</literal> which takes an an address instead. If forwarding
|
||||
to syslog is enabled but nothing reads messages from the socket, forwarding to syslog has no effect. By default,
|
||||
only forwarding to wall is enabled. These settings may be overridden at boot time with the kernel
|
||||
command line options <literal>systemd.journald.forward_to_syslog</literal>,
|
||||
<literal>systemd.journald.forward_to_kmsg</literal>,
|
||||
@ -381,6 +383,16 @@
|
||||
<literal>=</literal> and the following argument, true is assumed. Otherwise, the argument is parsed
|
||||
as a boolean.</para>
|
||||
|
||||
<para>The socket forwarding address can be specified with the credential
|
||||
<literal>journal.forward_to_socket</literal>. The following socket types are supported:</para>
|
||||
|
||||
<para><simplelist type="inline">
|
||||
<member><constant>AF_INET</constant> (e.g. <literal>192.168.0.11:4444</literal>)</member>
|
||||
<member><constant>AF_INET6</constant> (e.g. <literal>[2001:db8::ff00:42:8329]:4444</literal>)</member>
|
||||
<member><constant>AF_UNIX</constant> (e.g. <literal>/run/host/journal/socket</literal>)</member>
|
||||
<member><constant>AF_VSOCK</constant> (e.g. <literal>vsock:2:1234</literal>)</member>
|
||||
</simplelist></para>
|
||||
|
||||
<para>When forwarding to the console, the TTY to log to can be changed with
|
||||
<varname>TTYPath=</varname>, described below.</para>
|
||||
|
||||
@ -389,15 +401,27 @@
|
||||
<command>systemd</command> will automatically disable kernel's rate-limiting applied to userspace
|
||||
processes (equivalent to setting <literal>printk.devkmsg=on</literal>).</para>
|
||||
|
||||
<para>When forwarding over a socket the <ulink url="https://systemd.io/JOURNAL_EXPORT_FORMATS/#journal-export-format">
|
||||
Journal Export Format</ulink> is used when sending over the wire. Notably this includes the metadata
|
||||
field <varname>__REALTIME_TIMESTAMP</varname> so that
|
||||
<command>systemd-journal-remote</command> (see
|
||||
<citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>)
|
||||
can be used to receive the forwarded journal entries.</para>
|
||||
|
||||
<para>Note: Forwarding is performed synchronously within journald, and may significantly affect its
|
||||
performance. This is particularly relevant when using ForwardToConsole=yes in cloud environments,
|
||||
where the console is often a slow, virtual serial port. Since journald is implemented as a
|
||||
conventional single-process daemon, forwarding to a completely hung console will block journald.
|
||||
This can have a cascading effect resulting in any services synchronously logging to the blocked
|
||||
journal also becoming blocked. Unless actively debugging/developing something, it's generally
|
||||
preferable to setup a <command>journalctl --follow</command> style service redirected to the
|
||||
where the console is often a slow, virtual serial port.
|
||||
Since journald is implemented as a conventional single-process daemon, forwarding to a completely
|
||||
hung console will block journald. This can have a cascading effect resulting in any services synchronously
|
||||
logging to the blocked journal also becoming blocked. Unless actively debugging/developing something, it's
|
||||
generally preferable to setup a <command>journalctl --follow</command> style service redirected to the
|
||||
console, instead of ForwardToConsole=yes, for production use.</para>
|
||||
</listitem>
|
||||
|
||||
<para>Note: Using <varname>ForwardToSocket=</varname> over IPv4/IPv6 links can be very slow due to the synchronous nature of the sockets.
|
||||
Take care to ensure your link is a low-latency local link if possible. Typically IP networking is not available everywhere
|
||||
journald runs, e.g. in the initrd during boot. Consider using <constant>AF_VSOCK</constant>/<constant>AF_UNIX</constant> sockets for this if possible.
|
||||
</para>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -406,11 +430,12 @@
|
||||
<term><varname>MaxLevelKMsg=</varname></term>
|
||||
<term><varname>MaxLevelConsole=</varname></term>
|
||||
<term><varname>MaxLevelWall=</varname></term>
|
||||
<term><varname>MaxLevelSocket=</varname></term>
|
||||
|
||||
<listitem><para>Controls the maximum log level of messages
|
||||
that are stored in the journal, forwarded to syslog, kmsg, the
|
||||
console or wall (if that is enabled, see above). As argument,
|
||||
takes one of
|
||||
console, a socket, or wall (if that is enabled, see above).
|
||||
As argument, takes one of
|
||||
<literal>emerg</literal>,
|
||||
<literal>alert</literal>,
|
||||
<literal>crit</literal>,
|
||||
@ -422,9 +447,11 @@
|
||||
or integer values in the range of 0–7 (corresponding to the
|
||||
same levels). Messages equal or below the log level specified
|
||||
are stored/forwarded, messages above are dropped. Defaults to
|
||||
<literal>debug</literal> for <varname>MaxLevelStore=</varname>
|
||||
and <varname>MaxLevelSyslog=</varname>, to ensure that the all
|
||||
messages are stored in the journal and forwarded to syslog.
|
||||
<literal>debug</literal> for <varname>MaxLevelStore=</varname>,
|
||||
<varname>MaxLevelSyslog=</varname> and
|
||||
<varname>MaxLevelSocket=</varname>, to ensure that the all
|
||||
messages are stored in the journal, forwarded to syslog and
|
||||
the socket if one exists.
|
||||
Defaults to
|
||||
<literal>notice</literal> for <varname>MaxLevelKMsg=</varname>,
|
||||
<literal>info</literal> for <varname>MaxLevelConsole=</varname>,
|
||||
@ -435,7 +462,8 @@
|
||||
<literal>systemd.journald.max_level_syslog=</literal>,
|
||||
<literal>systemd.journald.max_level_kmsg=</literal>,
|
||||
<literal>systemd.journald.max_level_console=</literal>,
|
||||
<literal>systemd.journald.max_level_wall=</literal>.</para>
|
||||
<literal>systemd.journald.max_level_wall=</literal>,
|
||||
<literal>systemd.journald.max_level_socket=</literal>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v185"/>
|
||||
</listitem>
|
||||
|
@ -312,6 +312,25 @@
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Integration Options</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>--forward-journal=</option><replaceable>FILE|DIR</replaceable></term>
|
||||
|
||||
<listitem><para>Forward the virtual machine's journal entries to the host.</para>
|
||||
<para><citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
Is currently used to receive the guest VM's forwarded journal entries. For more information on the semantics
|
||||
of supplying a file vs a directory here see <option>-o</option>/<option>--output</option> in
|
||||
<citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Credentials</title>
|
||||
|
||||
|
@ -296,6 +296,18 @@
|
||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>journal.forward_to_socket</varname></term>
|
||||
<listitem>
|
||||
<para>Used by
|
||||
<citerefentry><refentrytitle>systemd-journald</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
to determine where to forward log messages for socket forwarding, see
|
||||
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>vmm.notify_socket</varname></term>
|
||||
<listitem>
|
||||
|
@ -516,7 +516,9 @@ static int accept_connection(
|
||||
|
||||
switch (socket_address_family(addr)) {
|
||||
case AF_INET:
|
||||
case AF_INET6: {
|
||||
case AF_INET6:
|
||||
case AF_VSOCK:
|
||||
case AF_UNIX: {
|
||||
_cleanup_free_ char *a = NULL;
|
||||
char *b;
|
||||
|
||||
|
@ -19,35 +19,37 @@ struct ConfigPerfItem;
|
||||
%struct-type
|
||||
%includes
|
||||
%%
|
||||
Journal.Storage, config_parse_storage, 0, offsetof(Server, storage)
|
||||
Journal.Compress, config_parse_compress, 0, offsetof(Server, compress)
|
||||
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
|
||||
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg)
|
||||
Journal.Audit, config_parse_tristate, 0, offsetof(Server, set_audit)
|
||||
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)
|
||||
Journal.Storage, config_parse_storage, 0, offsetof(Server, storage)
|
||||
Journal.Compress, config_parse_compress, 0, offsetof(Server, compress)
|
||||
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
|
||||
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg)
|
||||
Journal.Audit, config_parse_tristate, 0, offsetof(Server, set_audit)
|
||||
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)
|
||||
# The following is a legacy name for compatibility
|
||||
Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, ratelimit_interval)
|
||||
Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Server, ratelimit_interval)
|
||||
Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, ratelimit_burst)
|
||||
Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_use)
|
||||
Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_size)
|
||||
Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.keep_free)
|
||||
Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_storage.metrics.n_max_files)
|
||||
Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_use)
|
||||
Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_size)
|
||||
Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.keep_free)
|
||||
Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_storage.metrics.n_max_files)
|
||||
Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec)
|
||||
Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec)
|
||||
Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog)
|
||||
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg)
|
||||
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console)
|
||||
Journal.ForwardToWall, config_parse_bool, 0, offsetof(Server, forward_to_wall)
|
||||
Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path)
|
||||
Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Server, max_level_store)
|
||||
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Server, max_level_syslog)
|
||||
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Server, max_level_kmsg)
|
||||
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Server, max_level_console)
|
||||
Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Server, max_level_wall)
|
||||
Journal.SplitMode, config_parse_split_mode, 0, offsetof(Server, split_mode)
|
||||
Journal.LineMax, config_parse_line_max, 0, offsetof(Server, line_max)
|
||||
Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, ratelimit_interval)
|
||||
Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Server, ratelimit_interval)
|
||||
Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, ratelimit_burst)
|
||||
Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_use)
|
||||
Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_size)
|
||||
Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.keep_free)
|
||||
Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_storage.metrics.n_max_files)
|
||||
Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_use)
|
||||
Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_size)
|
||||
Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.keep_free)
|
||||
Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_storage.metrics.n_max_files)
|
||||
Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec)
|
||||
Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec)
|
||||
Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog)
|
||||
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg)
|
||||
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console)
|
||||
Journal.ForwardToWall, config_parse_bool, 0, offsetof(Server, forward_to_wall)
|
||||
Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(Server, forward_to_socket)
|
||||
Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path)
|
||||
Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Server, max_level_store)
|
||||
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Server, max_level_syslog)
|
||||
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Server, max_level_kmsg)
|
||||
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Server, max_level_console)
|
||||
Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Server, max_level_wall)
|
||||
Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(Server, max_level_socket)
|
||||
Journal.SplitMode, config_parse_split_mode, 0, offsetof(Server, split_mode)
|
||||
Journal.LineMax, config_parse_line_max, 0, offsetof(Server, line_max)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "audit-util.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "creds-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
@ -39,6 +40,7 @@
|
||||
#include "journald-native.h"
|
||||
#include "journald-rate-limit.h"
|
||||
#include "journald-server.h"
|
||||
#include "journald-socket.h"
|
||||
#include "journald-stream.h"
|
||||
#include "journald-syslog.h"
|
||||
#include "log.h"
|
||||
@ -52,6 +54,7 @@
|
||||
#include "rm-rf.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
@ -1152,6 +1155,8 @@ static void server_dispatch_message_real(
|
||||
else
|
||||
journal_uid = 0;
|
||||
|
||||
server_forward_socket(s, iovec, n, priority);
|
||||
|
||||
server_write_to_journal(s, journal_uid, iovec, n, priority);
|
||||
}
|
||||
|
||||
@ -1860,6 +1865,17 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
else
|
||||
s->max_level_wall = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = log_level_from_string(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
|
||||
else
|
||||
s->max_level_socket = r;
|
||||
|
||||
} else if (startswith(key, "systemd.journald"))
|
||||
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
|
||||
|
||||
@ -2465,6 +2481,29 @@ static int server_setup_memory_pressure(Server *s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void server_load_credentials(Server *s) {
|
||||
_cleanup_free_ void *data = NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* if we already have a forward address from config don't load the credential */
|
||||
if (s->forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC) {
|
||||
log_debug("Socket forward address already set not loading journal.forward_to_socket");
|
||||
return;
|
||||
}
|
||||
|
||||
r = read_credential("journal.forward_to_socket", &data, NULL);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
r = socket_address_parse(&s->forward_to_socket, data);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse credential journal.forward_to_socket, ignoring: %m");
|
||||
}
|
||||
|
||||
int server_new(Server **ret) {
|
||||
_cleanup_(server_freep) Server *s = NULL;
|
||||
|
||||
@ -2482,6 +2521,7 @@ int server_new(Server **ret) {
|
||||
.audit_fd = -EBADF,
|
||||
.hostname_fd = -EBADF,
|
||||
.notify_fd = -EBADF,
|
||||
.forward_socket_fd = -EBADF,
|
||||
|
||||
.compress.enabled = true,
|
||||
.compress.threshold_bytes = UINT64_MAX,
|
||||
@ -2498,6 +2538,7 @@ int server_new(Server **ret) {
|
||||
.ratelimit_burst = DEFAULT_RATE_LIMIT_BURST,
|
||||
|
||||
.forward_to_wall = true,
|
||||
.forward_to_socket = { .sockaddr.sa.sa_family = AF_UNSPEC },
|
||||
|
||||
.max_file_usec = DEFAULT_MAX_FILE_USEC,
|
||||
|
||||
@ -2506,6 +2547,7 @@ int server_new(Server **ret) {
|
||||
.max_level_kmsg = LOG_NOTICE,
|
||||
.max_level_console = LOG_INFO,
|
||||
.max_level_wall = LOG_EMERG,
|
||||
.max_level_socket = LOG_DEBUG,
|
||||
|
||||
.line_max = DEFAULT_LINE_MAX,
|
||||
|
||||
@ -2546,6 +2588,8 @@ int server_init(Server *s, const char *namespace) {
|
||||
|
||||
server_parse_config_file(s);
|
||||
|
||||
server_load_credentials(s);
|
||||
|
||||
if (!s->namespace) {
|
||||
/* Parse kernel command line, but only if we are not a namespace instance */
|
||||
r = proc_cmdline_parse(parse_proc_cmdline_item, s, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||
@ -2818,6 +2862,7 @@ Server* server_free(Server *s) {
|
||||
safe_close(s->audit_fd);
|
||||
safe_close(s->hostname_fd);
|
||||
safe_close(s->notify_fd);
|
||||
safe_close(s->forward_socket_fd);
|
||||
|
||||
if (s->ratelimit)
|
||||
journal_ratelimit_free(s->ratelimit);
|
||||
@ -2920,9 +2965,13 @@ int config_parse_compress(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
JournalCompressOptions* compress = data;
|
||||
JournalCompressOptions* compress = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(unit);
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
compress->enabled = true;
|
||||
compress->threshold_bytes = UINT64_MAX;
|
||||
@ -2949,3 +2998,34 @@ int config_parse_compress(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_forward_to_socket(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
SocketAddress* addr = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(unit);
|
||||
assert(filename);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue))
|
||||
*addr = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||
else {
|
||||
r = socket_address_parse(addr, rvalue);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse ForwardToSocket= value, ignoring: %s", rvalue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-event.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
typedef struct Server Server;
|
||||
|
||||
@ -78,6 +79,7 @@ struct Server {
|
||||
int audit_fd;
|
||||
int hostname_fd;
|
||||
int notify_fd;
|
||||
int forward_socket_fd;
|
||||
|
||||
sd_event *event;
|
||||
|
||||
@ -123,6 +125,7 @@ struct Server {
|
||||
bool forward_to_syslog;
|
||||
bool forward_to_console;
|
||||
bool forward_to_wall;
|
||||
SocketAddress forward_to_socket;
|
||||
|
||||
unsigned n_forward_syslog_missed;
|
||||
usec_t last_warn_forward_syslog_missed;
|
||||
@ -142,6 +145,7 @@ struct Server {
|
||||
int max_level_kmsg;
|
||||
int max_level_console;
|
||||
int max_level_wall;
|
||||
int max_level_socket;
|
||||
|
||||
Storage storage;
|
||||
SplitMode split_mode;
|
||||
@ -214,6 +218,7 @@ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TY
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_storage);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_compress);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_forward_to_socket);
|
||||
|
||||
const char *storage_to_string(Storage s) _const_;
|
||||
Storage storage_from_string(const char *s) _pure_;
|
||||
|
162
src/journal/journald-socket.c
Normal file
162
src/journal/journald-socket.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journald-socket.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "sparse-endian.h"
|
||||
|
||||
void server_open_forward_socket(Server *s) {
|
||||
_cleanup_close_ int socket_fd = -EBADF;
|
||||
const SocketAddress *addr;
|
||||
int family;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* nop if there is nothing to do */
|
||||
if (s->forward_to_socket.sockaddr.sa.sa_family == AF_UNSPEC || s->namespace || s->forward_socket_fd >= 0)
|
||||
return;
|
||||
|
||||
addr = &s->forward_to_socket;
|
||||
|
||||
family = socket_address_family(addr);
|
||||
|
||||
if (!IN_SET(family, AF_UNIX, AF_INET, AF_INET6, AF_VSOCK)) {
|
||||
log_debug("Unsupported socket type for forward socket: %d", family);
|
||||
return;
|
||||
}
|
||||
|
||||
socket_fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC, 0);
|
||||
if (socket_fd < 0) {
|
||||
log_debug_errno(errno, "Failed to create forward socket, ignoring: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
if (connect(socket_fd, &addr->sockaddr.sa, addr->size) < 0) {
|
||||
log_debug_errno(errno, "Failed to connect to remote address for forwarding, ignoring: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
s->forward_socket_fd = TAKE_FD(socket_fd);
|
||||
log_debug("Successfully connected to remote address for forwarding");
|
||||
}
|
||||
|
||||
static inline bool must_serialise(struct iovec iov) {
|
||||
/* checks an iovec of the form FIELD=VALUE to see if VALUE needs binary safe serialisation:
|
||||
* See https://systemd.io/JOURNAL_EXPORT_FORMATS/#journal-export-format for more information
|
||||
* on binary safe serialisation for the journal export format */
|
||||
|
||||
assert(iov.iov_len == 0 || iov.iov_base);
|
||||
|
||||
const uint8_t *s = iov.iov_base;
|
||||
bool before_value = true;
|
||||
|
||||
FOREACH_ARRAY(c, s, iov.iov_len) {
|
||||
if (before_value)
|
||||
before_value = *c != (uint8_t)'=';
|
||||
else if (*c < (uint8_t)' ' && *c != (uint8_t)'\t')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void server_forward_socket(
|
||||
Server *s,
|
||||
const struct iovec *iovec,
|
||||
size_t n_iovec,
|
||||
int priority) {
|
||||
_cleanup_free_ struct iovec *iov_alloc = NULL;
|
||||
struct iovec *iov = NULL;
|
||||
|
||||
_cleanup_free_ le64_t *len_alloc = NULL;
|
||||
le64_t *len = NULL;
|
||||
|
||||
assert(s);
|
||||
assert(iovec);
|
||||
assert(n_iovec > 0);
|
||||
|
||||
if (LOG_PRI(priority) > s->max_level_socket)
|
||||
return;
|
||||
|
||||
server_open_forward_socket(s);
|
||||
|
||||
/* if we failed to open a socket just return */
|
||||
if (s->forward_socket_fd < 0)
|
||||
return;
|
||||
|
||||
/* we need a newline after each iovec + 4 for each we have to serialise in a binary safe way
|
||||
* +1 for the final __REALTIME_TIMESTAMP metadata field */
|
||||
size_t n = n_iovec * 5 + 1;
|
||||
|
||||
if (n < ALLOCA_MAX / (sizeof(struct iovec) + sizeof(le64_t)) / 2) {
|
||||
iov = newa(struct iovec, n);
|
||||
len = newa(le64_t, n_iovec);
|
||||
} else {
|
||||
iov_alloc = new(struct iovec, n);
|
||||
if (!iov_alloc) {
|
||||
log_oom();
|
||||
return;
|
||||
}
|
||||
|
||||
iov = iov_alloc;
|
||||
|
||||
len_alloc = new(le64_t, n_iovec);
|
||||
if (!len_alloc) {
|
||||
log_oom();
|
||||
return;
|
||||
}
|
||||
|
||||
len = len_alloc;
|
||||
}
|
||||
|
||||
struct iovec nl = IOVEC_MAKE_STRING("\n");
|
||||
size_t iov_idx = 0, len_idx = 0;
|
||||
FOREACH_ARRAY(i, iovec, n_iovec) {
|
||||
if (must_serialise(*i)) {
|
||||
const uint8_t *c;
|
||||
c = memchr(i->iov_base, '=', i->iov_len);
|
||||
|
||||
/* this should never happen */
|
||||
if (_unlikely_(!c || c == i->iov_base)) {
|
||||
log_error("Found invalid journal field, refusing to forward.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* write the field name */
|
||||
iov[iov_idx++] = IOVEC_MAKE(i->iov_base, c - (uint8_t*) i->iov_base);
|
||||
iov[iov_idx++] = nl;
|
||||
|
||||
/* write the length of the value */
|
||||
len[len_idx] = htole64(i->iov_len - (c - (uint8_t*) i->iov_base) - 1);
|
||||
iov[iov_idx++] = IOVEC_MAKE(&len[len_idx++], sizeof(le64_t));
|
||||
|
||||
/* write the raw binary value */
|
||||
iov[iov_idx++] = IOVEC_MAKE(c + 1, i->iov_len - (c - (uint8_t*) i->iov_base) - 1);
|
||||
} else
|
||||
/* if it doesn't need special treatment just write the value out */
|
||||
iov[iov_idx++] = *i;
|
||||
|
||||
iov[iov_idx++] = nl;
|
||||
}
|
||||
|
||||
/* synthesise __REALTIME_TIMESTAMP as the last argument so systemd-journal-upload can receive these export messages */
|
||||
char buf[sizeof("__REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t) + 2];
|
||||
xsprintf(buf, "__REALTIME_TIMESTAMP="USEC_FMT"\n\n", now(CLOCK_REALTIME));
|
||||
iov[iov_idx++] = IOVEC_MAKE_STRING(buf);
|
||||
|
||||
if (writev(s->forward_socket_fd, iov, iov_idx) < 0) {
|
||||
log_debug_errno(errno, "Failed to forward log message over socket: %m");
|
||||
|
||||
/* if we failed to send once we will probably fail again so wait for a new connection to
|
||||
* establish before attempting to forward again */
|
||||
s->forward_socket_fd = safe_close(s->forward_socket_fd);
|
||||
}
|
||||
}
|
8
src/journal/journald-socket.h
Normal file
8
src/journal/journald-socket.h
Normal file
@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "journald-server.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
void server_forward_socket(Server *s, const struct iovec *iovec, size_t n, int priority);
|
||||
void server_open_forward_socket(Server *s);
|
@ -44,6 +44,7 @@
|
||||
#MaxLevelKMsg=notice
|
||||
#MaxLevelConsole=info
|
||||
#MaxLevelWall=emerg
|
||||
#MaxLevelSocket=debug
|
||||
#LineMax=48K
|
||||
#ReadKMsg=yes
|
||||
#Audit=yes
|
||||
|
@ -12,6 +12,7 @@ sources = files(
|
||||
'journald-stream.c',
|
||||
'journald-syslog.c',
|
||||
'journald-wall.c',
|
||||
'journald-socket.c',
|
||||
)
|
||||
|
||||
sources += custom_target(
|
||||
|
@ -1,8 +1,15 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "journald-server.h"
|
||||
#include "log.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \
|
||||
@ -47,4 +54,125 @@ TEST(config_compress) {
|
||||
COMPRESS_PARSE_CHECK("", true, UINT64_MAX);
|
||||
}
|
||||
|
||||
#define _FORWARD_TO_SOCKET_PARSE_CHECK_FAILS(str, addr, varname) \
|
||||
do { \
|
||||
SocketAddress varname = {}; \
|
||||
config_parse_forward_to_socket("", "", 0, "", 0, "", 0, str, \
|
||||
&varname, NULL); \
|
||||
assert_se(socket_address_verify(&varname, true) < 0); \
|
||||
} while (0)
|
||||
|
||||
#define FORWARD_TO_SOCKET_PARSE_CHECK_FAILS(str) \
|
||||
_FORWARD_TO_SOCKET_PARSE_CHECK_FAILS(str, addr, conf##__COUNTER__)
|
||||
|
||||
#define _FORWARD_TO_SOCKET_PARSE_CHECK(str, addr, varname) \
|
||||
do { \
|
||||
SocketAddress varname = {}; \
|
||||
config_parse_forward_to_socket("", "", 0, "", 0, "", 0, str, \
|
||||
&varname, NULL); \
|
||||
buf = mfree(buf); \
|
||||
buf2 = mfree(buf2); \
|
||||
socket_address_print(&varname, &buf);\
|
||||
socket_address_print(&addr, &buf2);\
|
||||
log_info("\"%s\" parsed as \"%s\", should be \"%s\"", str, buf, buf2); \
|
||||
log_info("socket_address_verify(&addr, false) = %d", socket_address_verify(&addr, false)); \
|
||||
log_info("socket_address_verify(&varname, false) = %d", socket_address_verify(&varname, false)); \
|
||||
log_info("socket_address_family(&addr) = %d", socket_address_family(&addr)); \
|
||||
log_info("socket_address_family(&varname) = %d", socket_address_family(&varname)); \
|
||||
log_info("addr.size = %u", addr.size); \
|
||||
log_info("varname.size = %u", varname.size); \
|
||||
assert_se(socket_address_equal(&varname, &addr)); \
|
||||
} while (0)
|
||||
|
||||
#define FORWARD_TO_SOCKET_PARSE_CHECK(str, addr) \
|
||||
_FORWARD_TO_SOCKET_PARSE_CHECK(str, addr, conf##__COUNTER__)
|
||||
|
||||
TEST(config_forward_to_socket) {
|
||||
SocketAddress addr;
|
||||
_cleanup_free_ char *buf = NULL, *buf2 = NULL;
|
||||
|
||||
/* Valid AF_UNIX */
|
||||
addr = (SocketAddress) {
|
||||
.sockaddr.un = (struct sockaddr_un) {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = "/run/host/journal/socket",
|
||||
},
|
||||
.size = offsetof(struct sockaddr_un, sun_path) + strlen("/run/host/journal/socket") + 1,
|
||||
};
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK("/run/host/journal/socket", addr);
|
||||
|
||||
addr.size -= 1;
|
||||
memcpy(addr.sockaddr.un.sun_path, "\0run/host/journal/socket", sizeof("\0run/host/journal/socket"));
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK("@run/host/journal/socket", addr);
|
||||
|
||||
/* Valid AF_INET */
|
||||
addr = (SocketAddress) {
|
||||
.sockaddr.in = (struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = { htobe32(0xC0A80001) },
|
||||
.sin_port = htobe16(1234),
|
||||
},
|
||||
.size = sizeof(struct sockaddr_in),
|
||||
};
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK("192.168.0.1:1234", addr);
|
||||
|
||||
/* Valid AF_INET6 */
|
||||
addr = (SocketAddress) {
|
||||
.sockaddr.in6 = (struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = (struct in6_addr) {
|
||||
.s6_addr16 = {
|
||||
htobe16(0x2001),
|
||||
htobe16(0xdb8),
|
||||
htobe16(0x4006),
|
||||
htobe16(0x812),
|
||||
0, 0, 0,
|
||||
htobe16(0x200e)
|
||||
}
|
||||
},
|
||||
.sin6_port = htobe16(8080),
|
||||
},
|
||||
.size = sizeof(struct sockaddr_in6),
|
||||
};
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK("[2001:db8:4006:812::200e]:8080", addr);
|
||||
|
||||
/* Valid AF_VSOCK */
|
||||
addr = (SocketAddress) {
|
||||
.sockaddr.vm = (struct sockaddr_vm) {
|
||||
.svm_family = AF_VSOCK,
|
||||
.svm_cid = 123456,
|
||||
.svm_port = 654321,
|
||||
},
|
||||
.size = sizeof(struct sockaddr_vm),
|
||||
};
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK("vsock:123456:654321", addr);
|
||||
|
||||
/* Invalid IPv4 */
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("256.123.45.12:1235");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("252.123.45.12:123500");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("252.123.45.12:0");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("252.123.45.12:-1");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("-1.123.45.12:22");
|
||||
|
||||
/* Invalid IPv6 */
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("[2001:db8:4006:812::200e]:80800");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("[1ffff:db8:4006:812::200e]:8080");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("[-1:db8:4006:812::200e]:8080");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("[2001:db8:4006:812::200e]:-1");
|
||||
|
||||
/* Invalid UNIX */
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("a/b/c");
|
||||
|
||||
/* Invalid VSock */
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("vsock:4294967296:1234");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("vsock:1234:4294967296");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("vsock:abcd:1234");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("vsock:1234:abcd");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("vsock:1234");
|
||||
|
||||
/* Invalid Case */
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("");
|
||||
FORWARD_TO_SOCKET_PARSE_CHECK_FAILS("ahh yes sockets, mmh");
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
@ -82,6 +82,7 @@ static RuntimeMountContext arg_runtime_mounts = {};
|
||||
static SettingsMask arg_settings_mask = 0;
|
||||
static char *arg_firmware = NULL;
|
||||
static char *arg_runtime_directory = NULL;
|
||||
static char *arg_forward_journal = NULL;
|
||||
static bool arg_runtime_directory_created = false;
|
||||
static bool arg_privileged = false;
|
||||
static char **arg_kernel_cmdline_extra = NULL;
|
||||
@ -96,6 +97,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_firmware, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_linux, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_initrds, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_runtime_mounts, runtime_mount_context_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline_extra, strv_freep);
|
||||
|
||||
static int help(void) {
|
||||
@ -145,6 +147,10 @@ static int help(void) {
|
||||
" the VM.\n"
|
||||
" --bind-ro=SOURCE[:TARGET]\n"
|
||||
" Similar, but creates a read-only mount\n"
|
||||
"\n%3$sIntegration:%4$s\n"
|
||||
" --forward-journal=FILE|DIR\n"
|
||||
" Forward the virtual machine's journal entries to\n"
|
||||
" the host.\n"
|
||||
"\n%3$sCredentials:%4$s\n"
|
||||
" --set-credential=ID:VALUE\n"
|
||||
" Pass a credential with literal value to the\n"
|
||||
@ -181,6 +187,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_BIND_RO,
|
||||
ARG_SECURE_BOOT,
|
||||
ARG_PRIVATE_USERS,
|
||||
ARG_FORWARD_JOURNAL,
|
||||
ARG_SET_CREDENTIAL,
|
||||
ARG_LOAD_CREDENTIAL,
|
||||
ARG_FIRMWARE,
|
||||
@ -209,6 +216,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "bind-ro", required_argument, NULL, ARG_BIND_RO },
|
||||
{ "secure-boot", required_argument, NULL, ARG_SECURE_BOOT },
|
||||
{ "private-users", required_argument, NULL, ARG_PRIVATE_USERS },
|
||||
{ "forward-journal", required_argument, NULL, ARG_FORWARD_JOURNAL },
|
||||
{ "set-credential", required_argument, NULL, ARG_SET_CREDENTIAL },
|
||||
{ "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL },
|
||||
{ "firmware", required_argument, NULL, ARG_FIRMWARE },
|
||||
@ -365,6 +373,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_FORWARD_JOURNAL:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_forward_journal);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_SET_CREDENTIAL: {
|
||||
r = machine_credential_set(&arg_credentials, optarg);
|
||||
if (r < 0)
|
||||
@ -664,6 +678,45 @@ static int start_tpm(sd_bus *bus, const char *scope, const char *tpm, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_systemd_journal_remote(sd_bus *bus, const char *scope, unsigned port, const char *sd_journal_remote, char **listen_address) {
|
||||
_cleanup_free_ char *scope_prefix = NULL;
|
||||
_cleanup_(socket_service_pair_done) SocketServicePair ssp = {
|
||||
.socket_type = SOCK_STREAM,
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(scope);
|
||||
assert(sd_journal_remote);
|
||||
|
||||
r = unit_name_to_prefix(scope, &scope_prefix);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to strip .scope suffix from scope: %m");
|
||||
|
||||
ssp.unit_name_prefix = strjoin(scope_prefix, "-forward-journal");
|
||||
if (!ssp.unit_name_prefix)
|
||||
return log_oom();
|
||||
|
||||
r = asprintf(&ssp.listen_address, "vsock:2:%u", port);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
ssp.exec_start = strv_new(sd_journal_remote,
|
||||
"--output", arg_forward_journal,
|
||||
"--split-mode", endswith(arg_forward_journal, ".journal") ? "none" : "host");
|
||||
if (!ssp.exec_start)
|
||||
return log_oom();
|
||||
|
||||
r = start_socket_service_pair(bus, scope, &ssp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (listen_address)
|
||||
*listen_address = TAKE_PTR(ssp.listen_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int discover_root(char **ret) {
|
||||
int r;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *image = NULL;
|
||||
@ -1105,9 +1158,9 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
return log_oom();
|
||||
|
||||
_cleanup_close_ int child_vsock_fd = -EBADF;
|
||||
unsigned child_cid = arg_vsock_cid;
|
||||
if (use_vsock) {
|
||||
int device_fd = vhost_device_fd;
|
||||
unsigned child_cid = arg_vsock_cid;
|
||||
|
||||
if (device_fd < 0) {
|
||||
child_vsock_fd = open("/dev/vhost-vsock", O_RDWR|O_CLOEXEC);
|
||||
@ -1155,24 +1208,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
if (ARCHITECTURE_SUPPORTS_SMBIOS)
|
||||
FOREACH_ARRAY(cred, arg_credentials.credentials, arg_credentials.n_credentials) {
|
||||
_cleanup_free_ char *cred_data_b64 = NULL;
|
||||
ssize_t n;
|
||||
|
||||
n = base64mem(cred->data, cred->size, &cred_data_b64);
|
||||
if (n < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extend(&cmdline, "-smbios");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extendf(&cmdline, "type=11,value=io.systemd.credential.binary:%s=%s", cred->id, cred_data_b64);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = strv_extend(&cmdline, "-drive");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@ -1411,6 +1446,43 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (arg_forward_journal) {
|
||||
_cleanup_free_ char *sd_journal_remote = NULL, *listen_address = NULL, *cred = NULL;
|
||||
r = find_executable("systemd-journal-remote", &sd_journal_remote);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to find systemd-journal-remote binary: %m");
|
||||
|
||||
r = start_systemd_journal_remote(bus, trans_scope, child_cid, sd_journal_remote, &listen_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
cred = strjoin("journal.forward_to_socket:", listen_address);
|
||||
if (!cred)
|
||||
return log_oom();
|
||||
|
||||
r = machine_credential_set(&arg_credentials, cred);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ARCHITECTURE_SUPPORTS_SMBIOS)
|
||||
FOREACH_ARRAY(cred, arg_credentials.credentials, arg_credentials.n_credentials) {
|
||||
_cleanup_free_ char *cred_data_b64 = NULL;
|
||||
ssize_t n;
|
||||
|
||||
n = base64mem(cred->data, cred->size, &cred_data_b64);
|
||||
if (n < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extend(&cmdline, "-smbios");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extendf(&cmdline, "type=11,value=io.systemd.credential.binary:%s=%s", cred->id, cred_data_b64);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (use_vsock) {
|
||||
notify_sock_fd = open_vsock();
|
||||
if (notify_sock_fd < 0)
|
||||
|
@ -865,6 +865,7 @@ MaxLevelKMsg=
|
||||
MaxLevelStore=
|
||||
MaxLevelSyslog=
|
||||
MaxLevelWall=
|
||||
MaxLevelSocket=
|
||||
MaxRetentionSec=
|
||||
MaxUse=
|
||||
MemoryDenyWriteExecute=
|
||||
|
@ -343,7 +343,7 @@ done
|
||||
|
||||
# Aux verbs & assorted checks
|
||||
systemctl is-active "*-journald.service"
|
||||
systemctl cat "*journal*"
|
||||
systemctl cat "*udevd*"
|
||||
systemctl cat "$UNIT_NAME"
|
||||
systemctl help "$UNIT_NAME"
|
||||
systemctl service-watchdogs
|
||||
|
@ -29,6 +29,7 @@ IgnoreOnIsolate=yes
|
||||
DeviceAllow=char-* rw
|
||||
ExecStart={{LIBEXECDIR}}/systemd-journald
|
||||
FileDescriptorStoreMax=4224
|
||||
ImportCredential=journal.*
|
||||
IPAddressDeny=any
|
||||
LockPersonality=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
@ -37,7 +38,7 @@ OOMScoreAdjust=-250
|
||||
ProtectClock=yes
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_VSOCK AF_INET AF_INET6
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictSUIDSGID=yes
|
||||
|
Loading…
Reference in New Issue
Block a user