mirror of
https://github.com/systemd/systemd
synced 2025-10-07 20:54:45 +02:00
Compare commits
10 Commits
33a5cc768c
...
7aefb194e7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7aefb194e7 | ||
![]() |
df5b3426f6 | ||
![]() |
c35ceb84e3 | ||
![]() |
cc43510a13 | ||
![]() |
88444243b8 | ||
![]() |
b6d4997683 | ||
![]() |
7425f76c4e | ||
![]() |
9a33cbac7d | ||
![]() |
bd068e2903 | ||
![]() |
e28d408c6b |
@ -218,6 +218,22 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
|
|||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v228"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v228"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>SIGHUP</term>
|
||||||
|
|
||||||
|
<listitem><para>Upon reception of the <constant>SIGHUP</constant> process signal
|
||||||
|
<command>systemd-journald</command> will reload its configuration values
|
||||||
|
and update the kernel log buffer and journals to reflect the new configuration.
|
||||||
|
If <varname>ReadKmsg=</varname> has changed, the kernel log buffer will be flushed
|
||||||
|
and updated as part of the reload. The active journal (e.g., persistent, volatile)
|
||||||
|
will continue to be used with the updated configuration.
|
||||||
|
However, if the storage mode has changed from persistent to volatile
|
||||||
|
and the current journal in use is the persistent journal, then the active journal will
|
||||||
|
be switched to the volatile journal.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -2561,10 +2561,16 @@ RestrictNamespaces=~cgroup net</programlisting>
|
|||||||
<listitem><para>Takes a boolean argument. If set, mount a private instance of the BPF filesystem
|
<listitem><para>Takes a boolean argument. If set, mount a private instance of the BPF filesystem
|
||||||
on <filename>/sys/fs/bpf/</filename>, effectively hiding the host bpffs which contains information
|
on <filename>/sys/fs/bpf/</filename>, effectively hiding the host bpffs which contains information
|
||||||
about loaded programs and maps. Otherwise, if <varname>ProtectKernelTunables=</varname> is set, the
|
about loaded programs and maps. Otherwise, if <varname>ProtectKernelTunables=</varname> is set, the
|
||||||
instance from the host is inherited but mounted read-only.</para>
|
instance from the host is inherited but mounted read-only. Defaults to false.</para>
|
||||||
|
|
||||||
|
<para>This can be used together with the bpffs delegate feature to choose what BPF functions are
|
||||||
|
available to the unit's processes. When mounting the BPF filesystem with the fsopen() API, four mount
|
||||||
|
options can be specified to set a list of BPF commands, maps, programs and attachment types that are
|
||||||
|
allowed to be used. Processes needs to get a file descriptor for the bpffs mountpoint and use that to
|
||||||
|
get a token which will enable for that user namespace the BPF functionalities choosen upon bpffs mount.
|
||||||
|
A more detailed explanation of the feature can be found in this
|
||||||
|
<ulink url="https://lwn.net/Articles/947173/">LWN post</ulink>.</para>
|
||||||
|
|
||||||
<para>This can be used together with the BPF delegate feature to choose what BPF functions are
|
|
||||||
available to the unit's processes. Defaults to false.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -2575,10 +2581,10 @@ RestrictNamespaces=~cgroup net</programlisting>
|
|||||||
<listitem><para>Accepts a list of BPF commands to allow or <literal>any</literal> to allow everything.
|
<listitem><para>Accepts a list of BPF commands to allow or <literal>any</literal> to allow everything.
|
||||||
Defaults to none. The accepted values are:
|
Defaults to none. The accepted values are:
|
||||||
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_cmd"/>
|
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_cmd"/>
|
||||||
Requires <varname>PrivateBPF=</varname> enabled to be effective.
|
This will set the <constant>delegate_cmds</constant> bpffs mount option.</para>
|
||||||
This will set the <constant>delegate_cmds</constant> bpffs mount option.
|
|
||||||
A more detailed explanation of the feature can be found in this
|
<para>Requires <varname>PrivateBPF=yes</varname> to be effective,
|
||||||
<ulink url="https://lwn.net/Articles/947173/">LWN post</ulink>.</para>
|
see <varname>PrivateBPF=</varname> more details.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -2589,8 +2595,10 @@ RestrictNamespaces=~cgroup net</programlisting>
|
|||||||
<listitem><para>Accepts a list of BPF maps to allow or <literal>any</literal> to allow everything.
|
<listitem><para>Accepts a list of BPF maps to allow or <literal>any</literal> to allow everything.
|
||||||
Defaults to none. The accepted values are:
|
Defaults to none. The accepted values are:
|
||||||
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_map_type"/>
|
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_map_type"/>
|
||||||
This will set the <constant>delegate_maps</constant> bpffs mount option.
|
This will set the <constant>delegate_maps</constant> bpffs mount option.</para>
|
||||||
See <varname>BPFDelegateCommands=</varname> for dependencies and more details.</para>
|
|
||||||
|
<para>Requires <varname>PrivateBPF=yes</varname> to be effective,
|
||||||
|
see <varname>PrivateBPF=</varname> more details.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -2601,8 +2609,10 @@ RestrictNamespaces=~cgroup net</programlisting>
|
|||||||
<listitem><para>Accepts a list of BPF programs to allow or <literal>any</literal> to allow everything.
|
<listitem><para>Accepts a list of BPF programs to allow or <literal>any</literal> to allow everything.
|
||||||
Defaults to none. The accepted values are:
|
Defaults to none. The accepted values are:
|
||||||
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_prog_type"/>
|
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_prog_type"/>
|
||||||
This will set the <constant>delegate_progs</constant> bpffs mount option.
|
This will set the <constant>delegate_progs</constant> bpffs mount option.</para>
|
||||||
See <varname>BPFDelegateCommands=</varname> for dependencies and more details.</para>
|
|
||||||
|
<para>Requires <varname>PrivateBPF=yes</varname> to be effective,
|
||||||
|
see <varname>PrivateBPF=</varname> more details.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -2613,8 +2623,10 @@ RestrictNamespaces=~cgroup net</programlisting>
|
|||||||
<listitem><para>Accepts a list of BPF attach points to allow or <literal>any</literal> to allow everything.
|
<listitem><para>Accepts a list of BPF attach points to allow or <literal>any</literal> to allow everything.
|
||||||
Defaults to none. The accepted values are:
|
Defaults to none. The accepted values are:
|
||||||
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_attach_type"/>
|
<xi:include href="bpf-delegate.xml" xpointer="bpf_delegate_attach_type"/>
|
||||||
This will set the <constant>delegate_attachs</constant> bpffs mount option.
|
This will set the <constant>delegate_attachs</constant> bpffs mount option.</para>
|
||||||
See <varname>BPFDelegateCommands=</varname> for dependencies and more details.</para>
|
|
||||||
|
<para>Requires <varname>PrivateBPF=yes</varname> to be effective,
|
||||||
|
see <varname>PrivateBPF=</varname> more details.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -475,6 +475,8 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>userdb.user.*</varname></term>
|
<term><varname>userdb.user.*</varname></term>
|
||||||
<term><varname>userdb.group.*</varname></term>
|
<term><varname>userdb.group.*</varname></term>
|
||||||
|
<term><varname>userdb.transient.user.*</varname></term>
|
||||||
|
<term><varname>userdb.transient.group.*</varname></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Configure JSON user and group records. Read by
|
<para>Configure JSON user and group records. Read by
|
||||||
@ -499,7 +501,10 @@
|
|||||||
<literal>userdb.user.foobar</literal> the suffix is <literal>foobar</literal>) must match the user
|
<literal>userdb.user.foobar</literal> the suffix is <literal>foobar</literal>) must match the user
|
||||||
or group name field from the user or group record.</para>
|
or group name field from the user or group record.</para>
|
||||||
|
|
||||||
<para>Note that the records are created in <filename>/etc/userdb/</filename>
|
<para>Note that the records created for <varname>userdb.user.*</varname> and
|
||||||
|
<varname>userdb.group.*</varname> credentials are created in <filename>/etc/userdb/</filename> and
|
||||||
|
the records created for <varname>userdb.transient.user.*</varname> and
|
||||||
|
<varname>userdb.transient.group.*</varname> are created in <filename>/run/userdb/</filename>
|
||||||
(<filename>/etc/passwd</filename> and <filename>/etc/group</filename> are not modified).</para>
|
(<filename>/etc/passwd</filename> and <filename>/etc/group</filename> are not modified).</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
target-version = "py39"
|
target-version = "py37"
|
||||||
line-length = 109
|
line-length = 109
|
||||||
lint.select = ["E", "F", "I", "UP"]
|
lint.select = ["E", "F", "I", "UP"]
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
quote-style = "single"
|
quote-style = "single"
|
||||||
|
|
||||||
|
[per-file-target-version]
|
||||||
|
"src/ukify/*.py" = "py39"
|
||||||
|
"test/**/integration-test-wrapper.py" = "py39"
|
||||||
|
"test/test-udev.py" = "py39"
|
||||||
|
@ -21,6 +21,15 @@ _kernel_install() {
|
|||||||
local comps
|
local comps
|
||||||
local MACHINE_ID
|
local MACHINE_ID
|
||||||
local cur=${COMP_WORDS[COMP_CWORD]}
|
local cur=${COMP_WORDS[COMP_CWORD]}
|
||||||
|
local prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
|
local entry_types="type1 type2 all"
|
||||||
|
|
||||||
|
case "$prev" in
|
||||||
|
--entry-type)
|
||||||
|
COMPREPLY=( $(compgen -W "$entry_types" -- "$cur") )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
case $COMP_CWORD in
|
case $COMP_CWORD in
|
||||||
1)
|
1)
|
||||||
@ -42,6 +51,11 @@ _kernel_install() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [[ "${COMP_WORDS[1]}" == "remove" ]] && [[ $cur == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W '--entry-type' -- "$cur") )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,12 @@ static inline bool ERRNO_IS_NEG_PRIVILEGE(intmax_t r) {
|
|||||||
}
|
}
|
||||||
_DEFINE_ABS_WRAPPER(PRIVILEGE);
|
_DEFINE_ABS_WRAPPER(PRIVILEGE);
|
||||||
|
|
||||||
|
/* Three different errors for writing on a filesystem */
|
||||||
|
static inline bool ERRNO_IS_NEG_FS_WRITE_REFUSED(intmax_t r) {
|
||||||
|
return r == -EROFS || ERRNO_IS_NEG_PRIVILEGE(r);
|
||||||
|
}
|
||||||
|
_DEFINE_ABS_WRAPPER(FS_WRITE_REFUSED);
|
||||||
|
|
||||||
/* Three different errors for "not enough disk space" */
|
/* Three different errors for "not enough disk space" */
|
||||||
static inline bool ERRNO_IS_NEG_DISK_SPACE(intmax_t r) {
|
static inline bool ERRNO_IS_NEG_DISK_SPACE(intmax_t r) {
|
||||||
return IN_SET(r,
|
return IN_SET(r,
|
||||||
|
@ -193,10 +193,10 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int binfmt_mounted_warn(void) {
|
static int binfmt_mounted_and_writable_warn(void) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = binfmt_mounted();
|
r = binfmt_mounted_and_writable();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to check if /proc/sys/fs/binfmt_misc is mounted: %m");
|
return log_error_errno(r, "Failed to check if /proc/sys/fs/binfmt_misc is mounted: %m");
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -222,7 +222,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
return disable_binfmt();
|
return disable_binfmt();
|
||||||
|
|
||||||
if (argc > optind) {
|
if (argc > optind) {
|
||||||
r = binfmt_mounted_warn();
|
r = binfmt_mounted_and_writable_warn();
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (arg_cat_flags != CAT_CONFIG_OFF)
|
if (arg_cat_flags != CAT_CONFIG_OFF)
|
||||||
return cat_config(files);
|
return cat_config(files);
|
||||||
|
|
||||||
r = binfmt_mounted_warn();
|
r = binfmt_mounted_and_writable_warn();
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
/* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access
|
/* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access
|
||||||
* problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask
|
* problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask
|
||||||
* out specific attributes from us. */
|
* out specific attributes from us. */
|
||||||
#define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(ABS(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING)
|
#define LOG_LEVEL_CGROUP_WRITE(r) ((ABS(r) == ENOENT || ERRNO_IS_FS_WRITE_REFUSED(r)) ? LOG_DEBUG : LOG_WARNING)
|
||||||
|
|
||||||
static void unit_remove_from_cgroup_empty_queue(Unit *u);
|
static void unit_remove_from_cgroup_empty_queue(Unit *u);
|
||||||
|
|
||||||
|
@ -1271,8 +1271,8 @@ static void bump_file_max_and_nr_open(void) {
|
|||||||
* different, but the operation would fail silently.) */
|
* different, but the operation would fail silently.) */
|
||||||
r = sysctl_write("fs/file-max", LONG_MAX_STR);
|
r = sysctl_write("fs/file-max", LONG_MAX_STR);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING,
|
log_full_errno(ERRNO_IS_NEG_FS_WRITE_REFUSED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
r, "Failed to bump fs.file-max, ignoring: %m");
|
"Failed to bump fs.file-max, ignoring: %m");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUMP_PROC_SYS_FS_NR_OPEN
|
#if BUMP_PROC_SYS_FS_NR_OPEN
|
||||||
@ -1293,7 +1293,8 @@ static void bump_file_max_and_nr_open(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to bump fs.nr_open, ignoring: %m");
|
log_full_errno(ERRNO_IS_NEG_FS_WRITE_REFUSED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to bump fs.nr_open, ignoring: %m");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1534,7 +1535,7 @@ static int bump_unix_max_dgram_qlen(void) {
|
|||||||
|
|
||||||
r = sysctl_write("net/unix/max_dgram_qlen", STRINGIFY(DEFAULT_UNIX_MAX_DGRAM_QLEN));
|
r = sysctl_write("net/unix/max_dgram_qlen", STRINGIFY(DEFAULT_UNIX_MAX_DGRAM_QLEN));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
return log_full_errno(ERRNO_IS_NEG_FS_WRITE_REFUSED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
|
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1269,7 +1269,7 @@ static void mount_enter_mounting(Mount *m) {
|
|||||||
* when the path is on NFS. See issue #24120. All such errors will be logged in the debug level. */
|
* when the path is on NFS. See issue #24120. All such errors will be logged in the debug level. */
|
||||||
if (r < 0 && r != -EEXIST)
|
if (r < 0 && r != -EEXIST)
|
||||||
log_unit_full_errno(UNIT(m),
|
log_unit_full_errno(UNIT(m),
|
||||||
(r == -EROFS || ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_WARNING,
|
ERRNO_IS_NEG_FS_WRITE_REFUSED(r) ? LOG_DEBUG : LOG_WARNING,
|
||||||
r, "Failed to make bind mount source '%s', ignoring: %m", p->what);
|
r, "Failed to make bind mount source '%s', ignoring: %m", p->what);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
fuzz_setup_logging();
|
fuzz_setup_logging();
|
||||||
|
|
||||||
assert_se(manager_new(&m) >= 0);
|
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
|
||||||
dummy_manager_init(m, data, size);
|
dummy_manager_init(m, data, size);
|
||||||
process_audit_string(m, 0, m->buffer, size);
|
process_audit_string(m, 0, m->buffer, size);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
fuzz_setup_logging();
|
fuzz_setup_logging();
|
||||||
|
|
||||||
assert_se(manager_new(&m) >= 0);
|
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
|
||||||
dummy_manager_init(m, data, size);
|
dummy_manager_init(m, data, size);
|
||||||
dev_kmsg_record(m, m->buffer, size);
|
dev_kmsg_record(m, m->buffer, size);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
fuzz_setup_logging();
|
fuzz_setup_logging();
|
||||||
|
|
||||||
assert_se(manager_new(&m) >= 0);
|
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
|
||||||
dummy_manager_init(m, NULL, 0);
|
dummy_manager_init(m, NULL, 0);
|
||||||
|
|
||||||
sealed_fd = memfd_new_and_seal(NULL, data, size);
|
sealed_fd = memfd_new_and_seal(NULL, data, size);
|
||||||
|
@ -23,7 +23,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
fuzz_setup_logging();
|
fuzz_setup_logging();
|
||||||
|
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0);
|
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0);
|
||||||
assert_se(manager_new(&m) >= 0);
|
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
|
||||||
dummy_manager_init(m, NULL, 0);
|
dummy_manager_init(m, NULL, 0);
|
||||||
|
|
||||||
assert_se(stdout_stream_install(m, stream_fds[0], &stream) >= 0);
|
assert_se(stdout_stream_install(m, stream_fds[0], &stream) >= 0);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
void dummy_manager_init(Manager *m, const uint8_t *buffer, size_t size) {
|
void dummy_manager_init(Manager *m, const uint8_t *buffer, size_t size) {
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
m->storage = STORAGE_NONE;
|
m->config.storage = STORAGE_NONE;
|
||||||
assert_se(sd_event_default(&m->event) >= 0);
|
assert_se(sd_event_default(&m->event) >= 0);
|
||||||
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
@ -33,7 +33,7 @@ void fuzz_journald_processing_function(
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert_se(manager_new(&m) >= 0);
|
assert_se(manager_new(&m, /* namespace= */ NULL) >= 0);
|
||||||
dummy_manager_init(m, data, size);
|
dummy_manager_init(m, data, size);
|
||||||
(*f)(m, m->buffer, size, ucred, tv, label, label_len);
|
(*f)(m, m->buffer, size, ucred, tv, label, label_len);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ void manager_forward_console(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_console)
|
if (LOG_PRI(priority) > m->config.max_level_console)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* First: timestamp */
|
/* First: timestamp */
|
||||||
|
@ -19,7 +19,7 @@ struct ConfigPerfItem;
|
|||||||
%struct-type
|
%struct-type
|
||||||
%includes
|
%includes
|
||||||
%%
|
%%
|
||||||
Journal.Storage, config_parse_storage, 0, offsetof(Manager, storage)
|
Journal.Storage, config_parse_storage, 0, offsetof(Manager, config_by_conf.storage)
|
||||||
Journal.Compress, config_parse_compress, 0, offsetof(Manager, compress)
|
Journal.Compress, config_parse_compress, 0, offsetof(Manager, compress)
|
||||||
Journal.Seal, config_parse_bool, 0, offsetof(Manager, seal)
|
Journal.Seal, config_parse_bool, 0, offsetof(Manager, seal)
|
||||||
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Manager, read_kmsg)
|
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Manager, read_kmsg)
|
||||||
@ -39,17 +39,17 @@ Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Manager,
|
|||||||
Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Manager, runtime_storage.metrics.n_max_files)
|
Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Manager, runtime_storage.metrics.n_max_files)
|
||||||
Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Manager, max_retention_usec)
|
Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Manager, max_retention_usec)
|
||||||
Journal.MaxFileSec, config_parse_sec, 0, offsetof(Manager, max_file_usec)
|
Journal.MaxFileSec, config_parse_sec, 0, offsetof(Manager, max_file_usec)
|
||||||
Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Manager, forward_to_syslog)
|
Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_syslog)
|
||||||
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Manager, forward_to_kmsg)
|
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_kmsg)
|
||||||
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Manager, forward_to_console)
|
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_console)
|
||||||
Journal.ForwardToWall, config_parse_bool, 0, offsetof(Manager, forward_to_wall)
|
Journal.ForwardToWall, config_parse_bool, 0, offsetof(Manager, config_by_conf.forward_to_wall)
|
||||||
Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(Manager, forward_to_socket)
|
Journal.ForwardToSocket, config_parse_forward_to_socket, 0, offsetof(Manager, config_by_conf.forward_to_socket)
|
||||||
Journal.TTYPath, config_parse_path, 0, offsetof(Manager, tty_path)
|
Journal.TTYPath, config_parse_path, 0, offsetof(Manager, tty_path)
|
||||||
Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Manager, max_level_store)
|
Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_store)
|
||||||
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Manager, max_level_syslog)
|
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_syslog)
|
||||||
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Manager, max_level_kmsg)
|
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_kmsg)
|
||||||
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Manager, max_level_console)
|
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_console)
|
||||||
Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Manager, max_level_wall)
|
Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_wall)
|
||||||
Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(Manager, max_level_socket)
|
Journal.MaxLevelSocket, config_parse_log_level, 0, offsetof(Manager, config_by_conf.max_level_socket)
|
||||||
Journal.SplitMode, config_parse_split_mode, 0, offsetof(Manager, split_mode)
|
Journal.SplitMode, config_parse_split_mode, 0, offsetof(Manager, split_mode)
|
||||||
Journal.LineMax, config_parse_line_max, 0, offsetof(Manager, line_max)
|
Journal.LineMax, config_parse_line_max, 0, offsetof(Manager, line_max)
|
||||||
|
@ -46,7 +46,7 @@ void manager_forward_kmsg(
|
|||||||
assert(priority <= 999);
|
assert(priority <= 999);
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
if (_unlikely_(LOG_PRI(priority) > m->max_level_kmsg))
|
if (_unlikely_(LOG_PRI(priority) > m->config.max_level_kmsg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_unlikely_(m->dev_kmsg_fd < 0))
|
if (_unlikely_(m->dev_kmsg_fd < 0))
|
||||||
@ -128,7 +128,7 @@ void dev_kmsg_record(Manager *m, char *p, size_t l) {
|
|||||||
if (r < 0 || priority < 0 || priority > 999)
|
if (r < 0 || priority < 0 || priority > 999)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m->forward_to_kmsg && LOG_FAC(priority) != LOG_KERN)
|
if (m->config.forward_to_kmsg && LOG_FAC(priority) != LOG_KERN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* seqnum */
|
/* seqnum */
|
||||||
@ -389,6 +389,10 @@ static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void
|
|||||||
return manager_read_dev_kmsg(m);
|
return manager_read_dev_kmsg(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mode_t manager_kmsg_mode(bool read_kmsg) {
|
||||||
|
return O_CLOEXEC|O_NONBLOCK|O_NOCTTY|(read_kmsg ? O_RDWR : O_WRONLY);
|
||||||
|
}
|
||||||
|
|
||||||
int manager_open_dev_kmsg(Manager *m) {
|
int manager_open_dev_kmsg(Manager *m) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -396,7 +400,7 @@ int manager_open_dev_kmsg(Manager *m) {
|
|||||||
assert(m->dev_kmsg_fd < 0);
|
assert(m->dev_kmsg_fd < 0);
|
||||||
assert(!m->dev_kmsg_event_source);
|
assert(!m->dev_kmsg_event_source);
|
||||||
|
|
||||||
mode_t mode = O_CLOEXEC|O_NONBLOCK|O_NOCTTY|(m->read_kmsg ? O_RDWR : O_WRONLY);
|
mode_t mode = manager_kmsg_mode(m->read_kmsg);
|
||||||
|
|
||||||
_cleanup_close_ int fd = open("/dev/kmsg", mode);
|
_cleanup_close_ int fd = open("/dev/kmsg", mode);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -441,3 +445,33 @@ int manager_open_kernel_seqnum(Manager *m) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int manager_reload_dev_kmsg(Manager *m) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
/* Check if the fd has not yet been initialized. If so, open /dev/kmsg. */
|
||||||
|
if (m->dev_kmsg_fd < 0)
|
||||||
|
return manager_open_dev_kmsg(m);
|
||||||
|
|
||||||
|
mode_t mode = manager_kmsg_mode(m->read_kmsg);
|
||||||
|
int flags = fcntl(m->dev_kmsg_fd, F_GETFL);
|
||||||
|
if (flags < 0)
|
||||||
|
/* Proceed with reload in case the flags have changed. */
|
||||||
|
log_warning_errno(errno, "Failed to get flags for /dev/kmsg, ignoring: %m");
|
||||||
|
else if ((flags & O_ACCMODE_STRICT) == mode)
|
||||||
|
/* Mode is the same. No-op. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Flush kmsg. */
|
||||||
|
r = manager_flush_dev_kmsg(m);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to flush /dev/kmsg on reload, ignoring: %m");
|
||||||
|
|
||||||
|
/* Set kmsg values to default. */
|
||||||
|
m->dev_kmsg_event_source = sd_event_source_disable_unref(m->dev_kmsg_event_source);
|
||||||
|
m->dev_kmsg_fd = safe_close(m->dev_kmsg_fd);
|
||||||
|
|
||||||
|
return manager_open_dev_kmsg(m);
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
int manager_open_dev_kmsg(Manager *m);
|
int manager_open_dev_kmsg(Manager *m);
|
||||||
int manager_flush_dev_kmsg(Manager *m);
|
int manager_flush_dev_kmsg(Manager *m);
|
||||||
|
int manager_reload_dev_kmsg(Manager *m);
|
||||||
|
|
||||||
void manager_forward_kmsg(Manager *m, int priority, const char *identifier, const char *message, const struct ucred *ucred);
|
void manager_forward_kmsg(Manager *m, int priority, const char *identifier, const char *message, const struct ucred *ucred);
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@
|
|||||||
|
|
||||||
static int manager_schedule_sync(Manager *m, int priority);
|
static int manager_schedule_sync(Manager *m, int priority);
|
||||||
static int manager_refresh_idle_timer(Manager *m);
|
static int manager_refresh_idle_timer(Manager *m);
|
||||||
|
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
|
||||||
|
|
||||||
static int manager_determine_path_usage(
|
static int manager_determine_path_usage(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
@ -269,6 +270,12 @@ static void manager_add_acls(JournalFile *f, uid_t uid) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int manager_get_file_flags(Manager *m, bool seal) {
|
||||||
|
return (m->compress.enabled ? JOURNAL_COMPRESS : 0) |
|
||||||
|
(seal ? JOURNAL_SEAL : 0) |
|
||||||
|
JOURNAL_STRICT_ORDER;
|
||||||
|
}
|
||||||
|
|
||||||
static int manager_open_journal(
|
static int manager_open_journal(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
bool reliably,
|
bool reliably,
|
||||||
@ -286,10 +293,7 @@ static int manager_open_journal(
|
|||||||
assert(fname);
|
assert(fname);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
file_flags =
|
file_flags = manager_get_file_flags(m, seal);
|
||||||
(m->compress.enabled ? JOURNAL_COMPRESS : 0) |
|
|
||||||
(seal ? JOURNAL_SEAL : 0) |
|
|
||||||
JOURNAL_STRICT_ORDER;
|
|
||||||
|
|
||||||
set_clear(m->deferred_closes);
|
set_clear(m->deferred_closes);
|
||||||
|
|
||||||
@ -363,7 +367,7 @@ static int manager_system_journal_open(
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (!m->system_journal &&
|
if (!m->system_journal &&
|
||||||
IN_SET(m->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
|
IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
|
||||||
(flush_requested || manager_flushed_flag_is_set(m)) &&
|
(flush_requested || manager_flushed_flag_is_set(m)) &&
|
||||||
!relinquish_requested) {
|
!relinquish_requested) {
|
||||||
|
|
||||||
@ -371,7 +375,7 @@ static int manager_system_journal_open(
|
|||||||
*
|
*
|
||||||
* If in persistent mode: create /var/log/journal and the machine path */
|
* If in persistent mode: create /var/log/journal and the machine path */
|
||||||
|
|
||||||
if (m->storage == STORAGE_PERSISTENT)
|
if (m->config.storage == STORAGE_PERSISTENT)
|
||||||
(void) mkdir_parents(m->system_storage.path, 0755);
|
(void) mkdir_parents(m->system_storage.path, 0755);
|
||||||
|
|
||||||
(void) mkdir(m->system_storage.path, 0755);
|
(void) mkdir(m->system_storage.path, 0755);
|
||||||
@ -408,7 +412,7 @@ static int manager_system_journal_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m->runtime_journal &&
|
if (!m->runtime_journal &&
|
||||||
(m->storage != STORAGE_NONE)) {
|
(m->config.storage != STORAGE_NONE)) {
|
||||||
|
|
||||||
fn = strjoina(m->runtime_storage.path, "/system.journal");
|
fn = strjoina(m->runtime_storage.path, "/system.journal");
|
||||||
|
|
||||||
@ -532,7 +536,7 @@ static JournalFile* manager_find_journal(Manager *m, uid_t uid) {
|
|||||||
* persistent journal of any sort.
|
* persistent journal of any sort.
|
||||||
*
|
*
|
||||||
* Fixes https://github.com/systemd/systemd/issues/20390 */
|
* Fixes https://github.com/systemd/systemd/issues/20390 */
|
||||||
if (!IN_SET(m->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
|
if (!IN_SET(m->config.storage, STORAGE_AUTO, STORAGE_PERSISTENT))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!uid_for_system_journal(uid)) {
|
if (!uid_for_system_journal(uid)) {
|
||||||
@ -1279,12 +1283,12 @@ void manager_dispatch_message(
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_store)
|
if (LOG_PRI(priority) > m->config.max_level_store)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Stop early in case the information will not be stored
|
/* Stop early in case the information will not be stored
|
||||||
* in a journal. */
|
* in a journal. */
|
||||||
if (m->storage == STORAGE_NONE)
|
if (m->config.storage == STORAGE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c && c->unit) {
|
if (c && c->unit) {
|
||||||
@ -1320,7 +1324,7 @@ int manager_flush_to_var(Manager *m, bool require_flag_file) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (!IN_SET(m->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
|
if (!IN_SET(m->config.storage, STORAGE_AUTO, STORAGE_PERSISTENT))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (m->namespace) /* Flushing concept does not exist for namespace instances */
|
if (m->namespace) /* Flushing concept does not exist for namespace instances */
|
||||||
@ -1468,7 +1472,7 @@ finish:
|
|||||||
int manager_relinquish_var(Manager *m) {
|
int manager_relinquish_var(Manager *m) {
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (m->storage == STORAGE_NONE)
|
if (m->config.storage == STORAGE_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (m->namespace) /* Concept does not exist for namespaced instances */
|
if (m->namespace) /* Concept does not exist for namespaced instances */
|
||||||
@ -1859,6 +1863,10 @@ static int manager_setup_signals(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = sd_event_add_signal(m->event, NULL, SIGHUP|SD_EVENT_SIGNAL_PROCMASK, dispatch_reload_signal, m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1872,7 +1880,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
|
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->forward_to_syslog = r;
|
m->config_by_cmdline.forward_to_syslog = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) {
|
||||||
|
|
||||||
@ -1880,7 +1888,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
|
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->forward_to_kmsg = r;
|
m->config_by_cmdline.forward_to_kmsg = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) {
|
||||||
|
|
||||||
@ -1888,7 +1896,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
|
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->forward_to_console = r;
|
m->config_by_cmdline.forward_to_console = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) {
|
||||||
|
|
||||||
@ -1896,7 +1904,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
|
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->forward_to_wall = r;
|
m->config_by_cmdline.forward_to_wall = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) {
|
||||||
|
|
||||||
@ -1907,7 +1915,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_console = r;
|
m->config_by_cmdline.max_level_console = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) {
|
||||||
|
|
||||||
@ -1918,7 +1926,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_store = r;
|
m->config_by_cmdline.max_level_store = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) {
|
||||||
|
|
||||||
@ -1929,7 +1937,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_syslog = r;
|
m->config_by_cmdline.max_level_syslog = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) {
|
||||||
|
|
||||||
@ -1940,7 +1948,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_kmsg = r;
|
m->config_by_cmdline.max_level_kmsg = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) {
|
||||||
|
|
||||||
@ -1951,7 +1959,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_wall = r;
|
m->config_by_cmdline.max_level_wall = r;
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
|
} else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_socket")) {
|
||||||
|
|
||||||
@ -1962,7 +1970,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
|
log_warning("Failed to parse max level socket value \"%s\". Ignoring.", value);
|
||||||
else
|
else
|
||||||
m->max_level_socket = r;
|
m->config_by_cmdline.max_level_socket = r;
|
||||||
|
|
||||||
} else if (startswith(key, "systemd.journald"))
|
} else if (startswith(key, "systemd.journald"))
|
||||||
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
|
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
|
||||||
@ -2394,7 +2402,7 @@ static void manager_load_credentials(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
|
log_debug_errno(r, "Failed to read credential journal.forward_to_socket, ignoring: %m");
|
||||||
else {
|
else {
|
||||||
r = socket_address_parse(&m->forward_to_socket, data);
|
r = socket_address_parse(&m->config_by_cred.forward_to_socket, data);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to parse socket address '%s' from credential journal.forward_to_socket, ignoring: %m", (char *) data);
|
log_debug_errno(r, "Failed to parse socket address '%s' from credential journal.forward_to_socket, ignoring: %m", (char *) data);
|
||||||
}
|
}
|
||||||
@ -2409,12 +2417,225 @@ static void manager_load_credentials(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
|
log_debug_errno(r, "Failed to parse storage '%s' from credential journal.storage, ignoring: %m", (char *) data);
|
||||||
else
|
else
|
||||||
m->storage = r;
|
m->config_by_cred.storage = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_new(Manager **ret) {
|
static void manager_set_defaults(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
m->compress.enabled = true;
|
||||||
|
m->compress.threshold_bytes = UINT64_MAX;
|
||||||
|
|
||||||
|
m->seal = true;
|
||||||
|
|
||||||
|
/* By default, only read from /dev/kmsg if are the main namespace */
|
||||||
|
m->read_kmsg = !m->namespace;
|
||||||
|
|
||||||
|
m->set_audit = true;
|
||||||
|
|
||||||
|
m->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
|
||||||
|
|
||||||
|
m->ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
|
||||||
|
m->ratelimit_burst = DEFAULT_RATE_LIMIT_BURST;
|
||||||
|
|
||||||
|
m->system_storage.name = "System Journal";
|
||||||
|
journal_reset_metrics(&m->system_storage.metrics);
|
||||||
|
|
||||||
|
m->runtime_storage.name = "Runtime Journal";
|
||||||
|
journal_reset_metrics(&m->runtime_storage.metrics);
|
||||||
|
|
||||||
|
m->max_file_usec = DEFAULT_MAX_FILE_USEC;
|
||||||
|
|
||||||
|
m->config.forward_to_wall = true;
|
||||||
|
|
||||||
|
m->config.max_level_store = LOG_DEBUG;
|
||||||
|
m->config.max_level_syslog = LOG_DEBUG;
|
||||||
|
m->config.max_level_kmsg = LOG_NOTICE;
|
||||||
|
m->config.max_level_console = LOG_INFO;
|
||||||
|
m->config.max_level_wall = LOG_EMERG;
|
||||||
|
m->config.max_level_socket = LOG_DEBUG;
|
||||||
|
|
||||||
|
m->line_max = DEFAULT_LINE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_reset_configs(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
m->config_by_cmdline = JOURNAL_CONFIG_INIT;
|
||||||
|
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||||
|
m->config_by_cred = JOURNAL_CONFIG_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_adjust_configs(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */
|
||||||
|
log_debug(
|
||||||
|
"Setting both rate limit interval and burst from %s/%u to 0/0",
|
||||||
|
FORMAT_TIMESPAN(m->ratelimit_interval, USEC_PER_SEC),
|
||||||
|
m->ratelimit_burst);
|
||||||
|
m->ratelimit_interval = m->ratelimit_burst = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_merge_forward_to_socket(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
/* Conf file takes precendence over credentials. */
|
||||||
|
if (m->config_by_conf.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||||
|
m->config.forward_to_socket = m->config_by_conf.forward_to_socket;
|
||||||
|
else if (m->config_by_cred.forward_to_socket.sockaddr.sa.sa_family != AF_UNSPEC)
|
||||||
|
m->config.forward_to_socket = m->config_by_cred.forward_to_socket;
|
||||||
|
else
|
||||||
|
m->config.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC };
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_merge_storage(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
/* Conf file takes precendence over credentials. */
|
||||||
|
if (m->config_by_conf.storage != _STORAGE_INVALID)
|
||||||
|
m->config.storage = m->config_by_conf.storage;
|
||||||
|
else if (m->config_by_cred.storage != _STORAGE_INVALID)
|
||||||
|
m->config.storage = m->config_by_cred.storage;
|
||||||
|
else
|
||||||
|
m->config.storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MERGE_BOOL(name, default_value) \
|
||||||
|
(m->config.name = (m->config_by_cmdline.name ? m->config_by_cmdline.name : \
|
||||||
|
m->config_by_conf.name ? m->config_by_conf.name : \
|
||||||
|
m->config_by_cred.name ? m->config_by_cred.name : \
|
||||||
|
default_value))
|
||||||
|
|
||||||
|
#define MERGE_NON_NEGATIVE(name, default_value) \
|
||||||
|
(m->config.name = (m->config_by_cmdline.name >= 0 ? m->config_by_cmdline.name : \
|
||||||
|
m->config_by_conf.name >= 0 ? m->config_by_conf.name : \
|
||||||
|
m->config_by_cred.name >= 0 ? m->config_by_cred.name : \
|
||||||
|
default_value))
|
||||||
|
|
||||||
|
static void manager_merge_configs(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From highest to lowest priority: cmdline, conf, cred
|
||||||
|
*/
|
||||||
|
manager_merge_storage(m);
|
||||||
|
manager_merge_forward_to_socket(m);
|
||||||
|
|
||||||
|
MERGE_BOOL(forward_to_syslog, false);
|
||||||
|
MERGE_BOOL(forward_to_kmsg, false);
|
||||||
|
MERGE_BOOL(forward_to_console, false);
|
||||||
|
MERGE_BOOL(forward_to_wall, true);
|
||||||
|
|
||||||
|
MERGE_NON_NEGATIVE(max_level_store, LOG_DEBUG);
|
||||||
|
MERGE_NON_NEGATIVE(max_level_syslog, LOG_DEBUG);
|
||||||
|
MERGE_NON_NEGATIVE(max_level_kmsg, LOG_NOTICE);
|
||||||
|
MERGE_NON_NEGATIVE(max_level_console, LOG_INFO);
|
||||||
|
MERGE_NON_NEGATIVE(max_level_wall, LOG_EMERG);
|
||||||
|
MERGE_NON_NEGATIVE(max_level_socket, LOG_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_load_config(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
manager_set_defaults(m);
|
||||||
|
manager_reset_configs(m);
|
||||||
|
|
||||||
|
manager_load_credentials(m);
|
||||||
|
manager_parse_config_file(m);
|
||||||
|
|
||||||
|
if (!m->namespace) {
|
||||||
|
/* Parse kernel command line, but only if we are not a namespace instance */
|
||||||
|
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
manager_merge_configs(m);
|
||||||
|
|
||||||
|
manager_adjust_configs(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_reload_config(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
manager_set_defaults(m);
|
||||||
|
|
||||||
|
m->config_by_conf = JOURNAL_CONFIG_INIT;
|
||||||
|
manager_parse_config_file(m);
|
||||||
|
|
||||||
|
manager_merge_configs(m);
|
||||||
|
manager_adjust_configs(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int manager_reload_journals(Manager *m) {
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (m->system_journal && IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO)) {
|
||||||
|
/* Current journal can continue being used. Update config values as needed. */
|
||||||
|
r = journal_file_reload(
|
||||||
|
m->system_journal,
|
||||||
|
manager_get_file_flags(m, m->seal),
|
||||||
|
m->compress.threshold_bytes,
|
||||||
|
&m->system_storage.metrics);
|
||||||
|
if (r < 0)
|
||||||
|
return log_warning_errno(r, "Failed to reload system journal on reload, ignoring: %m");
|
||||||
|
} else if (m->system_journal && m->config.storage == STORAGE_VOLATILE) {
|
||||||
|
/* Journal needs to be switched from system to runtime. */
|
||||||
|
r = manager_relinquish_var(m);
|
||||||
|
if (r < 0)
|
||||||
|
return log_warning_errno(r, "Failed to relinquish to runtime journal on reload, ignoring: %m");
|
||||||
|
} else if (m->runtime_journal && IN_SET(m->config.storage, STORAGE_PERSISTENT, STORAGE_AUTO, STORAGE_VOLATILE)) {
|
||||||
|
/* Current journal can continue being used. Update config values as needed.*/
|
||||||
|
r = journal_file_reload(
|
||||||
|
m->runtime_journal,
|
||||||
|
manager_get_file_flags(m, /* seal */ false),
|
||||||
|
m->compress.threshold_bytes,
|
||||||
|
&m->runtime_storage.metrics);
|
||||||
|
if (r < 0)
|
||||||
|
return log_warning_errno(r, "Failed to reload runtime journal on reload, ignoring: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If journal-related configuration, such as SystemMaxUse, SystemMaxFileSize, RuntimeMaxUse, RuntimeMaxFileSize,
|
||||||
|
* were to change, then we can vacuum for the change to take effect. For example, if pre-reload SystemMaxUse=2M,
|
||||||
|
* current usage=1.5M, and the post-reload SystemMaxUse=1M, the vacuum can shrink it to 1M.
|
||||||
|
*/
|
||||||
|
manager_vacuum(m, /* verbose */ false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||||
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
(void) notify_reloading();
|
||||||
|
|
||||||
|
manager_reload_config(m);
|
||||||
|
|
||||||
|
r = manager_reload_dev_kmsg(m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = manager_reload_journals(m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
log_info("Config file reloaded.");
|
||||||
|
(void) sd_notify(/* unset_environment */ false, NOTIFY_READY_MESSAGE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int manager_new(Manager **ret, const char *namespace) {
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
@ -2432,37 +2653,10 @@ int manager_new(Manager **ret) {
|
|||||||
.notify_fd = -EBADF,
|
.notify_fd = -EBADF,
|
||||||
.forward_socket_fd = -EBADF,
|
.forward_socket_fd = -EBADF,
|
||||||
|
|
||||||
.compress.enabled = true,
|
|
||||||
.compress.threshold_bytes = UINT64_MAX,
|
|
||||||
.seal = true,
|
|
||||||
|
|
||||||
.set_audit = true,
|
|
||||||
|
|
||||||
.watchdog_usec = USEC_INFINITY,
|
.watchdog_usec = USEC_INFINITY,
|
||||||
|
|
||||||
.sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC,
|
|
||||||
.sync_scheduled = false,
|
.sync_scheduled = false,
|
||||||
|
|
||||||
.ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL,
|
|
||||||
.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,
|
|
||||||
|
|
||||||
.max_level_store = LOG_DEBUG,
|
|
||||||
.max_level_syslog = LOG_DEBUG,
|
|
||||||
.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,
|
|
||||||
|
|
||||||
.runtime_storage.name = "Runtime Journal",
|
|
||||||
.system_storage.name = "System Journal",
|
|
||||||
|
|
||||||
.kmsg_own_ratelimit = {
|
.kmsg_own_ratelimit = {
|
||||||
.interval = DEFAULT_KMSG_OWN_INTERVAL,
|
.interval = DEFAULT_KMSG_OWN_INTERVAL,
|
||||||
.burst = DEFAULT_KMSG_OWN_BURST,
|
.burst = DEFAULT_KMSG_OWN_BURST,
|
||||||
@ -2472,11 +2666,17 @@ int manager_new(Manager **ret) {
|
|||||||
.sigrtmin18_info.memory_pressure_userdata = m,
|
.sigrtmin18_info.memory_pressure_userdata = m,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
r = manager_set_namespace(m, namespace);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
manager_load_config(m);
|
||||||
|
|
||||||
*ret = TAKE_PTR(m);
|
*ret = TAKE_PTR(m);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_init(Manager *m, const char *namespace) {
|
int manager_init(Manager *m) {
|
||||||
const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e;
|
const char *native_socket, *syslog_socket, *stdout_socket, *varlink_socket, *e;
|
||||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||||
int n, r, varlink_fd = -EBADF;
|
int n, r, varlink_fd = -EBADF;
|
||||||
@ -2484,33 +2684,6 @@ int manager_init(Manager *m, const char *namespace) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = manager_set_namespace(m, namespace);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* By default, only read from /dev/kmsg if are the main namespace */
|
|
||||||
m->read_kmsg = !m->namespace;
|
|
||||||
m->storage = m->namespace ? STORAGE_PERSISTENT : STORAGE_AUTO;
|
|
||||||
|
|
||||||
journal_reset_metrics(&m->system_storage.metrics);
|
|
||||||
journal_reset_metrics(&m->runtime_storage.metrics);
|
|
||||||
|
|
||||||
manager_load_credentials(m);
|
|
||||||
manager_parse_config_file(m);
|
|
||||||
|
|
||||||
if (!m->namespace) {
|
|
||||||
/* Parse kernel command line, but only if we are not a namespace instance */
|
|
||||||
r = proc_cmdline_parse(parse_proc_cmdline_item, m, PROC_CMDLINE_STRIP_RD_PREFIX);
|
|
||||||
if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!m->ratelimit_interval != !!m->ratelimit_burst) { /* One set to 0 and the other not? */
|
|
||||||
log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0",
|
|
||||||
m->ratelimit_interval, m->ratelimit_burst);
|
|
||||||
m->ratelimit_interval = m->ratelimit_burst = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = getenv("RUNTIME_DIRECTORY");
|
e = getenv("RUNTIME_DIRECTORY");
|
||||||
if (e)
|
if (e)
|
||||||
m->runtime_directory = strdup(e);
|
m->runtime_directory = strdup(e);
|
||||||
|
@ -55,6 +55,23 @@ typedef struct SeqnumData {
|
|||||||
uint64_t seqnum;
|
uint64_t seqnum;
|
||||||
} SeqnumData;
|
} SeqnumData;
|
||||||
|
|
||||||
|
typedef struct JournalConfig {
|
||||||
|
SocketAddress forward_to_socket;
|
||||||
|
Storage storage;
|
||||||
|
|
||||||
|
bool forward_to_kmsg;
|
||||||
|
bool forward_to_syslog;
|
||||||
|
bool forward_to_console;
|
||||||
|
bool forward_to_wall;
|
||||||
|
|
||||||
|
int max_level_store;
|
||||||
|
int max_level_syslog;
|
||||||
|
int max_level_kmsg;
|
||||||
|
int max_level_console;
|
||||||
|
int max_level_wall;
|
||||||
|
int max_level_socket;
|
||||||
|
} JournalConfig;
|
||||||
|
|
||||||
typedef struct Manager {
|
typedef struct Manager {
|
||||||
char *namespace;
|
char *namespace;
|
||||||
|
|
||||||
@ -111,12 +128,6 @@ typedef struct Manager {
|
|||||||
bool sent_notify_ready;
|
bool sent_notify_ready;
|
||||||
bool sync_scheduled;
|
bool sync_scheduled;
|
||||||
|
|
||||||
bool forward_to_kmsg;
|
|
||||||
bool forward_to_syslog;
|
|
||||||
bool forward_to_console;
|
|
||||||
bool forward_to_wall;
|
|
||||||
SocketAddress forward_to_socket;
|
|
||||||
|
|
||||||
unsigned n_forward_syslog_missed;
|
unsigned n_forward_syslog_missed;
|
||||||
usec_t last_warn_forward_syslog_missed;
|
usec_t last_warn_forward_syslog_missed;
|
||||||
|
|
||||||
@ -130,14 +141,6 @@ typedef struct Manager {
|
|||||||
|
|
||||||
char *tty_path;
|
char *tty_path;
|
||||||
|
|
||||||
int max_level_store;
|
|
||||||
int max_level_syslog;
|
|
||||||
int max_level_kmsg;
|
|
||||||
int max_level_console;
|
|
||||||
int max_level_wall;
|
|
||||||
int max_level_socket;
|
|
||||||
|
|
||||||
Storage storage;
|
|
||||||
SplitMode split_mode;
|
SplitMode split_mode;
|
||||||
|
|
||||||
MMapCache *mmap;
|
MMapCache *mmap;
|
||||||
@ -183,6 +186,21 @@ typedef struct Manager {
|
|||||||
|
|
||||||
/* Pending synchronization requests with non-zero rqlen counter */
|
/* Pending synchronization requests with non-zero rqlen counter */
|
||||||
LIST_HEAD(SyncReq, sync_req_pending_rqlen);
|
LIST_HEAD(SyncReq, sync_req_pending_rqlen);
|
||||||
|
|
||||||
|
/* These structs are used to preserve configurations set by credentials and command line.
|
||||||
|
config - main configuration used by journald manager,
|
||||||
|
config_by_cred - configuration set by credentials,
|
||||||
|
config_by_conf - configuration set by configuration file,
|
||||||
|
config_by_cmdline - configuration set by command line.
|
||||||
|
The priority order of the sub-configurations is:
|
||||||
|
config_by_cmdline > config_by_conf > config_by_cred
|
||||||
|
where A > B means that if the two have the same setting,
|
||||||
|
A's value overrides B's value for that setting.
|
||||||
|
*/
|
||||||
|
JournalConfig config;
|
||||||
|
JournalConfig config_by_cred;
|
||||||
|
JournalConfig config_by_conf;
|
||||||
|
JournalConfig config_by_cmdline;
|
||||||
} Manager;
|
} Manager;
|
||||||
|
|
||||||
#define MANAGER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID="))
|
#define MANAGER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID="))
|
||||||
@ -209,6 +227,17 @@ void manager_dispatch_message(Manager *m, struct iovec *iovec, size_t n, size_t
|
|||||||
void manager_driver_message_internal(Manager *m, pid_t object_pid, const char *format, ...) _sentinel_;
|
void manager_driver_message_internal(Manager *m, pid_t object_pid, const char *format, ...) _sentinel_;
|
||||||
#define manager_driver_message(...) manager_driver_message_internal(__VA_ARGS__, NULL)
|
#define manager_driver_message(...) manager_driver_message_internal(__VA_ARGS__, NULL)
|
||||||
|
|
||||||
|
#define JOURNAL_CONFIG_INIT \
|
||||||
|
(JournalConfig) { \
|
||||||
|
.forward_to_socket = (SocketAddress) { .sockaddr.sa.sa_family = AF_UNSPEC }, \
|
||||||
|
.storage = _STORAGE_INVALID, \
|
||||||
|
.max_level_store = -1, \
|
||||||
|
.max_level_syslog = -1, \
|
||||||
|
.max_level_kmsg = -1, \
|
||||||
|
.max_level_console = -1, \
|
||||||
|
.max_level_wall = -1, \
|
||||||
|
}
|
||||||
|
|
||||||
/* gperf lookup function */
|
/* gperf lookup function */
|
||||||
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||||
|
|
||||||
@ -225,8 +254,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
|
|||||||
const char* split_mode_to_string(SplitMode s) _const_;
|
const char* split_mode_to_string(SplitMode s) _const_;
|
||||||
SplitMode split_mode_from_string(const char *s) _pure_;
|
SplitMode split_mode_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
int manager_new(Manager **ret);
|
int manager_new(Manager **ret, const char *namespace);
|
||||||
int manager_init(Manager *m, const char *namespace);
|
int manager_init(Manager *m);
|
||||||
Manager* manager_free(Manager *m);
|
Manager* manager_free(Manager *m);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||||
void manager_full_sync(Manager *m, bool wait);
|
void manager_full_sync(Manager *m, bool wait);
|
||||||
|
@ -267,16 +267,16 @@ static int manager_process_entry(
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (m->forward_to_syslog)
|
if (m->config.forward_to_syslog)
|
||||||
manager_forward_syslog(m, syslog_fixup_facility(priority), identifier, message, ucred, tv);
|
manager_forward_syslog(m, syslog_fixup_facility(priority), identifier, message, ucred, tv);
|
||||||
|
|
||||||
if (m->forward_to_kmsg)
|
if (m->config.forward_to_kmsg)
|
||||||
manager_forward_kmsg(m, priority, identifier, message, ucred);
|
manager_forward_kmsg(m, priority, identifier, message, ucred);
|
||||||
|
|
||||||
if (m->forward_to_console)
|
if (m->config.forward_to_console)
|
||||||
manager_forward_console(m, priority, identifier, message, ucred);
|
manager_forward_console(m, priority, identifier, message, ucred);
|
||||||
|
|
||||||
if (m->forward_to_wall)
|
if (m->config.forward_to_wall)
|
||||||
manager_forward_wall(m, priority, identifier, message, ucred);
|
manager_forward_wall(m, priority, identifier, message, ucred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ static int manager_open_forward_socket(Manager *m) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
/* Noop if there is nothing to do. */
|
/* Noop if there is nothing to do. */
|
||||||
if (m->forward_to_socket.sockaddr.sa.sa_family == AF_UNSPEC || m->namespace)
|
if (m->config.forward_to_socket.sockaddr.sa.sa_family == AF_UNSPEC || m->namespace)
|
||||||
return 0;
|
return 0;
|
||||||
/* All ready, nothing to do. */
|
/* All ready, nothing to do. */
|
||||||
if (m->forward_socket_fd >= 0)
|
if (m->forward_socket_fd >= 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
addr = &m->forward_to_socket;
|
addr = &m->config.forward_to_socket;
|
||||||
|
|
||||||
family = socket_address_family(addr);
|
family = socket_address_family(addr);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ int manager_forward_socket(
|
|||||||
assert(n_iovec > 0);
|
assert(n_iovec > 0);
|
||||||
assert(ts);
|
assert(ts);
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_socket)
|
if (LOG_PRI(priority) > m->config.max_level_socket)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = manager_open_forward_socket(m);
|
r = manager_open_forward_socket(m);
|
||||||
|
@ -251,16 +251,16 @@ static int stdout_stream_log(
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (s->forward_to_syslog || s->manager->forward_to_syslog)
|
if (s->forward_to_syslog || s->manager->config.forward_to_syslog)
|
||||||
manager_forward_syslog(s->manager, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
|
manager_forward_syslog(s->manager, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
|
||||||
|
|
||||||
if (s->forward_to_kmsg || s->manager->forward_to_kmsg)
|
if (s->forward_to_kmsg || s->manager->config.forward_to_kmsg)
|
||||||
manager_forward_kmsg(s->manager, priority, s->identifier, p, &s->ucred);
|
manager_forward_kmsg(s->manager, priority, s->identifier, p, &s->ucred);
|
||||||
|
|
||||||
if (s->forward_to_console || s->manager->forward_to_console)
|
if (s->forward_to_console || s->manager->config.forward_to_console)
|
||||||
manager_forward_console(s->manager, priority, s->identifier, p, &s->ucred);
|
manager_forward_console(s->manager, priority, s->identifier, p, &s->ucred);
|
||||||
|
|
||||||
if (s->manager->forward_to_wall)
|
if (s->manager->config.forward_to_wall)
|
||||||
manager_forward_wall(s->manager, priority, s->identifier, p, &s->ucred);
|
manager_forward_wall(s->manager, priority, s->identifier, p, &s->ucred);
|
||||||
|
|
||||||
m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context);
|
m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context);
|
||||||
|
@ -127,7 +127,7 @@ static void forward_syslog_raw(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(buffer);
|
assert(buffer);
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_syslog)
|
if (LOG_PRI(priority) > m->config.max_level_syslog)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iovec = IOVEC_MAKE((char *) buffer, buffer_len);
|
iovec = IOVEC_MAKE((char *) buffer, buffer_len);
|
||||||
@ -154,7 +154,7 @@ void manager_forward_syslog(
|
|||||||
assert(priority <= 999);
|
assert(priority <= 999);
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_syslog)
|
if (LOG_PRI(priority) > m->config.max_level_syslog)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* First: priority field */
|
/* First: priority field */
|
||||||
@ -403,16 +403,16 @@ void manager_process_syslog_message(
|
|||||||
|
|
||||||
syslog_parse_identifier(&msg, &identifier, &pid);
|
syslog_parse_identifier(&msg, &identifier, &pid);
|
||||||
|
|
||||||
if (m->forward_to_syslog)
|
if (m->config.forward_to_syslog)
|
||||||
forward_syslog_raw(m, priority, buf, raw_len, ucred, tv);
|
forward_syslog_raw(m, priority, buf, raw_len, ucred, tv);
|
||||||
|
|
||||||
if (m->forward_to_kmsg)
|
if (m->config.forward_to_kmsg)
|
||||||
manager_forward_kmsg(m, priority, identifier, msg, ucred);
|
manager_forward_kmsg(m, priority, identifier, msg, ucred);
|
||||||
|
|
||||||
if (m->forward_to_console)
|
if (m->config.forward_to_console)
|
||||||
manager_forward_console(m, priority, identifier, msg, ucred);
|
manager_forward_console(m, priority, identifier, msg, ucred);
|
||||||
|
|
||||||
if (m->forward_to_wall)
|
if (m->config.forward_to_wall)
|
||||||
manager_forward_wall(m, priority, identifier, msg, ucred);
|
manager_forward_wall(m, priority, identifier, msg, ucred);
|
||||||
|
|
||||||
mm = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context);
|
mm = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context);
|
||||||
|
@ -23,7 +23,7 @@ void manager_forward_wall(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
if (LOG_PRI(priority) > m->max_level_wall)
|
if (LOG_PRI(priority) > m->config.max_level_wall)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ucred) {
|
if (ucred) {
|
||||||
|
@ -52,11 +52,11 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
sigbus_install();
|
sigbus_install();
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m, namespace);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = manager_init(m, namespace);
|
r = manager_init(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -33,6 +33,11 @@ case "$COMMAND" in
|
|||||||
exec depmod -a "$KERNEL_VERSION"
|
exec depmod -a "$KERNEL_VERSION"
|
||||||
;;
|
;;
|
||||||
remove)
|
remove)
|
||||||
|
[ "$KERNEL_INSTALL_BOOT_ENTRY_TYPE" = "type2" ] || \
|
||||||
|
[ "$KERNEL_INSTALL_BOOT_ENTRY_TYPE" = "type1" ] && \
|
||||||
|
[ -d "/lib/modules/$KERNEL_VERSION/kernel" ] && \
|
||||||
|
echo "Multiple entry types exist, not removing modules.dep or associated files." && \
|
||||||
|
exit 0
|
||||||
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
|
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
|
||||||
echo "Removing /lib/modules/${KERNEL_VERSION}/modules.dep and associated files"
|
echo "Removing /lib/modules/${KERNEL_VERSION}/modules.dep and associated files"
|
||||||
exec rm -f \
|
exec rm -f \
|
||||||
|
@ -49,6 +49,11 @@ LOADER_ENTRY="$BOOT_ROOT/loader/entries/$ENTRY_TOKEN-$KERNEL_VERSION.conf"
|
|||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
remove)
|
remove)
|
||||||
|
if [ -f "/lib/modules/$KERNEL_VERSION/vmlinuz" ] && [ "$KERNEL_INSTALL_BOOT_ENTRY_TYPE" = "type2" ]; then
|
||||||
|
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
|
||||||
|
echo "BOOT_ENTRY_TYPE=type2, not removing loader entries."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
|
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
|
||||||
echo "Removing ${LOADER_ENTRY%.conf}*.conf"
|
echo "Removing ${LOADER_ENTRY%.conf}*.conf"
|
||||||
exec rm -f \
|
exec rm -f \
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "argv-util.h"
|
#include "argv-util.h"
|
||||||
#include "boot-entry.h"
|
#include "boot-entry.h"
|
||||||
|
#include "bootspec.h"
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
#include "chase.h"
|
#include "chase.h"
|
||||||
#include "conf-files.h"
|
#include "conf-files.h"
|
||||||
@ -88,6 +89,7 @@ typedef struct Context {
|
|||||||
Action action;
|
Action action;
|
||||||
sd_id128_t machine_id;
|
sd_id128_t machine_id;
|
||||||
bool machine_id_is_random;
|
bool machine_id_is_random;
|
||||||
|
BootEntryType entry_type;
|
||||||
KernelImageType kernel_image_type;
|
KernelImageType kernel_image_type;
|
||||||
Layout layout;
|
Layout layout;
|
||||||
char *layout_other;
|
char *layout_other;
|
||||||
@ -427,6 +429,20 @@ static int context_set_initrds(Context *c, char* const* strv) {
|
|||||||
return context_set_path_strv(c, strv, "command line", "initrds", &c->initrds);
|
return context_set_path_strv(c, strv, "command line", "initrds", &c->initrds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int context_set_entry_type(Context *c, const char *s) {
|
||||||
|
assert(c);
|
||||||
|
BootEntryType e;
|
||||||
|
if (isempty(s) || streq(s, "all")) {
|
||||||
|
c->entry_type = _BOOT_ENTRY_TYPE_INVALID;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
e = boot_entry_type_from_string(s);
|
||||||
|
if (e < 0)
|
||||||
|
return log_error_errno(e, "Invalid entry type: %s", s);
|
||||||
|
c->entry_type = e;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int context_load_environment(Context *c) {
|
static int context_load_environment(Context *c) {
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
@ -983,6 +999,7 @@ static int context_build_environment(Context *c) {
|
|||||||
"KERNEL_INSTALL_LAYOUT", context_get_layout(c),
|
"KERNEL_INSTALL_LAYOUT", context_get_layout(c),
|
||||||
"KERNEL_INSTALL_INITRD_GENERATOR", strempty(c->initrd_generator),
|
"KERNEL_INSTALL_INITRD_GENERATOR", strempty(c->initrd_generator),
|
||||||
"KERNEL_INSTALL_UKI_GENERATOR", strempty(c->uki_generator),
|
"KERNEL_INSTALL_UKI_GENERATOR", strempty(c->uki_generator),
|
||||||
|
"KERNEL_INSTALL_BOOT_ENTRY_TYPE", boot_entry_type_to_string(c->entry_type),
|
||||||
"KERNEL_INSTALL_STAGING_AREA", c->staging_area);
|
"KERNEL_INSTALL_STAGING_AREA", c->staging_area);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to build environment variables for plugins: %m");
|
return log_error_errno(r, "Failed to build environment variables for plugins: %m");
|
||||||
@ -1487,6 +1504,9 @@ static int help(void) {
|
|||||||
" --root=PATH Operate on an alternate filesystem root\n"
|
" --root=PATH Operate on an alternate filesystem root\n"
|
||||||
" --image=PATH Operate on disk image as filesystem root\n"
|
" --image=PATH Operate on disk image as filesystem root\n"
|
||||||
" --image-policy=POLICY Specify disk image dissection policy\n"
|
" --image-policy=POLICY Specify disk image dissection policy\n"
|
||||||
|
" --entry-type=type1|type2|all\n"
|
||||||
|
" Operate only on the specified bootloader\n"
|
||||||
|
" entry type\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This program may also be invoked as 'installkernel':\n"
|
"This program may also be invoked as 'installkernel':\n"
|
||||||
" installkernel [OPTIONS...] VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\n"
|
" installkernel [OPTIONS...] VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\n"
|
||||||
@ -1516,6 +1536,7 @@ static int parse_argv(int argc, char *argv[], Context *c) {
|
|||||||
ARG_ROOT,
|
ARG_ROOT,
|
||||||
ARG_IMAGE,
|
ARG_IMAGE,
|
||||||
ARG_IMAGE_POLICY,
|
ARG_IMAGE_POLICY,
|
||||||
|
ARG_BOOT_ENTRY_TYPE,
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
@ -1531,6 +1552,7 @@ static int parse_argv(int argc, char *argv[], Context *c) {
|
|||||||
{ "image", required_argument, NULL, ARG_IMAGE },
|
{ "image", required_argument, NULL, ARG_IMAGE },
|
||||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||||
|
{ "entry-type", required_argument, NULL, ARG_BOOT_ENTRY_TYPE },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int t, r;
|
int t, r;
|
||||||
@ -1614,6 +1636,12 @@ static int parse_argv(int argc, char *argv[], Context *c) {
|
|||||||
return r;
|
return r;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_BOOT_ENTRY_TYPE:
|
||||||
|
r = context_set_entry_type(c, optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -1641,6 +1669,7 @@ static int run(int argc, char* argv[]) {
|
|||||||
.action = _ACTION_INVALID,
|
.action = _ACTION_INVALID,
|
||||||
.kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN,
|
.kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN,
|
||||||
.layout = _LAYOUT_INVALID,
|
.layout = _LAYOUT_INVALID,
|
||||||
|
.entry_type = _BOOT_ENTRY_TYPE_INVALID,
|
||||||
.entry_token_type = BOOT_ENTRY_TOKEN_AUTO,
|
.entry_token_type = BOOT_ENTRY_TOKEN_AUTO,
|
||||||
};
|
};
|
||||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||||
|
@ -97,6 +97,13 @@ test ! -e "$entry"
|
|||||||
test ! -e "$BOOT_ROOT/the-token/1.1.1/linux"
|
test ! -e "$BOOT_ROOT/the-token/1.1.1/linux"
|
||||||
test ! -e "$BOOT_ROOT/the-token/1.1.1/initrd"
|
test ! -e "$BOOT_ROOT/the-token/1.1.1/initrd"
|
||||||
|
|
||||||
|
# Test --entry-type options
|
||||||
|
"$kernel_install" -v add 1.1.1 "$D/sources/linux" "$D/sources/initrd"
|
||||||
|
"$kernel_install" -v remove 1.1.1 --entry-type=type1
|
||||||
|
test ! -e "$entry"
|
||||||
|
test ! -e "$BOOT_ROOT/the-token/1.1.1/linux"
|
||||||
|
test ! -e "$BOOT_ROOT/the-token/1.1.1/initrd"
|
||||||
|
|
||||||
# Invoke kernel-install as installkernel
|
# Invoke kernel-install as installkernel
|
||||||
ln -s --relative -v "$kernel_install" "$D/sources/installkernel"
|
ln -s --relative -v "$kernel_install" "$D/sources/installkernel"
|
||||||
"$D/sources/installkernel" -v 1.1.2 "$D/sources/linux" System.map /somedirignored
|
"$D/sources/installkernel" -v 1.1.2 "$D/sources/linux" System.map /somedirignored
|
||||||
|
@ -4082,6 +4082,54 @@ static void journal_default_metrics(JournalMetrics *m, int fd, bool compact) {
|
|||||||
m->n_max_files);
|
m->n_max_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t get_compress_threshold_bytes(uint64_t compress_threshold_bytes) {
|
||||||
|
return compress_threshold_bytes == UINT64_MAX ?
|
||||||
|
DEFAULT_COMPRESS_THRESHOLD :
|
||||||
|
MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_metrics(JournalFile *f, JournalMetrics *metrics, JournalFile *template) {
|
||||||
|
assert(f);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!journal_file_writable(f))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (metrics) {
|
||||||
|
journal_default_metrics(metrics, f->fd, JOURNAL_HEADER_COMPACT(f->header));
|
||||||
|
f->metrics = *metrics;
|
||||||
|
} else if (template)
|
||||||
|
f->metrics = template->metrics;
|
||||||
|
|
||||||
|
r = journal_file_refresh_header(f);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to refresh journal file header. Error to be handled by caller.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int journal_file_reload(
|
||||||
|
JournalFile *f,
|
||||||
|
JournalFileFlags file_flags,
|
||||||
|
uint64_t compress_threshold_bytes,
|
||||||
|
JournalMetrics *metrics) {
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
assert((file_flags & ~_JOURNAL_FILE_FLAGS_ALL) == 0);
|
||||||
|
assert(metrics);
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
f->compress_threshold_bytes = get_compress_threshold_bytes(compress_threshold_bytes);
|
||||||
|
|
||||||
|
r = set_metrics(f, metrics, /* template */ NULL);
|
||||||
|
if (r < 0)
|
||||||
|
/* Journal file header failed to be rotated. The changes may not have taken effect in this case. */
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int journal_file_open(
|
int journal_file_open(
|
||||||
int fd,
|
int fd,
|
||||||
const char *fname,
|
const char *fname,
|
||||||
@ -4121,9 +4169,7 @@ int journal_file_open(
|
|||||||
.fd = fd,
|
.fd = fd,
|
||||||
.mode = mode,
|
.mode = mode,
|
||||||
.open_flags = open_flags,
|
.open_flags = open_flags,
|
||||||
.compress_threshold_bytes = compress_threshold_bytes == UINT64_MAX ?
|
.compress_threshold_bytes = get_compress_threshold_bytes(compress_threshold_bytes),
|
||||||
DEFAULT_COMPRESS_THRESHOLD :
|
|
||||||
MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes),
|
|
||||||
.strict_order = FLAGS_SET(file_flags, JOURNAL_STRICT_ORDER),
|
.strict_order = FLAGS_SET(file_flags, JOURNAL_STRICT_ORDER),
|
||||||
.newest_boot_id_prioq_idx = PRIOQ_IDX_NULL,
|
.newest_boot_id_prioq_idx = PRIOQ_IDX_NULL,
|
||||||
.last_direction = _DIRECTION_INVALID,
|
.last_direction = _DIRECTION_INVALID,
|
||||||
@ -4232,17 +4278,9 @@ int journal_file_open(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (journal_file_writable(f)) {
|
r = set_metrics(f, metrics, template);
|
||||||
if (metrics) {
|
if (r < 0)
|
||||||
journal_default_metrics(metrics, f->fd, JOURNAL_HEADER_COMPACT(f->header));
|
goto fail;
|
||||||
f->metrics = *metrics;
|
|
||||||
} else if (template)
|
|
||||||
f->metrics = template->metrics;
|
|
||||||
|
|
||||||
r = journal_file_refresh_header(f);
|
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAVE_GCRYPT
|
#if HAVE_GCRYPT
|
||||||
r = journal_file_hmac_setup(f);
|
r = journal_file_hmac_setup(f);
|
||||||
|
@ -149,6 +149,12 @@ int journal_file_open(
|
|||||||
JournalFile *template,
|
JournalFile *template,
|
||||||
JournalFile **ret);
|
JournalFile **ret);
|
||||||
|
|
||||||
|
int journal_file_reload(
|
||||||
|
JournalFile *f,
|
||||||
|
JournalFileFlags file_flags,
|
||||||
|
uint64_t compress_threshold_bytes,
|
||||||
|
JournalMetrics *metrics);
|
||||||
|
|
||||||
int journal_file_set_offline_thread_join(JournalFile *f);
|
int journal_file_set_offline_thread_join(JournalFile *f);
|
||||||
JournalFile* journal_file_close(JournalFile *j);
|
JournalFile* journal_file_close(JournalFile *j);
|
||||||
int journal_file_fstat(JournalFile *f);
|
int journal_file_fstat(JournalFile *f);
|
||||||
|
@ -1907,14 +1907,14 @@ static int setup_timezone(const char *dest) {
|
|||||||
log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
|
log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
|
||||||
else {
|
else {
|
||||||
if (unlink(where) < 0 && errno != ENOENT) {
|
if (unlink(where) < 0 && errno != ENOENT) {
|
||||||
log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
|
log_full_errno(ERRNO_IS_FS_WRITE_REFUSED(errno) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
|
||||||
errno, "Failed to remove existing timezone info %s in container, ignoring: %m", where);
|
errno, "Failed to remove existing timezone info %s in container, ignoring: %m", where);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
what = strjoina("../usr/share/zoneinfo/", z);
|
what = strjoina("../usr/share/zoneinfo/", z);
|
||||||
if (symlink(what, where) < 0) {
|
if (symlink(what, where) < 0) {
|
||||||
log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING,
|
log_full_errno(ERRNO_IS_FS_WRITE_REFUSED(errno) ? LOG_DEBUG : LOG_WARNING,
|
||||||
errno, "Failed to correct timezone of container, ignoring: %m");
|
errno, "Failed to correct timezone of container, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1949,7 +1949,7 @@ static int setup_timezone(const char *dest) {
|
|||||||
/* If mounting failed, try to copy */
|
/* If mounting failed, try to copy */
|
||||||
r = copy_file_atomic("/etc/localtime", where, 0644, COPY_REFLINK|COPY_REPLACE);
|
r = copy_file_atomic("/etc/localtime", where, 0644, COPY_REFLINK|COPY_REPLACE);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_full_errno(IN_SET(r, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
|
log_full_errno(ERRNO_IS_NEG_FS_WRITE_REFUSED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
"Failed to copy /etc/localtime to %s, ignoring: %m", where);
|
"Failed to copy /etc/localtime to %s, ignoring: %m", where);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2085,7 +2085,7 @@ static int setup_resolv_conf(const char *dest) {
|
|||||||
* If the disk image is read-only, there's also no point in complaining.
|
* If the disk image is read-only, there's also no point in complaining.
|
||||||
*/
|
*/
|
||||||
log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC, RESOLV_CONF_COPY_UPLINK, RESOLV_CONF_COPY_STUB) &&
|
log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC, RESOLV_CONF_COPY_UPLINK, RESOLV_CONF_COPY_STUB) &&
|
||||||
IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
|
(r == -ELOOP || ERRNO_IS_NEG_FS_WRITE_REFUSED(r)) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
"Failed to copy /etc/resolv.conf to %s, ignoring: %m", where);
|
"Failed to copy /etc/resolv.conf to %s, ignoring: %m", where);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "missing_magic.h"
|
#include "missing_magic.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
|
|
||||||
int binfmt_mounted(void) {
|
int binfmt_mounted_and_writable(void) {
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -25,7 +25,13 @@ int binfmt_mounted(void) {
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return access_fd(fd, W_OK) >= 0;
|
r = access_fd(fd, W_OK);
|
||||||
|
if (ERRNO_IS_NEG_FS_WRITE_REFUSED(r))
|
||||||
|
return false;
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int disable_binfmt(void) {
|
int disable_binfmt(void) {
|
||||||
@ -37,7 +43,7 @@ int disable_binfmt(void) {
|
|||||||
* We are a bit careful here, since binfmt_misc might still be an autofs which we don't want to
|
* We are a bit careful here, since binfmt_misc might still be an autofs which we don't want to
|
||||||
* trigger. */
|
* trigger. */
|
||||||
|
|
||||||
r = binfmt_mounted();
|
r = binfmt_mounted_and_writable();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m");
|
return log_warning_errno(r, "Failed to determine whether binfmt_misc is mounted: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
int binfmt_mounted(void);
|
int binfmt_mounted_and_writable(void);
|
||||||
int disable_binfmt(void);
|
int disable_binfmt(void);
|
||||||
|
@ -48,7 +48,7 @@ static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
|
|||||||
[BOOT_ENTRY_AUTO] = "auto",
|
[BOOT_ENTRY_AUTO] = "auto",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
|
DEFINE_STRING_TABLE_LOOKUP(boot_entry_type, BootEntryType);
|
||||||
|
|
||||||
static const char* const boot_entry_source_description_table[_BOOT_ENTRY_SOURCE_MAX] = {
|
static const char* const boot_entry_source_description_table[_BOOT_ENTRY_SOURCE_MAX] = {
|
||||||
[BOOT_ENTRY_ESP] = "EFI System Partition",
|
[BOOT_ENTRY_ESP] = "EFI System Partition",
|
||||||
|
@ -93,6 +93,7 @@ typedef struct BootConfig {
|
|||||||
|
|
||||||
const char* boot_entry_type_description_to_string(BootEntryType) _const_;
|
const char* boot_entry_type_description_to_string(BootEntryType) _const_;
|
||||||
const char* boot_entry_type_to_string(BootEntryType) _const_;
|
const char* boot_entry_type_to_string(BootEntryType) _const_;
|
||||||
|
BootEntryType boot_entry_type_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
const char* boot_entry_source_description_to_string(BootEntrySource) _const_;
|
const char* boot_entry_source_description_to_string(BootEntrySource) _const_;
|
||||||
const char* boot_entry_source_to_string(BootEntrySource) _const_;
|
const char* boot_entry_source_to_string(BootEntrySource) _const_;
|
||||||
|
@ -660,7 +660,7 @@ int loop_device_make_by_path_at(
|
|||||||
r = fd;
|
r = fd;
|
||||||
|
|
||||||
/* Retry read-only? */
|
/* Retry read-only? */
|
||||||
if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
|
if (open_flags >= 0 || !ERRNO_IS_NEG_FS_WRITE_REFUSED(r))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY);
|
fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY);
|
||||||
|
@ -447,7 +447,7 @@ int main(int argc, char *argv[]) {
|
|||||||
(void) sync_with_progress(-EBADF);
|
(void) sync_with_progress(-EBADF);
|
||||||
|
|
||||||
disable_coredumps();
|
disable_coredumps();
|
||||||
disable_binfmt();
|
(void) disable_binfmt();
|
||||||
|
|
||||||
log_info("Sending SIGTERM to remaining processes...");
|
log_info("Sending SIGTERM to remaining processes...");
|
||||||
broadcast_signal(SIGTERM, true, true, arg_timeout);
|
broadcast_signal(SIGTERM, true, true, arg_timeout);
|
||||||
|
@ -321,7 +321,7 @@ static int add_export_unix_socket(
|
|||||||
log_debug("Container manager does not provide /run/host/unix-export/ mount, not binding AF_UNIX socket there.");
|
log_debug("Container manager does not provide /run/host/unix-export/ mount, not binding AF_UNIX socket there.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (errno == EROFS || ERRNO_IS_PRIVILEGE(errno)) {
|
if (ERRNO_IS_FS_WRITE_REFUSED(errno)) {
|
||||||
log_debug("Container manager does not provide write access to /run/host/unix-export/, not binding AF_UNIX socket there.");
|
log_debug("Container manager does not provide write access to /run/host/unix-export/, not binding AF_UNIX socket there.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_
|
|||||||
* permission problem here, since that's how container managers usually protected their
|
* permission problem here, since that's how container managers usually protected their
|
||||||
* sysctls.)
|
* sysctls.)
|
||||||
* In all other cases log an error and make the tool fail. */
|
* In all other cases log an error and make the tool fail. */
|
||||||
if (ignore_failure || (!arg_strict && (r == -EROFS || ERRNO_IS_PRIVILEGE(r))))
|
if (ignore_failure || (!arg_strict && ERRNO_IS_NEG_FS_WRITE_REFUSED(r)))
|
||||||
log_debug_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
|
log_debug_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
|
||||||
else if (ignore_enoent && r == -ENOENT)
|
else if (ignore_enoent && r == -ENOENT)
|
||||||
log_warning_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
|
log_warning_errno(r, "Couldn't write '%s' to '%s', ignoring: %m", value, key);
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#include "binfmt-util.h"
|
#include "binfmt-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
TEST(binfmt_mounted) {
|
TEST(binfmt_mounted_and_writable) {
|
||||||
ASSERT_OK(binfmt_mounted());
|
ASSERT_OK(binfmt_mounted_and_writable());
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||||
|
@ -64,10 +64,8 @@ TEST(cg_create) {
|
|||||||
(void) cg_trim(test_b, /* delete_root= */ true);
|
(void) cg_trim(test_b, /* delete_root= */ true);
|
||||||
|
|
||||||
r = cg_create(test_a);
|
r = cg_create(test_a);
|
||||||
if (IN_SET(r, -EPERM, -EACCES, -EROFS)) {
|
if (ERRNO_IS_NEG_FS_WRITE_REFUSED(r))
|
||||||
log_info_errno(r, "Skipping %s: %m", __func__);
|
return (void) log_tests_skipped_errno(r, "%s: Failed to create cgroup %s", __func__, test_a);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_OK_EQ(r, 1);
|
ASSERT_OK_EQ(r, 1);
|
||||||
ASSERT_OK_ZERO(cg_create(test_a));
|
ASSERT_OK_ZERO(cg_create(test_a));
|
||||||
|
@ -51,7 +51,7 @@ int main(int argc, char *argv[]) {
|
|||||||
log_info("Reducing limit by one to %"PRIu64"…", limit-1);
|
log_info("Reducing limit by one to %"PRIu64"…", limit-1);
|
||||||
|
|
||||||
r = procfs_tasks_set_limit(limit-1);
|
r = procfs_tasks_set_limit(limit-1);
|
||||||
if (IN_SET(r, -ENOENT, -EROFS) || ERRNO_IS_PRIVILEGE(r))
|
if (r == -ENOENT || ERRNO_IS_NEG_FS_WRITE_REFUSED(r))
|
||||||
return log_tests_skipped_errno(r, "can't set tasks limit");
|
return log_tests_skipped_errno(r, "can't set tasks limit");
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ TEST(sysctl_read) {
|
|||||||
assert_se(STR_IN_SET(s, "0", "1"));
|
assert_se(STR_IN_SET(s, "0", "1"));
|
||||||
|
|
||||||
r = sysctl_write_ip_property(AF_INET, "lo", "forwarding", s, NULL);
|
r = sysctl_write_ip_property(AF_INET, "lo", "forwarding", s, NULL);
|
||||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
assert_se(r >= 0 || ERRNO_IS_NEG_FS_WRITE_REFUSED(r));
|
||||||
s = mfree(s);
|
s = mfree(s);
|
||||||
|
|
||||||
assert_se(sysctl_read_ip_property(AF_INET, NULL, "ip_forward", &s));
|
assert_se(sysctl_read_ip_property(AF_INET, NULL, "ip_forward", &s));
|
||||||
assert_se(STR_IN_SET(s, "0", "1"));
|
assert_se(STR_IN_SET(s, "0", "1"));
|
||||||
|
|
||||||
r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", s, NULL);
|
r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", s, NULL);
|
||||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
assert_se(r >= 0 || ERRNO_IS_NEG_FS_WRITE_REFUSED(r));
|
||||||
s = mfree(s);
|
s = mfree(s);
|
||||||
|
|
||||||
assert_se(sysctl_read("kernel/hostname", &s) >= 0);
|
assert_se(sysctl_read("kernel/hostname", &s) >= 0);
|
||||||
@ -69,7 +69,7 @@ TEST(sysctl_read) {
|
|||||||
ASSERT_STREQ(s, u.nodename);
|
ASSERT_STREQ(s, u.nodename);
|
||||||
|
|
||||||
r = sysctl_write("kernel/hostname", s);
|
r = sysctl_write("kernel/hostname", s);
|
||||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
assert_se(r >= 0 || ERRNO_IS_NEG_FS_WRITE_REFUSED(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TEST_MAIN(LOG_INFO);
|
DEFINE_TEST_MAIN(LOG_INFO);
|
||||||
|
@ -1181,18 +1181,32 @@ static int ssh_authorized_keys(int argc, char *argv[], void *userdata) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_credential_one(int credential_dir_fd, const char *name, int userdb_dir_fd) {
|
static int load_credential_one(
|
||||||
|
int credential_dir_fd,
|
||||||
|
const char *name,
|
||||||
|
int userdb_dir_persist_fd,
|
||||||
|
int userdb_dir_transient_fd) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(credential_dir_fd >= 0);
|
assert(credential_dir_fd >= 0);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(userdb_dir_fd >= 0);
|
assert(userdb_dir_persist_fd >= 0);
|
||||||
|
assert(userdb_dir_transient_fd >= 0);
|
||||||
|
|
||||||
const char *user = startswith(name, "userdb.user.");
|
const char *suffix = startswith(name, "userdb.");
|
||||||
const char *group = startswith(name, "userdb.group.");
|
if (!suffix)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char *transient = startswith(suffix, "transient."),
|
||||||
|
*user = startswith(transient ?: suffix, "user."),
|
||||||
|
*group = startswith(transient ?: suffix, "group.");
|
||||||
if (!user && !group)
|
if (!user && !group)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
const char *userdb_dir = transient ? "/run/userdb" : "/etc/userdb";
|
||||||
|
int userdb_dir_fd = transient ? userdb_dir_transient_fd : userdb_dir_persist_fd;
|
||||||
|
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||||
unsigned line = 0, column = 0;
|
unsigned line = 0, column = 0;
|
||||||
r = sd_json_parse_file_at(NULL, credential_dir_fd, name, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
r = sd_json_parse_file_at(NULL, credential_dir_fd, name, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||||
@ -1350,12 +1364,12 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
|||||||
|
|
||||||
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
|
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to write JSON record to /etc/userdb/%s: %m", fn);
|
return log_error_errno(r, "Failed to write JSON record to %s/%s: %m", userdb_dir, fn);
|
||||||
|
|
||||||
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
||||||
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
||||||
|
|
||||||
log_info("Installed /etc/userdb/%s from credential.", fn);
|
log_info("Installed %s/%s from credential.", userdb_dir, fn);
|
||||||
|
|
||||||
if ((ur && !sd_json_variant_is_blank_object(ur_privileged->json)) ||
|
if ((ur && !sd_json_variant_is_blank_object(ur_privileged->json)) ||
|
||||||
(gr && !sd_json_variant_is_blank_object(gr_privileged->json))) {
|
(gr && !sd_json_variant_is_blank_object(gr_privileged->json))) {
|
||||||
@ -1371,7 +1385,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
|||||||
|
|
||||||
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MODE_0600);
|
r = write_string_file_at(userdb_dir_fd, fn, formatted, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MODE_0600);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to write JSON record to /etc/userdb/%s: %m", fn);
|
return log_error_errno(r, "Failed to write JSON record to %s/%s: %m", userdb_dir, fn);
|
||||||
|
|
||||||
link = mfree(link);
|
link = mfree(link);
|
||||||
|
|
||||||
@ -1386,7 +1400,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
|||||||
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
if (symlinkat(fn, userdb_dir_fd, link) < 0)
|
||||||
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
return log_error_errno(errno, "Failed to create symlink from %s to %s: %m", link, fn);
|
||||||
|
|
||||||
log_info("Installed /etc/userdb/%s from credential.", fn);
|
log_info("Installed %s/%s from credential.", userdb_dir, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ur)
|
if (ur)
|
||||||
@ -1399,7 +1413,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
||||||
|
|
||||||
log_info("Installed /etc/userdb/%s from credential.", membership);
|
log_info("Installed %s/%s from credential.", userdb_dir, membership);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
STRV_FOREACH(u, gr->members) {
|
STRV_FOREACH(u, gr->members) {
|
||||||
@ -1411,7 +1425,7 @@ static int load_credential_one(int credential_dir_fd, const char *name, int user
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
return log_error_errno(errno, "Failed to create %s: %m", membership);
|
||||||
|
|
||||||
log_info("Installed /etc/userdb/%s from credential.", membership);
|
log_info("Installed %s/%s from credential.", userdb_dir, membership);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ur && user_record_disposition(ur) == USER_REGULAR) {
|
if (ur && user_record_disposition(ur) == USER_REGULAR) {
|
||||||
@ -1461,13 +1475,21 @@ static int load_credentials(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enumerate credentials: %m");
|
return log_error_errno(r, "Failed to enumerate credentials: %m");
|
||||||
|
|
||||||
_cleanup_close_ int userdb_dir_fd = xopenat_full(
|
_cleanup_close_ int userdb_persist_dir_fd = xopenat_full(
|
||||||
AT_FDCWD, "/etc/userdb",
|
AT_FDCWD, "/etc/userdb",
|
||||||
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
||||||
/* xopen_flags= */ XO_LABEL,
|
/* xopen_flags= */ XO_LABEL,
|
||||||
/* mode= */ 0755);
|
/* mode= */ 0755);
|
||||||
if (userdb_dir_fd < 0)
|
if (userdb_persist_dir_fd < 0)
|
||||||
return log_error_errno(userdb_dir_fd, "Failed to open %s: %m", "/etc/userdb/");
|
return log_error_errno(userdb_persist_dir_fd, "Failed to open /etc/userdb/: %m");
|
||||||
|
|
||||||
|
_cleanup_close_ int userdb_transient_dir_fd = xopenat_full(
|
||||||
|
AT_FDCWD, "/run/userdb",
|
||||||
|
/* open_flags= */ O_DIRECTORY|O_CREAT|O_CLOEXEC,
|
||||||
|
/* xopen_flags= */ XO_LABEL,
|
||||||
|
/* mode= */ 0755);
|
||||||
|
if (userdb_transient_dir_fd < 0)
|
||||||
|
return log_error_errno(userdb_transient_dir_fd, "Failed to open /run/userdb/: %m");
|
||||||
|
|
||||||
FOREACH_ARRAY(i, des->entries, des->n_entries) {
|
FOREACH_ARRAY(i, des->entries, des->n_entries) {
|
||||||
struct dirent *de = *i;
|
struct dirent *de = *i;
|
||||||
@ -1475,7 +1497,11 @@ static int load_credentials(int argc, char *argv[], void *userdata) {
|
|||||||
if (de->d_type != DT_REG)
|
if (de->d_type != DT_REG)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RET_GATHER(r, load_credential_one(credential_dir_fd, de->d_name, userdb_dir_fd));
|
RET_GATHER(r, load_credential_one(
|
||||||
|
credential_dir_fd,
|
||||||
|
de->d_name,
|
||||||
|
userdb_persist_dir_fd,
|
||||||
|
userdb_transient_dir_fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
316
test/units/TEST-04-JOURNAL.journal-reload.sh
Executable file
316
test/units/TEST-04-JOURNAL.journal-reload.sh
Executable file
@ -0,0 +1,316 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
set -eux
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
MACHINE_ID="$(</etc/machine-id)"
|
||||||
|
TEST_MSG_PREFIX="JOURNAL-RELOAD TEST"
|
||||||
|
SYSLOG_ID="$(systemd-id128 new)"
|
||||||
|
|
||||||
|
write_to_journal() {
|
||||||
|
local rand_val
|
||||||
|
|
||||||
|
rand_val=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 14)
|
||||||
|
echo "$TEST_MSG_PREFIX $rand_val" | systemd-cat -t "$SYSLOG_ID"
|
||||||
|
journalctl --sync
|
||||||
|
|
||||||
|
echo "$rand_val"
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_archived_journals() {
|
||||||
|
local msg="$1"
|
||||||
|
local journal_path_prefix="$2"
|
||||||
|
local journal_dir="/$journal_path_prefix/log/journal/$MACHINE_ID"
|
||||||
|
|
||||||
|
for journal_file in "$journal_dir"/*; do
|
||||||
|
filename=$(basename -- "$journal_file")
|
||||||
|
if [[ "$filename" != "system.journal" ]]; then
|
||||||
|
if journalctl --file="$journal_file" | grep -q "$msg"; then
|
||||||
|
echo "Message present in archived journal: $filename"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
verify_journal() {
|
||||||
|
local msg="$1"
|
||||||
|
local entry_expected="$2"
|
||||||
|
local test_name="$3"
|
||||||
|
local journal_path_prefix="$4"
|
||||||
|
|
||||||
|
local path="/$journal_path_prefix/log/journal/$MACHINE_ID/system.journal"
|
||||||
|
|
||||||
|
if [ ! -e "$path" ] || ! grep -Fxq "MESSAGE=$TEST_MSG_PREFIX $msg" "$path"; then
|
||||||
|
if [ "$entry_expected" == true ]; then
|
||||||
|
echo "$test_name ERROR: Message not present in $journal_path_prefix journal. Checking archived journals..."
|
||||||
|
if ! verify_archived_journals "$msg" "$journal_path_prefix"; then
|
||||||
|
echo "$test_name ERROR: Message also not present in archived journals"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$entry_expected" == false ]; then
|
||||||
|
echo "$test_name ERROR: Message present in $journal_path_prefix journal"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_journals() {
|
||||||
|
local msg="$1"
|
||||||
|
local runtime_expected="$2"
|
||||||
|
local system_expected="$3"
|
||||||
|
local test_name="$4"
|
||||||
|
|
||||||
|
local failed=false
|
||||||
|
|
||||||
|
if ! verify_journal "$msg" "$runtime_expected" "$test_name" "run"; then
|
||||||
|
failed=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! verify_journal "$msg" "$system_expected" "$test_name" "var"; then
|
||||||
|
failed=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$failed" == true ]; then
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_num_archived_journals() {
|
||||||
|
local journal_path_prefix="$1"
|
||||||
|
|
||||||
|
local journal_dir="/$journal_path_prefix/log/journal/$MACHINE_ID/"
|
||||||
|
num_journal_files=$(find "$journal_dir" -type f -name "*.journal" ! -name "system.journal" | wc -l)
|
||||||
|
|
||||||
|
echo "$num_journal_files"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm /run/systemd/journald.conf.d/reload.conf
|
||||||
|
journalctl --vacuum-size=1M
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start clean slate.
|
||||||
|
mkdir -p /run/systemd/journald.conf.d
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=persistent
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart systemd-journald.service
|
||||||
|
|
||||||
|
# Add entries in system.
|
||||||
|
journalctl --flush
|
||||||
|
rand_val1=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val1" false true "Confirming test setup after flush."
|
||||||
|
|
||||||
|
# Reload journald (persistent->persistent)
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
|
||||||
|
# Reload should persist persistent journal.
|
||||||
|
verify_journals "$rand_val1" false true "Persistent->Persistent System Reload: "
|
||||||
|
|
||||||
|
rand_val1=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val1" false true "Persistent->Persistent System Post-Reload: "
|
||||||
|
|
||||||
|
# Add entries in runtime
|
||||||
|
journalctl --relinquish
|
||||||
|
rand_val2=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val2" true false "Confirming test setup after relinquish."
|
||||||
|
|
||||||
|
# Reload journald (persistent->persistent)
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
|
||||||
|
# System journal entries should stay in system journal, runtime in runtime.
|
||||||
|
verify_journals "$rand_val1" false true "Persistent->Persistent Runtime Reload 1: "
|
||||||
|
verify_journals "$rand_val2" true false "Persistent->Persistent Runtime Reload 2: "
|
||||||
|
|
||||||
|
# Write new message and confirm it's written to runtime.
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" true false "Persistent->Persistent New Message After Reload: "
|
||||||
|
|
||||||
|
# Flush and confirm that messages are written to system.
|
||||||
|
journalctl --flush
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" false true "Persistent->Volatile New Message Before Reload: "
|
||||||
|
|
||||||
|
# Test persistent->volatile
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=volatile
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Confirm old message exists where it was written to (storage->storage).
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
verify_journals "$rand_val" false true "Persistent->Volatile Reload: "
|
||||||
|
|
||||||
|
# Confirm that messages are written to only runtime journal.
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" true false "Persistent->Volatile New Message After Reload: "
|
||||||
|
|
||||||
|
# Test volatile works and logs are NOT getting written to system journal despite flush.
|
||||||
|
journalctl --flush
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" true false "Persistent->Volatile New Message After Flush: "
|
||||||
|
|
||||||
|
# Test that the new limits (e.g., RuntimeMaxUse) take effect on reload.
|
||||||
|
# Write 1M of data to runtime journal
|
||||||
|
max_size=1048656 # (1 * 1024 * 1024) = 1048576, but centos has a different minimum value for some reason.
|
||||||
|
set +x
|
||||||
|
dd if=/dev/urandom bs=1M count=5 | base64 | systemd-cat -t "$SYSLOG_ID"
|
||||||
|
set -x
|
||||||
|
journalctl --vacuum-size=2M
|
||||||
|
|
||||||
|
total_size=$(du -sb "/run/log/journal/$MACHINE_ID" | cut -f1)
|
||||||
|
if [ "$total_size" -lt "$max_size" ]; then
|
||||||
|
echo "ERROR: Journal size does not exceed RuntimeMaxUse limit"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload with RuntimeMaxUse=1M.
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=volatile
|
||||||
|
RuntimeMaxUse=1M
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# systemctl daemon-reload
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
|
||||||
|
sleep 15 # Wait for RuntimeMaxUse change to take effect.
|
||||||
|
|
||||||
|
# Confirm that runtime journal size shrunk to <=1M.
|
||||||
|
total_size=$(du -sb "/run/log/journal/$MACHINE_ID" | cut -f1)
|
||||||
|
if [ "$total_size" -gt "$max_size" ]; then
|
||||||
|
echo "ERROR: Journal size exceeds RuntimeMaxUse limit"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prepare for volatile->persistent by getting rid of runtime limit. Otherwise, it will not write.
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=volatile
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
sleep 15 # Wait for RuntimeMaxUse change to take effect.
|
||||||
|
|
||||||
|
journalctl --vacuum-size=1M
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" true false "Volatile->Persistent New Message Before Reload: "
|
||||||
|
|
||||||
|
# Reload volatile->persistent
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=persistent
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
|
||||||
|
# Confirm that previous message is still in runtime journal.
|
||||||
|
verify_journals "$rand_val" true false "Volatile->Persistent Reload: "
|
||||||
|
|
||||||
|
# Confirm that new messages are written to runtime journal.
|
||||||
|
rand_val=$(write_to_journal)
|
||||||
|
verify_journals "$rand_val" true false "Volatile->Persistent New Message After Reload: "
|
||||||
|
|
||||||
|
# Confirm that flushing writes to system journal.
|
||||||
|
journalctl --flush
|
||||||
|
verify_journals "$rand_val" false true "Volatile->Persistent New Message After Flush: "
|
||||||
|
|
||||||
|
set +x
|
||||||
|
dd if=/dev/urandom bs=1M count=5 | base64 | systemd-cat -t "$SYSLOG_ID"
|
||||||
|
set -x
|
||||||
|
|
||||||
|
max_size=$((2 * 1024 * 1024))
|
||||||
|
total_size=$(du -sb "/var/log/journal/$MACHINE_ID" | cut -f1)
|
||||||
|
if [ "$total_size" -lt "$max_size" ]; then
|
||||||
|
echo "ERROR: Journal size does not exceed SystemMaxUse limit"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure reloading without limit does not interfere with SystemMaxUse test.
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
total_size=$(du -sb "/var/log/journal/$MACHINE_ID" | cut -f1)
|
||||||
|
if [ "$total_size" -lt "$max_size" ]; then
|
||||||
|
echo "ERROR: Journal size does not exceed SystemMaxUse limit"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write to storage to prepare for SystemMaxFiles test.
|
||||||
|
journalctl --flush
|
||||||
|
|
||||||
|
num_var_journals=$(get_num_archived_journals "var")
|
||||||
|
limit_var_journals=3
|
||||||
|
if [ "$num_var_journals" -lt "$limit_var_journals" ]; then
|
||||||
|
echo "Creating archive files."
|
||||||
|
for (( i=0; i<=num_var_journals; i++ ))
|
||||||
|
do
|
||||||
|
echo "$TEST_MSG_PREFIX" | systemd-cat -t "$SYSLOG_ID"
|
||||||
|
journalctl --rotate
|
||||||
|
done
|
||||||
|
|
||||||
|
num_var_journals=$(get_num_archived_journals "var")
|
||||||
|
if [ "$num_var_journals" -lt "$limit_var_journals" ]; then
|
||||||
|
echo "ERROR: Number of journal files in /var/log/journal/$MACHINE_ID/ is less than $limit_var_journals"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload with less SystemMaxUse and SystemMaxFiles.
|
||||||
|
cat <<EOF >/run/systemd/journald.conf.d/reload.conf
|
||||||
|
[Journal]
|
||||||
|
Storage=persistent
|
||||||
|
RuntimeMaxUse=2M
|
||||||
|
SystemMaxUse=2M
|
||||||
|
SystemMaxFiles=3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl reload systemd-journald.service
|
||||||
|
|
||||||
|
# New system journal needs to be created with the new configuration for change to take effect.
|
||||||
|
journalctl --flush
|
||||||
|
|
||||||
|
# Check SystemMaxFiles
|
||||||
|
num_var_journals=$(get_num_archived_journals "var")
|
||||||
|
if [ "$num_var_journals" -gt "$limit_var_journals" ]; then
|
||||||
|
echo "ERROR: Number of journal files in /var/log/journal/$MACHINE_ID/ is greater than $limit_var_journals"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 15
|
||||||
|
|
||||||
|
# Check SystemMaxUse
|
||||||
|
total_size=$(du -sb "/var/log/journal/$MACHINE_ID" | cut -f1)
|
||||||
|
if [ "$total_size" -gt "$max_size" ]; then
|
||||||
|
echo "ERROR: Journal size exceeds SystemMaxUse limit"
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm /run/systemd/journald.conf.d/reload.conf
|
||||||
|
journalctl --vacuum-size=1M
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl reload systemd-journald.service
|
@ -57,7 +57,7 @@ StandardOutput=null
|
|||||||
SystemCallArchitectures=native
|
SystemCallArchitectures=native
|
||||||
SystemCallErrorNumber=EPERM
|
SystemCallErrorNumber=EPERM
|
||||||
SystemCallFilter=@system-service
|
SystemCallFilter=@system-service
|
||||||
Type=notify
|
Type=notify-reload
|
||||||
PassEnvironment=TERM
|
PassEnvironment=TERM
|
||||||
{{SERVICE_WATCHDOG}}
|
{{SERVICE_WATCHDOG}}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ RemainAfterExit=yes
|
|||||||
ExecStart=userdbctl load-credentials
|
ExecStart=userdbctl load-credentials
|
||||||
ImportCredential=userdb.user.*
|
ImportCredential=userdb.user.*
|
||||||
ImportCredential=userdb.group.*
|
ImportCredential=userdb.group.*
|
||||||
|
ImportCredential=userdb.transient.user.*
|
||||||
|
ImportCredential=userdb.transient.group.*
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=sysinit.target
|
WantedBy=sysinit.target
|
||||||
|
Loading…
x
Reference in New Issue
Block a user