mirror of
https://github.com/systemd/systemd
synced 2025-09-21 21:04:46 +02:00
Compare commits
47 Commits
85a725a942
...
c6e6c85f83
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c6e6c85f83 | ||
![]() |
a55f64edc0 | ||
![]() |
9bec72c94f | ||
![]() |
d64720bbe7 | ||
![]() |
204c34040a | ||
![]() |
b594bdeb97 | ||
![]() |
ddd2590a4e | ||
![]() |
fd1351e3c8 | ||
![]() |
7472ca8744 | ||
![]() |
75a9c87004 | ||
![]() |
00b6fe28b6 | ||
![]() |
3c16aa53cc | ||
![]() |
052b15f4fe | ||
![]() |
acd33c5df8 | ||
![]() |
444af9538f | ||
![]() |
23860b4975 | ||
![]() |
acd4943528 | ||
![]() |
e566236fc1 | ||
![]() |
4301ad00ef | ||
![]() |
ff33c8f87d | ||
![]() |
9736f634c8 | ||
![]() |
97eeecaa3c | ||
![]() |
f8d5efc703 | ||
![]() |
b83f9acfef | ||
![]() |
194e05642f | ||
![]() |
6a616e62ad | ||
![]() |
2ff79a81a8 | ||
![]() |
aa5aac9e40 | ||
![]() |
87a87b02b9 | ||
![]() |
abd0eb20e4 | ||
![]() |
6e219a09c2 | ||
![]() |
5809c451e8 | ||
![]() |
248f651eb5 | ||
![]() |
e6b06359c0 | ||
![]() |
59897d8655 | ||
![]() |
a5527e2228 | ||
![]() |
6fdaa3d22c | ||
![]() |
f7dffbf835 | ||
![]() |
9f94034ea8 | ||
![]() |
f56c036fd3 | ||
![]() |
ee120e5caa | ||
![]() |
11a1f68217 | ||
![]() |
5035e4a4f8 | ||
![]() |
86048cce95 | ||
![]() |
8b6c1d392e | ||
![]() |
2f473de3cb | ||
![]() |
9b5ba882bd |
6
NEWS
6
NEWS
@ -1,5 +1,11 @@
|
||||
systemd System and Service Manager
|
||||
|
||||
CHANGES WITH 259 in spe:
|
||||
|
||||
* homectl's --recovery-key= option may now be used with the "update"
|
||||
command to add recovery keys to existing user accounts. Previously,
|
||||
recovery keys could only be configured during initial user creation.
|
||||
|
||||
CHANGES WITH 258:
|
||||
|
||||
Incompatible changes:
|
||||
|
@ -1584,6 +1584,13 @@ homectl update lafcadio --pkcs11-token-uri=auto</programlisting>
|
||||
<programlisting># Allow a FIDO2 security token to unlock the account of user 'nihilbaxter'.
|
||||
homectl update nihilbaxter --fido2-device=auto</programlisting>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Add a recovery key to an existing user account:</title>
|
||||
|
||||
<programlisting># Generate and add a recovery key for user 'emily'.
|
||||
homectl update emily --recovery-key=yes</programlisting>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -735,10 +735,11 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-W</option></term>
|
||||
<term><option>--no-hostname</option></term>
|
||||
|
||||
<listitem><para>Do not show the hostname field of log messages originating from the local host. This
|
||||
switch has an effect only on the <option>short</option> family of output modes (see above).</para>
|
||||
<listitem><para>Do not show the hostname field of log messages. This switch has an effect only on the
|
||||
<option>short</option> family of output modes (see above).</para>
|
||||
|
||||
<para>Note: this option does not remove occurrences of the hostname from log entries themselves, so
|
||||
it does not prevent the hostname from being visible in the logs.</para>
|
||||
|
@ -729,6 +729,14 @@ SUBSYSTEM=="net", OPTIONS="log_level=debug"</programlisting></para>
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>dump-json</option></term>
|
||||
<listitem>
|
||||
<para>Similar to <option>dump</option>, but dump the status of the event in JSON format.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v259"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
13
meson.build
13
meson.build
@ -3008,15 +3008,15 @@ summary({
|
||||
'default LLMNR mode' : default_llmnr,
|
||||
'default DNS servers' : dns_servers.split(' '),
|
||||
'default NTP servers' : ntp_servers.split(' '),
|
||||
'default net.naming_scheme= value': default_net_naming_scheme,
|
||||
'default KillUserProcesses= value': kill_user_processes,
|
||||
'default net.naming_scheme= value' : default_net_naming_scheme,
|
||||
'default KillUserProcesses= value' : kill_user_processes,
|
||||
'default locale' : default_locale,
|
||||
'default nspawn locale' : nspawn_locale,
|
||||
'default status unit format' : status_unit_format_default,
|
||||
'default user $PATH' :
|
||||
default_user_path != '' ? default_user_path : '(same as system services)',
|
||||
'default user $PATH' : default_user_path != '' ? default_user_path : '(same as system services)',
|
||||
'systemd service watchdog' : service_watchdog == '' ? 'disabled' : service_watchdog,
|
||||
'time epoch' : '@0@ (@1@)'.format(time_epoch, alt_time_epoch)})
|
||||
'time epoch' : '@0@ (@1@)'.format(time_epoch, alt_time_epoch)
|
||||
})
|
||||
|
||||
# TODO:
|
||||
# CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
|
||||
@ -3186,5 +3186,6 @@ endif
|
||||
|
||||
summary({
|
||||
'enabled' : ', '.join(found),
|
||||
'disabled' : ', '.join(missing)},
|
||||
'disabled' : ', '.join(missing)
|
||||
},
|
||||
section : 'Features')
|
||||
|
@ -111,7 +111,6 @@ Packages=
|
||||
llvm
|
||||
lsof
|
||||
lvm2
|
||||
man
|
||||
mdadm
|
||||
mtools
|
||||
nano
|
||||
|
@ -59,6 +59,7 @@ Packages=
|
||||
libapparmor1
|
||||
libcap-progs
|
||||
libtss2-tcti-device0
|
||||
man
|
||||
multipath-tools
|
||||
ncat
|
||||
open-iscsi
|
||||
|
@ -3,6 +3,8 @@ set -e
|
||||
|
||||
# We don't use mkosi.extra because /usr/sbin could be a symlink and cp doesn't handle that properly until
|
||||
# coreutils 9.5 or newer.
|
||||
mkdir -p "$BUILDROOT/sbin"
|
||||
rm -f "$BUILDROOT/sbin/init"
|
||||
cat >"$BUILDROOT/sbin/init" <<EOF
|
||||
#!/bin/bash
|
||||
echo "Hello from dummy init, beautiful day, innit?"
|
||||
|
@ -47,7 +47,7 @@ _journalctl() {
|
||||
--show-cursor --dmesg -k --pager-end -e -r --reverse
|
||||
--utc -x --catalog --no-full --force --dump-catalog
|
||||
--flush --rotate --sync --relinquish-var
|
||||
--smart-relinquish-var --no-hostname -N --fields
|
||||
--smart-relinquish-var --no-hostname -W -N --fields
|
||||
--list-namespaces --list-invocations -I -v --verbose'
|
||||
[ARG]='-b --boot -D --directory -i --file -F --field -t --identifier
|
||||
-T --exclude-identifier --facility -M --machine -o --output
|
||||
|
@ -99,7 +99,7 @@ _arguments -s \
|
||||
'(- *)'{-h,--help}'[Show this help]' \
|
||||
'(- *)--version[Show package version]' \
|
||||
'--no-pager[Do not pipe output into a pager]' \
|
||||
--no-hostname"[Don't show the hostname of local log messages]" \
|
||||
'(-W --no-hostname)'{-W,--no-hostname}"[Don't show the hostname of log messages]" \
|
||||
'(-l --full)'{-l,--full}'[Show long fields in full]' \
|
||||
'(-a --all)'{-a,--all}'[Show all fields, including long and unprintable]' \
|
||||
'(-f --follow)'{-f,--follow}'[Follow journal]' \
|
||||
|
@ -144,8 +144,8 @@ bool compression_supported(Compression c) {
|
||||
return BIT_SET(supported, c);
|
||||
}
|
||||
|
||||
#if HAVE_XZ
|
||||
int dlopen_lzma(void) {
|
||||
#if HAVE_XZ
|
||||
ELF_NOTE_DLOPEN("lzma",
|
||||
"Support lzma compression in journal and coredump files",
|
||||
COMPRESSION_PRIORITY_XZ,
|
||||
@ -160,8 +160,10 @@ int dlopen_lzma(void) {
|
||||
DLSYM_ARG(lzma_stream_buffer_encode),
|
||||
DLSYM_ARG(lzma_lzma_preset),
|
||||
DLSYM_ARG(lzma_stream_decoder));
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int compress_blob_xz(const void *src, uint64_t src_size,
|
||||
void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
|
||||
@ -213,8 +215,8 @@ int compress_blob_xz(const void *src, uint64_t src_size,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LZ4
|
||||
int dlopen_lz4(void) {
|
||||
#if HAVE_LZ4
|
||||
ELF_NOTE_DLOPEN("lz4",
|
||||
"Support lz4 compression in journal and coredump files",
|
||||
COMPRESSION_PRIORITY_LZ4,
|
||||
@ -238,8 +240,10 @@ int dlopen_lz4(void) {
|
||||
DLSYM_ARG(LZ4_decompress_safe),
|
||||
DLSYM_ARG(LZ4_decompress_safe_partial),
|
||||
DLSYM_ARG(LZ4_versionNumber));
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int compress_blob_lz4(const void *src, uint64_t src_size,
|
||||
void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
|
||||
@ -278,8 +282,8 @@ int compress_blob_lz4(const void *src, uint64_t src_size,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_ZSTD
|
||||
int dlopen_zstd(void) {
|
||||
#if HAVE_ZSTD
|
||||
ELF_NOTE_DLOPEN("zstd",
|
||||
"Support zstd compression in journal and coredump files",
|
||||
COMPRESSION_PRIORITY_ZSTD,
|
||||
@ -304,8 +308,10 @@ int dlopen_zstd(void) {
|
||||
DLSYM_ARG(ZSTD_isError),
|
||||
DLSYM_ARG(ZSTD_createDCtx),
|
||||
DLSYM_ARG(ZSTD_createCCtx));
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int compress_blob_zstd(
|
||||
const void *src, uint64_t src_size,
|
||||
|
@ -62,17 +62,9 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_size);
|
||||
int decompress_stream_lz4(int fdf, int fdt, uint64_t max_size);
|
||||
int decompress_stream_zstd(int fdf, int fdt, uint64_t max_size);
|
||||
|
||||
#if HAVE_LZ4
|
||||
int dlopen_lz4(void);
|
||||
#endif
|
||||
|
||||
#if HAVE_ZSTD
|
||||
int dlopen_zstd(void);
|
||||
#endif
|
||||
|
||||
#if HAVE_XZ
|
||||
int dlopen_lzma(void);
|
||||
#endif
|
||||
|
||||
static inline int compress_blob(
|
||||
Compression compression,
|
||||
|
@ -650,14 +650,16 @@ int write_env_file(int dir_fd, const char *fname, char **headers, char **l, Writ
|
||||
}
|
||||
|
||||
r = fopen_tmpfile_linkable_at(dir_fd, fname, O_WRONLY|O_CLOEXEC, &p, &f);
|
||||
if (call_label_ops_post)
|
||||
RET_GATHER(r, label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f));
|
||||
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f) : 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
CLEANUP_TMPFILE_AT(dir_fd, p);
|
||||
if (k < 0)
|
||||
return k;
|
||||
|
||||
r = fchmod_umask(fileno(f), 0644);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, headers) {
|
||||
assert(isempty(*i) || startswith(*i, "#"));
|
||||
@ -670,15 +672,11 @@ int write_env_file(int dir_fd, const char *fname, char **headers, char **l, Writ
|
||||
|
||||
r = flink_tmpfile_at(f, dir_fd, p, fname, LINK_TMPFILE_REPLACE|LINK_TMPFILE_SYNC);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
p = mfree(p); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (p)
|
||||
(void) unlinkat(dir_fd, p, 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int write_vconsole_conf(int dir_fd, const char *fname, char **l) {
|
||||
|
@ -240,24 +240,28 @@ static int write_string_file_atomic_at(
|
||||
}
|
||||
|
||||
r = fopen_temporary_at(dir_fd, fn, &f, &p);
|
||||
if (call_label_ops_post)
|
||||
/* If fopen_temporary_at() failed in the above, propagate the error code, and ignore failures
|
||||
* in label_ops_post(). */
|
||||
RET_GATHER(r, label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f));
|
||||
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f) : 0;
|
||||
/* If fopen_temporary_at() failed in the above, propagate the error code, and ignore failures in
|
||||
* label_ops_post(). */
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
CLEANUP_TMPFILE_AT(dir_fd, p);
|
||||
if (k < 0)
|
||||
return k;
|
||||
|
||||
r = write_string_stream_full(f, line, flags, ts);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
r = fchmod_umask(fileno(f), mode);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
r = RET_NERRNO(renameat(dir_fd, p, dir_fd, fn));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
p = mfree(p); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
|
||||
if (FLAGS_SET(flags, WRITE_STRING_FILE_SYNC)) {
|
||||
/* Sync the rename, too */
|
||||
@ -267,11 +271,6 @@ static int write_string_file_atomic_at(
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (f)
|
||||
(void) unlinkat(dir_fd, p, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
int write_string_file_full(
|
||||
|
@ -236,7 +236,7 @@ typedef struct sd_hwdb sd_hwdb;
|
||||
|
||||
/* shared/ forward declarations */
|
||||
|
||||
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);
|
||||
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, uint64_t bytes_per_second, void *userdata);
|
||||
typedef int (*copy_progress_path_t)(const char *path, const struct stat *st, void *userdata);
|
||||
|
||||
struct local_address;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include "gcrypt-util.h"
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
|
||||
static void *gcrypt_dl = NULL;
|
||||
|
||||
static DLSYM_PROTOTYPE(gcry_control) = NULL;
|
||||
@ -40,8 +40,10 @@ DLSYM_PROTOTYPE(gcry_mpi_sub_ui) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_prime_check) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_randomize) = NULL;
|
||||
DLSYM_PROTOTYPE(gcry_strerror) = NULL;
|
||||
#endif
|
||||
|
||||
static int dlopen_gcrypt(void) {
|
||||
int dlopen_gcrypt(void) {
|
||||
#if HAVE_GCRYPT
|
||||
ELF_NOTE_DLOPEN("gcrypt",
|
||||
"Support for journald forward-sealing",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
@ -82,9 +84,13 @@ static int dlopen_gcrypt(void) {
|
||||
DLSYM_ARG(gcry_prime_check),
|
||||
DLSYM_ARG(gcry_randomize),
|
||||
DLSYM_ARG(gcry_strerror));
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int initialize_libgcrypt(bool secmem) {
|
||||
#if HAVE_GCRYPT
|
||||
int r;
|
||||
|
||||
r = dlopen_gcrypt();
|
||||
@ -105,5 +111,7 @@ int initialize_libgcrypt(bool secmem) {
|
||||
sym_gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
int dlopen_gcrypt(void);
|
||||
|
||||
int initialize_libgcrypt(bool secmem);
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
#include <gcrypt.h> /* IWYU pragma: export */
|
||||
|
||||
@ -40,8 +44,6 @@ extern DLSYM_PROTOTYPE(gcry_prime_check);
|
||||
extern DLSYM_PROTOTYPE(gcry_randomize);
|
||||
extern DLSYM_PROTOTYPE(gcry_strerror);
|
||||
|
||||
int initialize_libgcrypt(bool secmem);
|
||||
|
||||
/* Copied from gcry_md_putc from gcrypt.h due to the need to call the sym_ variant */
|
||||
#define sym_gcry_md_putc(h,c) \
|
||||
do { \
|
||||
|
@ -436,3 +436,17 @@ int mkdtemp_open(const char *template, int flags, char **ret) {
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void cleanup_tmpfile_data_done(struct cleanup_tmpfile_data *d) {
|
||||
assert(d);
|
||||
|
||||
if (!d->dir_fd ||
|
||||
*d->dir_fd < 0 ||
|
||||
!d->filename ||
|
||||
!*d->filename)
|
||||
return;
|
||||
|
||||
(void) unlinkat(*d->dir_fd, *d->filename, 0);
|
||||
d->dir_fd = NULL;
|
||||
d->filename = NULL;
|
||||
}
|
||||
|
@ -48,3 +48,14 @@ static inline int flink_tmpfile(FILE *f, const char *path, const char *target, L
|
||||
|
||||
int mkdtemp_malloc(const char *template, char **ret);
|
||||
int mkdtemp_open(const char *template, int flags, char **ret);
|
||||
|
||||
/* A helper for removing link_tmpfile_at() via _cleanup_() */
|
||||
struct cleanup_tmpfile_data {
|
||||
int *dir_fd;
|
||||
char **filename;
|
||||
};
|
||||
void cleanup_tmpfile_data_done(struct cleanup_tmpfile_data *d);
|
||||
#define _CLEANUP_TMPFILE_AT(u, dir_fd, filename) \
|
||||
_unused_ _cleanup_(cleanup_tmpfile_data_done) struct cleanup_tmpfile_data UNIQ_T(cta, u) = { &(dir_fd), &(filename) }
|
||||
#define CLEANUP_TMPFILE_AT(dir_fd, filename) \
|
||||
_CLEANUP_TMPFILE_AT(UNIQ, dir_fd, filename)
|
||||
|
@ -1165,6 +1165,10 @@ static void boot_entry_parse_tries(
|
||||
if (!strcaseeq16(counter, suffix))
|
||||
return;
|
||||
|
||||
entry->id = xasprintf("%.*ls%ls",
|
||||
(int) prefix_len - 1,
|
||||
file,
|
||||
suffix);
|
||||
entry->tries_left = tries_left;
|
||||
entry->tries_done = tries_done;
|
||||
entry->directory = xstrdup16(directory);
|
||||
@ -1395,13 +1399,16 @@ static void boot_entry_add_type1(
|
||||
}
|
||||
|
||||
entry->device = device;
|
||||
entry->id = xstrdup16(file);
|
||||
strtolower16(entry->id);
|
||||
|
||||
config_add_entry(config, entry);
|
||||
|
||||
if (path)
|
||||
boot_entry_parse_tries(entry, path, file, u".conf");
|
||||
|
||||
if (!entry->id)
|
||||
entry->id = xstrdup16(file);
|
||||
|
||||
strtolower16(entry->id);
|
||||
|
||||
config_add_entry(config, entry);
|
||||
TAKE_PTR(entry);
|
||||
}
|
||||
|
||||
|
@ -132,16 +132,19 @@ elif get_option('sbat-distro') != ''
|
||||
endif
|
||||
endif
|
||||
|
||||
summary({'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)},
|
||||
summary({
|
||||
'UEFI architectures' : efi_arch + (efi_arch_alt == '' ? '' : ', ' + efi_arch_alt)
|
||||
},
|
||||
section : 'UEFI')
|
||||
|
||||
if efi_conf.get('SBAT_DISTRO', '') != ''
|
||||
summary({
|
||||
'SBAT distro': efi_conf.get('SBAT_DISTRO'),
|
||||
'SBAT distro generation': efi_conf.get('SBAT_DISTRO_GENERATION'),
|
||||
'SBAT distro version': efi_conf.get('SBAT_DISTRO_VERSION'),
|
||||
'SBAT distro summary': efi_conf.get('SBAT_DISTRO_SUMMARY'),
|
||||
'SBAT distro URL': efi_conf.get('SBAT_DISTRO_URL')},
|
||||
'SBAT distro' : efi_conf.get('SBAT_DISTRO'),
|
||||
'SBAT distro generation' : efi_conf.get('SBAT_DISTRO_GENERATION'),
|
||||
'SBAT distro version' : efi_conf.get('SBAT_DISTRO_VERSION'),
|
||||
'SBAT distro summary' : efi_conf.get('SBAT_DISTRO_SUMMARY'),
|
||||
'SBAT distro URL' : efi_conf.get('SBAT_DISTRO_URL')
|
||||
},
|
||||
section : 'UEFI')
|
||||
endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -336,40 +336,35 @@ static int write_credential(
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
CLEANUP_TMPFILE_AT(dfd, tmp);
|
||||
|
||||
r = loop_write(fd, data, size);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
r = RET_NERRNO(fchmod(fd, 0400)); /* Take away "w" bit */
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
if (uid_is_valid(uid) && uid != getuid()) {
|
||||
r = fd_add_uid_acl_permission(fd, uid, ACL_READ);
|
||||
if (r < 0) {
|
||||
/* Ideally we use ACLs, since we can neatly express what we want to express:
|
||||
* the user gets read access and nothing else. But if the backing fs can't
|
||||
* support that (e.g. ramfs), then we can use file ownership instead. But that's
|
||||
* only safe if we can then re-mount the whole thing read-only, so that the user
|
||||
* can no longer chmod() the file to gain write access. */
|
||||
if (!ownership_ok || (!ERRNO_IS_NOT_SUPPORTED(r) && !ERRNO_IS_PRIVILEGE(r)))
|
||||
goto fail;
|
||||
|
||||
if ((ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r)) && ownership_ok)
|
||||
r = RET_NERRNO(fchown(fd, uid, gid));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
r = RET_NERRNO(renameat(dfd, tmp, dfd, id));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
(void) unlinkat(dfd, tmp, /* flags = */ 0);
|
||||
return r;
|
||||
|
||||
tmp = mfree(tmp); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum CredentialSearchPath {
|
||||
|
@ -22,7 +22,7 @@ static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependen
|
||||
assert(tr);
|
||||
assert(j);
|
||||
|
||||
/* Deletes one job from the transaction */
|
||||
/* Deletes one job from the transaction. */
|
||||
|
||||
transaction_unlink_job(tr, j, delete_dependencies);
|
||||
|
||||
@ -32,8 +32,7 @@ static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependen
|
||||
static void transaction_delete_unit(Transaction *tr, Unit *u) {
|
||||
Job *j;
|
||||
|
||||
/* Deletes all jobs associated with a certain unit from the
|
||||
* transaction */
|
||||
/* Deletes all jobs associated with a certain unit from the transaction. */
|
||||
|
||||
while ((j = hashmap_get(tr->jobs, u)))
|
||||
transaction_delete_job(tr, j, true);
|
||||
@ -53,21 +52,20 @@ static void transaction_abort(Transaction *tr) {
|
||||
static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
|
||||
assert(j);
|
||||
|
||||
/* A recursive sweep through the graph that marks all units
|
||||
* that matter to the anchor job, i.e. are directly or
|
||||
* indirectly a dependency of the anchor job via paths that
|
||||
* are fully marked as mattering. */
|
||||
/* A recursive sweep through the graph that marks all units that matter to the anchor job, i.e. are
|
||||
* directly or indirectly a dependency of the anchor job via paths that are fully marked as
|
||||
* mattering. */
|
||||
|
||||
j->matters_to_anchor = true;
|
||||
j->generation = generation;
|
||||
|
||||
LIST_FOREACH(subject, l, j->subject_list) {
|
||||
|
||||
/* This link does not matter */
|
||||
/* This link does not matter. */
|
||||
if (!l->matters)
|
||||
continue;
|
||||
|
||||
/* This unit has already been marked */
|
||||
/* This unit has already been marked. */
|
||||
if (l->object->generation == generation)
|
||||
continue;
|
||||
|
||||
@ -90,7 +88,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
j->irreversible = j->irreversible || other->irreversible;
|
||||
j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
|
||||
|
||||
/* Patch us in as new owner of the JobDependency objects */
|
||||
/* Patch us in as new owner of the JobDependency objects. */
|
||||
last = NULL;
|
||||
LIST_FOREACH(subject, l, other->subject_list) {
|
||||
assert(l->subject == other);
|
||||
@ -98,7 +96,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
last = l;
|
||||
}
|
||||
|
||||
/* Merge both lists */
|
||||
/* Merge both lists. */
|
||||
if (last) {
|
||||
last->subject_next = j->subject_list;
|
||||
if (j->subject_list)
|
||||
@ -106,7 +104,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
j->subject_list = other->subject_list;
|
||||
}
|
||||
|
||||
/* Patch us in as new owner of the JobDependency objects */
|
||||
/* Patch us in as new owner of the JobDependency objects. */
|
||||
last = NULL;
|
||||
LIST_FOREACH(object, l, other->object_list) {
|
||||
assert(l->object == other);
|
||||
@ -114,7 +112,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
last = l;
|
||||
}
|
||||
|
||||
/* Merge both lists */
|
||||
/* Merge both lists. */
|
||||
if (last) {
|
||||
last->object_next = j->object_list;
|
||||
if (j->object_list)
|
||||
@ -122,7 +120,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
j->object_list = other->object_list;
|
||||
}
|
||||
|
||||
/* Kill the other job */
|
||||
/* Kill the other job. */
|
||||
other->subject_list = NULL;
|
||||
other->object_list = NULL;
|
||||
transaction_delete_job(tr, other, true);
|
||||
@ -131,8 +129,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
||||
static bool job_is_conflicted_by(Job *j) {
|
||||
assert(j);
|
||||
|
||||
/* Returns true if this job is pulled in by a least one
|
||||
* ConflictedBy dependency. */
|
||||
/* Returns true if this job is pulled in by a least one ConflictedBy= dependency. */
|
||||
|
||||
LIST_FOREACH(object, l, j->object_list)
|
||||
if (l->conflicts)
|
||||
@ -145,59 +142,51 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *job) {
|
||||
assert(job);
|
||||
|
||||
/* Tries to delete one item in the linked list
|
||||
* j->transaction_next->transaction_next->... that conflicts
|
||||
* with another one, in an attempt to make an inconsistent
|
||||
* transaction work. */
|
||||
* j->transaction_next->transaction_next->... that conflicts with another one, in an attempt to make
|
||||
* an inconsistent transaction work. */
|
||||
|
||||
/* We rely here on the fact that if a merged with b does not
|
||||
* merge with c, either a or b merge with c neither */
|
||||
/* We rely here on the fact that if a merged with b does not merge with c, either a or b merge with c
|
||||
* neither. */
|
||||
LIST_FOREACH(transaction, j, job)
|
||||
LIST_FOREACH(transaction, k, j->transaction_next) {
|
||||
Job *d;
|
||||
|
||||
/* Is this one mergeable? Then skip it */
|
||||
/* Is this one mergeable? Then skip it. */
|
||||
if (job_type_is_mergeable(j->type, k->type))
|
||||
continue;
|
||||
|
||||
/* Ok, we found two that conflict, let's see if we can
|
||||
* drop one of them */
|
||||
/* Ok, we found two that conflict, let's see if we can drop one of them. */
|
||||
if (!j->matters_to_anchor && !k->matters_to_anchor) {
|
||||
|
||||
/* Both jobs don't matter, so let's
|
||||
* find the one that is smarter to
|
||||
* remove. Let's think positive and
|
||||
* rather remove stops then starts --
|
||||
* except if something is being
|
||||
* stopped because it is conflicted by
|
||||
* another unit in which case we
|
||||
* rather remove the start. */
|
||||
/* Both jobs don't matter, so let's find the one that is smarter to remove.
|
||||
* Let's think positive and rather remove stops than starts -- except if
|
||||
* something is being stopped because it is conflicted by another unit in
|
||||
* which case we rather remove the start. */
|
||||
|
||||
bool j_is_conflicted_by = job_is_conflicted_by(j),
|
||||
k_is_conflicted_by = job_is_conflicted_by(k);
|
||||
|
||||
/* Update test/units/TEST-87-AUX-UTILS-VM.sh when logs below are changed. */
|
||||
log_unit_debug(j->unit,
|
||||
"Looking at job %s/%s conflicted_by=%s",
|
||||
j->unit->id, job_type_to_string(j->type),
|
||||
yes_no(j->type == JOB_STOP && job_is_conflicted_by(j)));
|
||||
yes_no(j->type == JOB_STOP && j_is_conflicted_by));
|
||||
log_unit_debug(k->unit,
|
||||
"Looking at job %s/%s conflicted_by=%s",
|
||||
k->unit->id, job_type_to_string(k->type),
|
||||
yes_no(k->type == JOB_STOP && job_is_conflicted_by(k)));
|
||||
yes_no(k->type == JOB_STOP && k_is_conflicted_by));
|
||||
|
||||
if (j->type == JOB_STOP) {
|
||||
|
||||
if (job_is_conflicted_by(j))
|
||||
if (j->type == JOB_STOP && j_is_conflicted_by)
|
||||
d = k;
|
||||
else if (k->type == JOB_STOP && k_is_conflicted_by)
|
||||
d = j;
|
||||
else if (j->type == JOB_STOP)
|
||||
d = j;
|
||||
else if (k->type == JOB_STOP)
|
||||
d = k;
|
||||
else
|
||||
d = j;
|
||||
|
||||
} else if (k->type == JOB_STOP) {
|
||||
|
||||
if (job_is_conflicted_by(k))
|
||||
d = j;
|
||||
else
|
||||
d = k;
|
||||
} else
|
||||
d = j;
|
||||
|
||||
} else if (!j->matters_to_anchor)
|
||||
d = j;
|
||||
else if (!k->matters_to_anchor)
|
||||
@ -235,18 +224,16 @@ static int transaction_ensure_mergeable(Transaction *tr, bool matters_to_anchor,
|
||||
if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
|
||||
continue;
|
||||
|
||||
/* OK, we could not merge all jobs for this
|
||||
* action. Let's see if we can get rid of one
|
||||
* of them */
|
||||
/* OK, we could not merge all jobs for this action. Let's see if we can get rid of
|
||||
* one of them. */
|
||||
|
||||
r = delete_one_unmergeable_job(tr, j);
|
||||
if (r >= 0)
|
||||
/* Ok, we managed to drop one, now
|
||||
* let's ask our callers to call us
|
||||
* again after garbage collecting */
|
||||
/* Ok, we managed to drop one, now let's ask our callers to call us again
|
||||
* after garbage collecting. */
|
||||
return -EAGAIN;
|
||||
|
||||
/* We couldn't merge anything. Failure */
|
||||
/* We couldn't merge anything. Failure. */
|
||||
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING,
|
||||
"Transaction contains conflicting jobs '%s' and '%s' for %s. "
|
||||
"Probably contradicting requirement dependencies configured.",
|
||||
@ -279,7 +266,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
|
||||
HASHMAP_FOREACH(j, tr->jobs) {
|
||||
JobType t = j->type;
|
||||
|
||||
/* Merge all transaction jobs for j->unit */
|
||||
/* Merge all transaction jobs for j->unit. */
|
||||
LIST_FOREACH(transaction, k, j->transaction_next)
|
||||
assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
|
||||
|
||||
@ -378,7 +365,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
|
||||
* marker to find our way back, since smart how we are we stored our way back in there. */
|
||||
for (Job *k = from; k; k = (k->generation == generation && k->marker != k) ? k->marker : NULL) {
|
||||
|
||||
/* For logging below */
|
||||
/* For logging below. */
|
||||
if (strv_push_pair(&array, k->unit->id, (char*) job_type_to_string(k->type)) < 0)
|
||||
(void) log_oom_warning();
|
||||
|
||||
@ -386,7 +373,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
|
||||
/* Ok, we can drop this one, so let's do so. */
|
||||
delete = k;
|
||||
|
||||
/* Check if this in fact was the beginning of the cycle */
|
||||
/* Check if this in fact was the beginning of the cycle. */
|
||||
if (k == j)
|
||||
break;
|
||||
}
|
||||
@ -449,10 +436,8 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
|
||||
"Transaction order is cyclic. See system logs for details.");
|
||||
}
|
||||
|
||||
/* Make the marker point to where we come from, so that we can
|
||||
* find our way backwards if we want to break a cycle. We use
|
||||
* a special marker for the beginning: we point to
|
||||
* ourselves. */
|
||||
/* Make the marker point to where we come from, so that we can find our way backwards if we want to
|
||||
* break a cycle. We use a special marker for the beginning: we point to ourselves. */
|
||||
j->marker = from ?: j;
|
||||
j->generation = generation;
|
||||
|
||||
@ -486,8 +471,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
|
||||
}
|
||||
}
|
||||
|
||||
/* Ok, let's backtrack, and remember that this entry is not on
|
||||
* our path anymore. */
|
||||
/* Ok, let's backtrack, and remember that this entry is not on our path anymore. */
|
||||
j->marker = NULL;
|
||||
|
||||
return 0;
|
||||
@ -501,8 +485,7 @@ static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bu
|
||||
assert(tr);
|
||||
assert(generation);
|
||||
|
||||
/* Check if the ordering graph is cyclic. If it is, try to fix
|
||||
* that up by dropping one of the jobs. */
|
||||
/* Check if the ordering graph is cyclic. If it is, try to fix that up by dropping one of the jobs. */
|
||||
|
||||
g = (*generation)++;
|
||||
|
||||
@ -520,7 +503,7 @@ static void transaction_collect_garbage(Transaction *tr) {
|
||||
|
||||
assert(tr);
|
||||
|
||||
/* Drop jobs that are not required by any other job */
|
||||
/* Drop jobs that are not required by any other job. */
|
||||
|
||||
do {
|
||||
Job *j;
|
||||
@ -552,8 +535,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_erro
|
||||
|
||||
assert(tr);
|
||||
|
||||
/* Checks whether applying this transaction means that
|
||||
* existing jobs would be replaced */
|
||||
/* Checks whether applying this transaction means that existing jobs would be replaced. */
|
||||
|
||||
HASHMAP_FOREACH(j, tr->jobs) {
|
||||
|
||||
@ -577,8 +559,7 @@ static int transaction_minimize_impact(Transaction *tr, JobMode mode, sd_bus_err
|
||||
|
||||
assert(tr);
|
||||
|
||||
/* Drops all unnecessary jobs that reverse already active jobs
|
||||
* or that stop a running service. */
|
||||
/* Drops all unnecessary jobs that reverse already active jobs or that stop a running service. */
|
||||
|
||||
if (!IN_SET(mode, JOB_FAIL, JOB_LENIENT))
|
||||
return 0;
|
||||
@ -588,13 +569,12 @@ rescan:
|
||||
LIST_FOREACH(transaction, j, head) {
|
||||
bool stops_running_service, changes_existing_job;
|
||||
|
||||
/* If it matters, we shouldn't drop it */
|
||||
/* If it matters, we shouldn't drop it. */
|
||||
if (j->matters_to_anchor && mode != JOB_LENIENT)
|
||||
continue;
|
||||
|
||||
/* Would this stop a running service?
|
||||
* Would this change an existing job?
|
||||
* If so, let's drop this entry */
|
||||
/* Would this stop a running service? Would this change an existing job? If so, let's
|
||||
* drop this entry. */
|
||||
|
||||
stops_running_service =
|
||||
j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
|
||||
@ -623,7 +603,7 @@ rescan:
|
||||
"%s/%s would change existing job.",
|
||||
j->unit->id, job_type_to_string(j->type));
|
||||
|
||||
/* Ok, let's get rid of this */
|
||||
/* Ok, let's get rid of this. */
|
||||
log_unit_debug(j->unit,
|
||||
"Deleting %s/%s to minimize impact.",
|
||||
j->unit->id, job_type_to_string(j->type));
|
||||
@ -648,12 +628,11 @@ static int transaction_apply(
|
||||
assert(tr);
|
||||
assert(m);
|
||||
|
||||
/* Moves the transaction jobs to the set of active jobs */
|
||||
/* Moves the transaction jobs to the set of active jobs. */
|
||||
|
||||
if (IN_SET(mode, JOB_ISOLATE, JOB_FLUSH)) {
|
||||
|
||||
/* When isolating first kill all installed jobs which
|
||||
* aren't part of the new transaction */
|
||||
/* When isolating first kill all installed jobs which aren't part of the new transaction. */
|
||||
HASHMAP_FOREACH(j, m->jobs) {
|
||||
assert(j->installed);
|
||||
|
||||
@ -663,15 +642,14 @@ static int transaction_apply(
|
||||
if (hashmap_contains(tr->jobs, j->unit))
|
||||
continue;
|
||||
|
||||
/* Not invalidating recursively. Avoids triggering
|
||||
* OnFailure= actions of dependent jobs. Also avoids
|
||||
* invalidating our iterator. */
|
||||
/* Not invalidating recursively. Avoids triggering OnFailure= actions of dependent
|
||||
* jobs. Also avoids invalidating our iterator. */
|
||||
job_finish_and_invalidate(j, JOB_CANCELED, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(j, tr->jobs) {
|
||||
/* Assume merged */
|
||||
/* Assume merged. */
|
||||
assert(!j->transaction_prev);
|
||||
assert(!j->transaction_next);
|
||||
|
||||
@ -683,12 +661,12 @@ static int transaction_apply(
|
||||
while ((j = hashmap_steal_first(tr->jobs))) {
|
||||
Job *installed_job;
|
||||
|
||||
/* Clean the job dependencies */
|
||||
/* Clean the job dependencies. */
|
||||
transaction_unlink_job(tr, j, false);
|
||||
|
||||
installed_job = job_install(j);
|
||||
if (installed_job != j) {
|
||||
/* j has been merged into a previously installed job */
|
||||
/* j has been merged into a previously installed job. */
|
||||
if (tr->anchor_job == j)
|
||||
tr->anchor_job = installed_job;
|
||||
|
||||
@ -733,71 +711,69 @@ int transaction_activate(
|
||||
assert(tr);
|
||||
assert(m);
|
||||
|
||||
/* Reset the generation counter of all installed jobs. The detection of cycles
|
||||
* looks at installed jobs. If they had a non-zero generation from some previous
|
||||
* walk of the graph, the algorithm would break. */
|
||||
/* Reset the generation counter of all installed jobs. The detection of cycles looks at installed
|
||||
* jobs. If they had a non-zero generation from some previous walk of the graph, the algorithm would
|
||||
* break. */
|
||||
HASHMAP_FOREACH(j, m->jobs)
|
||||
j->generation = 0;
|
||||
|
||||
/* First step: figure out which jobs matter */
|
||||
/* First step: figure out which jobs matter. */
|
||||
transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
|
||||
|
||||
/* Second step: Try not to stop any running services if we don't have to. Don't try to reverse
|
||||
* running jobs if we don't have to. */
|
||||
r = transaction_minimize_impact(tr, mode, e);
|
||||
if (r < 0)
|
||||
return r; /* Note that we don't log here, because for JOB_LENIENT conflicts are very much expected
|
||||
and shouldn't appear to be fatal for the unit. Only inform the caller via bus error. */
|
||||
return r; /* Note that we don't log here, because for JOB_LENIENT conflicts are very much
|
||||
* expected and shouldn't appear to be fatal for the unit. Only inform the caller
|
||||
* via bus error. */
|
||||
|
||||
/* Third step: Drop redundant jobs */
|
||||
/* Third step: Drop redundant jobs. */
|
||||
transaction_drop_redundant(tr);
|
||||
|
||||
for (;;) {
|
||||
/* Fourth step: Let's remove unneeded jobs that might
|
||||
* be lurking. */
|
||||
/* Fourth step: Let's remove unneeded jobs that might be lurking. */
|
||||
if (mode != JOB_ISOLATE)
|
||||
transaction_collect_garbage(tr);
|
||||
|
||||
/* Fifth step: verify order makes sense and correct
|
||||
* cycles if necessary and possible */
|
||||
/* Fifth step: verify order makes sense and correct cycles if necessary and possible. */
|
||||
r = transaction_verify_order(tr, &generation, e);
|
||||
if (r >= 0)
|
||||
break;
|
||||
if (r != -EAGAIN)
|
||||
return log_warning_errno(r, "Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
|
||||
return log_warning_errno(r, "Requested transaction contains an unfixable cyclic ordering dependency: %s",
|
||||
bus_error_message(e, r));
|
||||
|
||||
/* Let's see if the resulting transaction ordering
|
||||
* graph is still cyclic... */
|
||||
/* Let's see if the resulting transaction ordering graph is still cyclic... */
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Sixth step: let's drop unmergeable entries if
|
||||
* necessary and possible, merge entries we can
|
||||
* merge */
|
||||
/* Sixth step: let's drop unmergeable entries if necessary and possible, merge entries we can
|
||||
* merge. */
|
||||
r = transaction_merge_jobs(tr, e);
|
||||
if (r >= 0)
|
||||
break;
|
||||
if (r != -EAGAIN)
|
||||
return log_warning_errno(r, "Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
|
||||
return log_warning_errno(r, "Requested transaction contains unmergeable jobs: %s",
|
||||
bus_error_message(e, r));
|
||||
|
||||
/* Seventh step: an entry got dropped, let's garbage
|
||||
* collect its dependencies. */
|
||||
/* Seventh step: an entry got dropped, let's garbage collect its dependencies. */
|
||||
if (mode != JOB_ISOLATE)
|
||||
transaction_collect_garbage(tr);
|
||||
|
||||
/* Let's see if the resulting transaction still has
|
||||
* unmergeable entries ... */
|
||||
/* Let's see if the resulting transaction still has unmergeable entries... */
|
||||
}
|
||||
|
||||
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
|
||||
transaction_drop_redundant(tr);
|
||||
|
||||
/* Ninth step: check whether we can actually apply this */
|
||||
/* Ninth step: check whether we can actually apply this. */
|
||||
r = transaction_is_destructive(tr, mode, e);
|
||||
if (r < 0)
|
||||
return log_notice_errno(r, "Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
|
||||
return log_notice_errno(r, "Requested transaction contradicts existing jobs: %s",
|
||||
bus_error_message(e, r));
|
||||
|
||||
/* Tenth step: apply changes */
|
||||
/* Tenth step: apply changes. */
|
||||
r = transaction_apply(tr, m, mode, affected_jobs);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to apply transaction: %m");
|
||||
@ -819,9 +795,8 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b
|
||||
assert(tr);
|
||||
assert(unit);
|
||||
|
||||
/* Looks for an existing prospective job and returns that. If
|
||||
* it doesn't exist it is created and added to the prospective
|
||||
* jobs list. */
|
||||
/* Looks for an existing prospective job and returns that. If it doesn't exist it is created and
|
||||
* added to the prospective jobs list. */
|
||||
|
||||
f = hashmap_get(tr->jobs, unit);
|
||||
|
||||
@ -932,7 +907,7 @@ static JobType job_type_propagate_stop_graceful(Job *j) {
|
||||
|
||||
case JOB_STOP:
|
||||
case JOB_RESTART:
|
||||
/* Nothing to worry about, an appropriate job is in-place */
|
||||
/* Nothing to worry about, an appropriate job is in-place. */
|
||||
return JOB_NOP;
|
||||
|
||||
case JOB_START:
|
||||
@ -942,7 +917,7 @@ static JobType job_type_propagate_stop_graceful(Job *j) {
|
||||
type = JOB_RESTART;
|
||||
break;
|
||||
|
||||
default: /* We don't care about others */
|
||||
default: /* We don't care about others. */
|
||||
;
|
||||
|
||||
}
|
||||
@ -970,16 +945,17 @@ int transaction_add_job_and_dependencies(
|
||||
|
||||
/* Before adding jobs for this unit, let's ensure that its state has been loaded. This matters when
|
||||
* jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()). This way, we
|
||||
* "recursively" coldplug units, ensuring that we do not look at state of not-yet-coldplugged
|
||||
* units. */
|
||||
* "recursively" coldplug units, ensuring that we do not look at state of not-yet-coldplugged units. */
|
||||
if (MANAGER_IS_RELOADING(unit->manager))
|
||||
unit_coldplug(unit);
|
||||
|
||||
if (by)
|
||||
log_trace("Pulling in %s/%s from %s/%s", unit->id, job_type_to_string(type), by->unit->id, job_type_to_string(by->type));
|
||||
log_trace("Pulling in %s/%s from %s/%s",
|
||||
unit->id, job_type_to_string(type),
|
||||
by->unit->id, job_type_to_string(by->type));
|
||||
|
||||
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
|
||||
* temporarily. */
|
||||
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should
|
||||
* only be set temporarily. */
|
||||
if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
|
||||
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
|
||||
|
||||
@ -992,8 +968,8 @@ int transaction_add_job_and_dependencies(
|
||||
* again — even if the cache is current, it might have been updated in a different context
|
||||
* before we had a chance to retry loading this particular unit.
|
||||
*
|
||||
* Given building up the transaction is a synchronous operation, attempt
|
||||
* to load the unit immediately. */
|
||||
* Given building up the transaction is a synchronous operation, attempt to load the unit
|
||||
* immediately. */
|
||||
if (manager_unit_cache_should_retry_load(unit)) {
|
||||
assert(unit->load_state == UNIT_NOT_FOUND);
|
||||
unit->load_state = UNIT_STUB;
|
||||
@ -1013,7 +989,7 @@ int transaction_add_job_and_dependencies(
|
||||
job_type_to_string(type), unit->id);
|
||||
|
||||
if (type == JOB_START) {
|
||||
/* The hard concurrency limit for slice units we already enforce when a job is enqueued */
|
||||
/* The hard concurrency limit for slice units we already enforce when a job is enqueued. */
|
||||
Slice *slice = SLICE(UNIT_GET_SLICE(unit));
|
||||
if (slice && slice_concurrency_hard_max_reached(slice, unit))
|
||||
return sd_bus_error_setf(
|
||||
@ -1139,8 +1115,8 @@ int transaction_add_job_and_dependencies(
|
||||
}
|
||||
|
||||
/* Process UNIT_ATOM_PROPAGATE_STOP_GRACEFUL (PropagatesStopTo=) units. We need to wait until
|
||||
* all other dependencies are processed, i.e. we're the anchor job or already in the recursion
|
||||
* that handles it. */
|
||||
* all other dependencies are processed, i.e. we're the anchor job or already in the
|
||||
* recursion that handles it. */
|
||||
if (!by || FLAGS_SET(flags, TRANSACTION_PROCESS_PROPAGATE_STOP_GRACEFUL))
|
||||
UNIT_FOREACH_DEPENDENCY_SAFE(dep, job->unit, UNIT_ATOM_PROPAGATE_STOP_GRACEFUL) {
|
||||
JobType nt;
|
||||
@ -1165,7 +1141,7 @@ int transaction_add_job_and_dependencies(
|
||||
if (type == JOB_RELOAD)
|
||||
transaction_add_propagate_reload_jobs(tr, job->unit, job, flags & TRANSACTION_IGNORE_ORDER);
|
||||
|
||||
/* JOB_VERIFY_ACTIVE requires no dependency handling */
|
||||
/* JOB_VERIFY_ACTIVE requires no dependency handling. */
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1204,11 +1180,11 @@ int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
|
||||
Unit *o;
|
||||
|
||||
/* Ignore aliases */
|
||||
/* Ignore aliases. */
|
||||
if (u->id != k)
|
||||
continue;
|
||||
|
||||
/* No need to stop inactive units */
|
||||
/* No need to stop inactive units. */
|
||||
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
|
||||
continue;
|
||||
|
||||
@ -1243,7 +1219,7 @@ int transaction_add_triggering_jobs(Transaction *tr, Unit *u) {
|
||||
UNIT_FOREACH_DEPENDENCY_SAFE(trigger, u, UNIT_ATOM_TRIGGERED_BY) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
|
||||
|
||||
/* No need to stop inactive jobs */
|
||||
/* No need to stop inactive jobs. */
|
||||
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(trigger)) && !trigger->job)
|
||||
continue;
|
||||
|
||||
@ -1259,7 +1235,7 @@ int transaction_add_triggering_jobs(Transaction *tr, Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Transaction *transaction_new(bool irreversible) {
|
||||
Transaction* transaction_new(bool irreversible) {
|
||||
Transaction *tr;
|
||||
|
||||
tr = new0(Transaction, 1);
|
||||
@ -1275,7 +1251,7 @@ Transaction *transaction_new(bool irreversible) {
|
||||
return tr;
|
||||
}
|
||||
|
||||
Transaction *transaction_free(Transaction *tr) {
|
||||
Transaction* transaction_free(Transaction *tr) {
|
||||
if (!tr)
|
||||
return NULL;
|
||||
|
||||
@ -1285,7 +1261,7 @@ Transaction *transaction_free(Transaction *tr) {
|
||||
return mfree(tr);
|
||||
}
|
||||
|
||||
Transaction *transaction_abort_and_free(Transaction *tr) {
|
||||
Transaction* transaction_abort_and_free(Transaction *tr) {
|
||||
if (!tr)
|
||||
return NULL;
|
||||
|
||||
|
@ -144,15 +144,15 @@
|
||||
#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
|
||||
#define UNIQ __COUNTER__
|
||||
|
||||
/* Note that this works differently from pthread_once(): this macro does
|
||||
* not synchronize code execution, i.e. code that is run conditionalized
|
||||
* on this macro will run concurrently to all other code conditionalized
|
||||
* the same way, there's no ordering or completion enforced. */
|
||||
/* The macro is true when the code block is called first time, and is false for the second and later times.
|
||||
* Note that this works differently from pthread_once(): this macro does not synchronize code execution, i.e.
|
||||
* code that is run conditionalized on this macro will run concurrently to all other code conditionalized the
|
||||
* same way, there's no ordering or completion enforced. */
|
||||
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
!__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
})
|
||||
|
||||
#define U64_KB UINT64_C(1024)
|
||||
|
@ -1829,9 +1829,15 @@ static int acquire_updated_home_record(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (arg_recovery_key) {
|
||||
r = identity_add_recovery_key(&json);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If the user supplied a full record, then add in lastChange, but do not override. Otherwise always
|
||||
* override. */
|
||||
r = update_last_change(&json, arg_pkcs11_token_uri || arg_fido2_device, !arg_identity);
|
||||
r = update_last_change(&json, arg_pkcs11_token_uri || arg_fido2_device || arg_recovery_key, !arg_identity);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -45,6 +45,7 @@ typedef struct ProgressInfo {
|
||||
uint64_t size;
|
||||
bool started;
|
||||
bool logged_incomplete;
|
||||
uint64_t bps;
|
||||
} ProgressInfo;
|
||||
|
||||
static void progress_info_free(ProgressInfo *p) {
|
||||
@ -72,8 +73,10 @@ static void progress_show(ProgressInfo *p) {
|
||||
|
||||
if (p->size == 0)
|
||||
log_info("Copying tree, currently at '%s'...", p->path);
|
||||
else
|
||||
else if (p->bps == UINT64_MAX)
|
||||
log_info("Copying tree, currently at '%s' (@%s)...", p->path, FORMAT_BYTES(p->size));
|
||||
else
|
||||
log_info("Copying tree, currently at '%s' (@%s, %s/s)...", p->path, FORMAT_BYTES(p->size), FORMAT_BYTES(p->bps));
|
||||
}
|
||||
|
||||
static int progress_path(const char *path, const struct stat *st, void *userdata) {
|
||||
@ -90,12 +93,13 @@ static int progress_path(const char *path, const struct stat *st, void *userdata
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int progress_bytes(uint64_t nbytes, void *userdata) {
|
||||
static int progress_bytes(uint64_t nbytes, uint64_t bps, void *userdata) {
|
||||
ProgressInfo *p = ASSERT_PTR(userdata);
|
||||
|
||||
assert(p->size != UINT64_MAX);
|
||||
|
||||
p->size += nbytes;
|
||||
p->bps = bps;
|
||||
|
||||
progress_show(p);
|
||||
return 0;
|
||||
@ -103,7 +107,7 @@ static int progress_bytes(uint64_t nbytes, void *userdata) {
|
||||
|
||||
static int import_fs(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(rm_rf_subvolume_and_freep) char *temp_path = NULL;
|
||||
_cleanup_(progress_info_free) ProgressInfo progress = {};
|
||||
_cleanup_(progress_info_free) ProgressInfo progress = { .bps = UINT64_MAX };
|
||||
_cleanup_free_ char *l = NULL, *final_path = NULL;
|
||||
const char *path = NULL, *local = NULL, *dest = NULL;
|
||||
_cleanup_close_ int open_fd = -EBADF;
|
||||
|
@ -274,7 +274,7 @@ static int help(void) {
|
||||
" --show-cursor Print the cursor after all the entries\n"
|
||||
" --utc Express time in Coordinated Universal Time (UTC)\n"
|
||||
" -x --catalog Add message explanations where available\n"
|
||||
" --no-hostname Suppress output of hostname field\n"
|
||||
" -W --no-hostname Suppress output of hostname field\n"
|
||||
" --no-full Ellipsize fields\n"
|
||||
" -a --all Show all fields, including long and unprintable\n"
|
||||
" -f --follow Follow the journal\n"
|
||||
@ -367,7 +367,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_VACUUM_SIZE,
|
||||
ARG_VACUUM_FILES,
|
||||
ARG_VACUUM_TIME,
|
||||
ARG_NO_HOSTNAME,
|
||||
ARG_OUTPUT_FIELDS,
|
||||
ARG_NAMESPACE,
|
||||
ARG_LIST_NAMESPACES,
|
||||
@ -441,7 +440,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
|
||||
{ "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
|
||||
{ "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
|
||||
{ "no-hostname", no_argument, NULL, ARG_NO_HOSTNAME },
|
||||
{ "no-hostname", no_argument, NULL, 'W' },
|
||||
{ "output-fields", required_argument, NULL, ARG_OUTPUT_FIELDS },
|
||||
{ "namespace", required_argument, NULL, ARG_NAMESPACE },
|
||||
{ "list-namespaces", no_argument, NULL, ARG_LIST_NAMESPACES },
|
||||
@ -454,7 +453,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:g:c:S:U:t:T:u:INF:xrM:i:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:g:c:S:U:t:T:u:INF:xrM:i:W", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
@ -907,7 +906,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_action = ACTION_LIST_FIELD_NAMES;
|
||||
break;
|
||||
|
||||
case ARG_NO_HOSTNAME:
|
||||
case 'W':
|
||||
arg_no_hostname = true;
|
||||
break;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "device-internal.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
@ -25,14 +26,17 @@
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
TEST(mdio_bus) {
|
||||
int r;
|
||||
|
||||
/* For issue #37711 */
|
||||
|
||||
if (getuid() != 0)
|
||||
return (void) log_tests_skipped("not running as root");
|
||||
if (getuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0)
|
||||
return (void) log_tests_skipped("Not privileged");
|
||||
if (running_in_chroot() > 0)
|
||||
return (void) log_tests_skipped("Running in chroot");
|
||||
|
||||
ASSERT_OK(r = safe_fork("(mdio_bus)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL));
|
||||
if (r == 0) {
|
||||
|
@ -1968,16 +1968,9 @@ _public_ int sd_event_add_memory_pressure(
|
||||
|
||||
/* By default we want to watch memory pressure on the local cgroup, but we'll fall back on
|
||||
* the system wide pressure if for some reason we cannot (which could be: memory controller
|
||||
* not delegated to us, or PSI simply not available in the kernel). On legacy cgroupv1 we'll
|
||||
* only use the system-wide logic. */
|
||||
r = cg_all_unified();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
watch = "/proc/pressure/memory";
|
||||
else {
|
||||
_cleanup_free_ char *cg = NULL;
|
||||
* not delegated to us, or PSI simply not available in the kernel). */
|
||||
|
||||
_cleanup_free_ char *cg = NULL;
|
||||
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1988,7 +1981,6 @@ _public_ int sd_event_add_memory_pressure(
|
||||
|
||||
watch = w;
|
||||
watch_fallback = "/proc/pressure/memory";
|
||||
}
|
||||
|
||||
/* Android uses three levels in its userspace low memory killer logic:
|
||||
* some 70000 1000000
|
||||
|
@ -4,31 +4,42 @@
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
GetInfo,
|
||||
SD_VARLINK_FIELD_COMMENT("String identifying the vendor of this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(vendor, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("String identifying the product implementing this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(product, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Version string of this product"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(version, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Web URL pointing to additional information about this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(url, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("List of interfaces implemented by this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(interfaces, SD_VARLINK_STRING, SD_VARLINK_ARRAY));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
GetInterfaceDescription,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of interface to query interface description of"),
|
||||
SD_VARLINK_DEFINE_INPUT(interface, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Interface description in Varlink IDL format"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(description, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
InterfaceNotFound,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of interface that was called but does not exist"),
|
||||
SD_VARLINK_DEFINE_FIELD(interface, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
MethodNotFound,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of method that was called but does not exist"),
|
||||
SD_VARLINK_DEFINE_FIELD(method, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
MethodNotImplemented,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of method that was called but is not implemented."),
|
||||
SD_VARLINK_DEFINE_FIELD(method, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
InvalidParameter,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of the invalid parameter"),
|
||||
SD_VARLINK_DEFINE_FIELD(parameter, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(PermissionDenied);
|
||||
@ -39,11 +50,20 @@ static SD_VARLINK_DEFINE_ERROR(ExpectedMore);
|
||||
SD_VARLINK_DEFINE_INTERFACE(
|
||||
org_varlink_service,
|
||||
"org.varlink.service",
|
||||
SD_VARLINK_INTERFACE_COMMENT("General Varlink service interface"),
|
||||
SD_VARLINK_SYMBOL_COMMENT("Get service meta information"),
|
||||
&vl_method_GetInfo,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Get description of an implemented interface in Varlink IDL format"),
|
||||
&vl_method_GetInterfaceDescription,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if a method is called on an unknown interface"),
|
||||
&vl_error_InterfaceNotFound,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if an unknown method is called on an known interface"),
|
||||
&vl_error_MethodNotFound,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if an method is called that is known but not implemented"),
|
||||
&vl_error_MethodNotImplemented,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if a method is called with an invalid parameter"),
|
||||
&vl_error_InvalidParameter,
|
||||
SD_VARLINK_SYMBOL_COMMENT("General permission error"),
|
||||
&vl_error_PermissionDenied,
|
||||
SD_VARLINK_SYMBOL_COMMENT("A method was called with the 'more' flag off, but it may only be called with the flag turned on"),
|
||||
&vl_error_ExpectedMore);
|
||||
|
@ -268,7 +268,7 @@ WireGuardPeer.PresharedKey, config_parse_wireguard_peer_key,
|
||||
WireGuardPeer.PresharedKeyFile, config_parse_wireguard_peer_key_file, 0, 0
|
||||
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
|
||||
WireGuardPeer.RouteTable, config_parse_wireguard_peer_route_table, 0, 0
|
||||
WireGuardPeer.RouteMetric, config_parse_wireguard_peer_route_priority,0, 0
|
||||
WireGuardPeer.RouteMetric, config_parse_wireguard_peer_route_priority, 0, 0
|
||||
Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id)
|
||||
Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent)
|
||||
BatmanAdvanced.Aggregation, config_parse_bool, 0, offsetof(BatmanAdvanced, aggregation)
|
||||
|
@ -511,11 +511,11 @@ CAKE.RTTSec, config_parse_cake_rtt,
|
||||
CAKE.AckFilter, config_parse_cake_ack_filter, QDISC_KIND_CAKE, 0
|
||||
ControlledDelay.Parent, config_parse_qdisc_parent, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.Handle, config_parse_qdisc_handle, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.PacketLimit, config_parse_controlled_delay_u32, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.TargetSec, config_parse_controlled_delay_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.IntervalSec, config_parse_controlled_delay_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.CEThresholdSec, config_parse_controlled_delay_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.ECN, config_parse_controlled_delay_bool, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.PacketLimit, config_parse_codel_u32, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.TargetSec, config_parse_codel_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.IntervalSec, config_parse_codel_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.CEThresholdSec, config_parse_codel_usec, QDISC_KIND_CODEL, 0
|
||||
ControlledDelay.ECN, config_parse_codel_bool, QDISC_KIND_CODEL, 0
|
||||
DeficitRoundRobinScheduler.Parent, config_parse_qdisc_parent, QDISC_KIND_DRR, 0
|
||||
DeficitRoundRobinScheduler.Handle, config_parse_qdisc_handle, QDISC_KIND_DRR, 0
|
||||
DeficitRoundRobinSchedulerClass.Parent, config_parse_tclass_parent, TCLASS_KIND_DRR, 0
|
||||
@ -539,86 +539,86 @@ QuickFairQueueing.Parent, config_parse_qdisc_parent,
|
||||
QuickFairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.Parent, config_parse_tclass_parent, TCLASS_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.ClassId, config_parse_tclass_classid, TCLASS_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.Weight, config_parse_quick_fair_queueing_weight, TCLASS_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.MaxPacketBytes, config_parse_quick_fair_queueing_max_packet, TCLASS_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.Weight, config_parse_qfq_weight, TCLASS_KIND_QFQ, 0
|
||||
QuickFairQueueingClass.MaxPacketBytes, config_parse_qfq_max_packet, TCLASS_KIND_QFQ, 0
|
||||
FairQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_FQ, 0
|
||||
FairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_FQ, 0
|
||||
FairQueueing.PacketLimit, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.FlowLimit, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.QuantumBytes, config_parse_fair_queueing_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.InitialQuantumBytes, config_parse_fair_queueing_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.MaximumRate, config_parse_fair_queueing_max_rate, QDISC_KIND_FQ, 0
|
||||
FairQueueing.Buckets, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.OrphanMask, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.Pacing, config_parse_fair_queueing_bool, QDISC_KIND_FQ, 0
|
||||
FairQueueing.CEThresholdSec, config_parse_fair_queueing_usec, QDISC_KIND_FQ, 0
|
||||
FairQueueing.PacketLimit, config_parse_fq_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.FlowLimit, config_parse_fq_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.QuantumBytes, config_parse_fq_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.InitialQuantumBytes, config_parse_fq_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.MaximumRate, config_parse_fq_max_rate, QDISC_KIND_FQ, 0
|
||||
FairQueueing.Buckets, config_parse_fq_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.OrphanMask, config_parse_fq_u32, QDISC_KIND_FQ, 0
|
||||
FairQueueing.Pacing, config_parse_fq_bool, QDISC_KIND_FQ, 0
|
||||
FairQueueing.CEThresholdSec, config_parse_fq_usec, QDISC_KIND_FQ, 0
|
||||
FairQueueingControlledDelay.Parent, config_parse_qdisc_parent, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.Handle, config_parse_qdisc_handle, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.PacketLimit, config_parse_fair_queueing_controlled_delay_u32, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.MemoryLimitBytes, config_parse_fair_queueing_controlled_delay_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.Flows, config_parse_fair_queueing_controlled_delay_u32, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.QuantumBytes, config_parse_fair_queueing_controlled_delay_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.TargetSec, config_parse_fair_queueing_controlled_delay_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.IntervalSec, config_parse_fair_queueing_controlled_delay_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.CEThresholdSec, config_parse_fair_queueing_controlled_delay_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.ECN, config_parse_fair_queueing_controlled_delay_bool, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.PacketLimit, config_parse_fq_codel_u32, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.MemoryLimitBytes, config_parse_fq_codel_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.Flows, config_parse_fq_codel_u32, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.QuantumBytes, config_parse_fq_codel_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.TargetSec, config_parse_fq_codel_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.IntervalSec, config_parse_fq_codel_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.CEThresholdSec, config_parse_fq_codel_usec, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.ECN, config_parse_fq_codel_bool, QDISC_KIND_FQ_CODEL, 0
|
||||
FlowQueuePIE.Parent, config_parse_qdisc_parent, QDISC_KIND_FQ_PIE, 0
|
||||
FlowQueuePIE.Handle, config_parse_qdisc_handle, QDISC_KIND_FQ_PIE, 0
|
||||
FlowQueuePIE.PacketLimit, config_parse_fq_pie_packet_limit, QDISC_KIND_FQ_PIE, 0
|
||||
GenericRandomEarlyDetection.Parent, config_parse_qdisc_parent, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.Handle, config_parse_qdisc_handle, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.VirtualQueues, config_parse_generic_random_early_detection_u32, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.DefaultVirtualQueue, config_parse_generic_random_early_detection_u32, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.GenericRIO, config_parse_generic_random_early_detection_bool, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.VirtualQueues, config_parse_gred_u32, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.DefaultVirtualQueue, config_parse_gred_u32, QDISC_KIND_GRED, 0
|
||||
GenericRandomEarlyDetection.GenericRIO, config_parse_gred_bool, QDISC_KIND_GRED, 0
|
||||
HeavyHitterFilter.Parent, config_parse_qdisc_parent, QDISC_KIND_HHF, 0
|
||||
HeavyHitterFilter.Handle, config_parse_qdisc_handle, QDISC_KIND_HHF, 0
|
||||
HeavyHitterFilter.PacketLimit, config_parse_heavy_hitter_filter_packet_limit, QDISC_KIND_HHF, 0
|
||||
HeavyHitterFilter.PacketLimit, config_parse_hhf_packet_limit, QDISC_KIND_HHF, 0
|
||||
HierarchyTokenBucket.Parent, config_parse_qdisc_parent, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucket.Handle, config_parse_qdisc_handle, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucket.DefaultClass, config_parse_hierarchy_token_bucket_default_class, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucket.RateToQuantum, config_parse_hierarchy_token_bucket_u32, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucket.DefaultClass, config_parse_htb_default_class, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucket.RateToQuantum, config_parse_htb_u32, QDISC_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.Parent, config_parse_tclass_parent, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.ClassId, config_parse_tclass_classid, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.Priority, config_parse_hierarchy_token_bucket_class_u32, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.QuantumBytes, config_parse_hierarchy_token_bucket_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.MTUBytes, config_parse_hierarchy_token_bucket_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.OverheadBytes, config_parse_hierarchy_token_bucket_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.Rate, config_parse_hierarchy_token_bucket_class_rate, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.CeilRate, config_parse_hierarchy_token_bucket_class_rate, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.BufferBytes, config_parse_hierarchy_token_bucket_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.CeilBufferBytes, config_parse_hierarchy_token_bucket_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.Priority, config_parse_htb_class_u32, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.QuantumBytes, config_parse_htb_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.MTUBytes, config_parse_htb_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.OverheadBytes, config_parse_htb_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.Rate, config_parse_htb_class_rate, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.CeilRate, config_parse_htb_class_rate, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.BufferBytes, config_parse_htb_class_size, TCLASS_KIND_HTB, 0
|
||||
HierarchyTokenBucketClass.CeilBufferBytes, config_parse_htb_class_size, TCLASS_KIND_HTB, 0
|
||||
ClassfulMultiQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_MQ, 0
|
||||
ClassfulMultiQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_MQ, 0
|
||||
BandMultiQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_MULTIQ, 0
|
||||
BandMultiQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_MULTIQ, 0
|
||||
NetworkEmulator.Parent, config_parse_qdisc_parent, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.Handle, config_parse_qdisc_handle, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DelaySec, config_parse_network_emulator_delay, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DelayJitterSec, config_parse_network_emulator_delay, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.LossRate, config_parse_network_emulator_rate, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DuplicateRate, config_parse_network_emulator_rate, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.PacketLimit, config_parse_network_emulator_packet_limit, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DelaySec, config_parse_netem_delay, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DelayJitterSec, config_parse_netem_delay, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.LossRate, config_parse_netem_rate, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.DuplicateRate, config_parse_netem_rate, QDISC_KIND_NETEM, 0
|
||||
NetworkEmulator.PacketLimit, config_parse_netem_packet_limit, QDISC_KIND_NETEM, 0
|
||||
PIE.Parent, config_parse_qdisc_parent, QDISC_KIND_PIE, 0
|
||||
PIE.Handle, config_parse_qdisc_handle, QDISC_KIND_PIE, 0
|
||||
PIE.PacketLimit, config_parse_pie_packet_limit, QDISC_KIND_PIE, 0
|
||||
StochasticFairBlue.Parent, config_parse_qdisc_parent, QDISC_KIND_SFB, 0
|
||||
StochasticFairBlue.Handle, config_parse_qdisc_handle, QDISC_KIND_SFB, 0
|
||||
StochasticFairBlue.PacketLimit, config_parse_stochastic_fair_blue_u32, QDISC_KIND_SFB, 0
|
||||
StochasticFairBlue.PacketLimit, config_parse_sfb_u32, QDISC_KIND_SFB, 0
|
||||
StochasticFairnessQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_SFQ, 0
|
||||
StochasticFairnessQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_SFQ, 0
|
||||
StochasticFairnessQueueing.PerturbPeriodSec, config_parse_stochastic_fairness_queueing_perturb_period, QDISC_KIND_SFQ, 0
|
||||
StochasticFairnessQueueing.PerturbPeriodSec, config_parse_sfq_perturb_period, QDISC_KIND_SFQ, 0
|
||||
TokenBucketFilter.Parent, config_parse_qdisc_parent, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.Handle, config_parse_qdisc_handle, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.Rate, config_parse_token_bucket_filter_rate, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.BurstBytes, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LimitBytes, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.MTUBytes, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.MPUBytes, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.PeakRate, config_parse_token_bucket_filter_rate, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LatencySec, config_parse_token_bucket_filter_latency, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.Rate, config_parse_tbf_rate, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.BurstBytes, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LimitBytes, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.MTUBytes, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.MPUBytes, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.PeakRate, config_parse_tbf_rate, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LatencySec, config_parse_tbf_latency, QDISC_KIND_TBF, 0
|
||||
TrivialLinkEqualizer.Parent, config_parse_qdisc_parent, QDISC_KIND_TEQL, 0
|
||||
TrivialLinkEqualizer.Handle, config_parse_qdisc_handle, QDISC_KIND_TEQL, 0
|
||||
TrivialLinkEqualizer.Id, config_parse_trivial_link_equalizer_id, QDISC_KIND_TEQL, 0
|
||||
TrivialLinkEqualizer.Id, config_parse_teql_id, QDISC_KIND_TEQL, 0
|
||||
/* backwards compatibility: do not add new entries to this section */
|
||||
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
|
||||
Network.IPv6Token, config_parse_address_generation_type, 0, offsetof(Network, ndisc_tokens)
|
||||
@ -672,14 +672,14 @@ IPv6AcceptRA.DenyList, config_parse_in_addr_prefixes,
|
||||
IPv6AcceptRA.BlackList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
|
||||
IPv6AcceptRA.UseICMP6RateLimit, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||
TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_network_emulator_delay, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_network_emulator_delay, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorLossRate, config_parse_network_emulator_rate, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_network_emulator_rate, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_network_emulator_packet_limit, 0, 0
|
||||
FairQueueing.Quantum, config_parse_fair_queueing_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.InitialQuantum, config_parse_fair_queueing_size, QDISC_KIND_FQ, 0
|
||||
FairQueueingControlledDelay.MemoryLimit, config_parse_fair_queueing_controlled_delay_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.Quantum, config_parse_fair_queueing_controlled_delay_size, QDISC_KIND_FQ_CODEL, 0
|
||||
TokenBucketFilter.Burst, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LimitSize, config_parse_token_bucket_filter_size, QDISC_KIND_TBF, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_netem_delay, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_netem_delay, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorLossRate, config_parse_netem_rate, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_netem_rate, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_netem_packet_limit, 0, 0
|
||||
FairQueueing.Quantum, config_parse_fq_size, QDISC_KIND_FQ, 0
|
||||
FairQueueing.InitialQuantum, config_parse_fq_size, QDISC_KIND_FQ, 0
|
||||
FairQueueingControlledDelay.MemoryLimit, config_parse_fq_codel_size, QDISC_KIND_FQ_CODEL, 0
|
||||
FairQueueingControlledDelay.Quantum, config_parse_fq_codel_size, QDISC_KIND_FQ_CODEL, 0
|
||||
TokenBucketFilter.Burst, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
TokenBucketFilter.LimitSize, config_parse_tbf_size, QDISC_KIND_TBF, 0
|
||||
|
@ -74,7 +74,7 @@ static int controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_me
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_controlled_delay_u32(
|
||||
int config_parse_codel_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -126,7 +126,7 @@ int config_parse_controlled_delay_u32(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_controlled_delay_usec(
|
||||
int config_parse_codel_usec(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -191,7 +191,7 @@ int config_parse_controlled_delay_usec(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_controlled_delay_bool(
|
||||
int config_parse_codel_bool(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -17,6 +17,6 @@ typedef struct ControlledDelay {
|
||||
DEFINE_QDISC_CAST(CODEL, ControlledDelay);
|
||||
extern const QDiscVTable codel_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_controlled_delay_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_controlled_delay_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_controlled_delay_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_codel_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_codel_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_codel_bool);
|
||||
|
@ -94,7 +94,7 @@ static int fair_queueing_controlled_delay_fill_message(Link *link, QDisc *qdisc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_controlled_delay_u32(
|
||||
int config_parse_fq_codel_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -154,7 +154,7 @@ int config_parse_fair_queueing_controlled_delay_u32(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_controlled_delay_usec(
|
||||
int config_parse_fq_codel_usec(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -219,7 +219,7 @@ int config_parse_fair_queueing_controlled_delay_usec(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_controlled_delay_bool(
|
||||
int config_parse_fq_codel_bool(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -264,7 +264,7 @@ int config_parse_fair_queueing_controlled_delay_bool(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_controlled_delay_size(
|
||||
int config_parse_fq_codel_size(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -21,7 +21,7 @@ typedef struct FairQueueingControlledDelay {
|
||||
DEFINE_QDISC_CAST(FQ_CODEL, FairQueueingControlledDelay);
|
||||
extern const QDiscVTable fq_codel_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_controlled_delay_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_controlled_delay_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_controlled_delay_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_controlled_delay_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_codel_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_codel_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_codel_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_codel_size);
|
||||
|
@ -103,7 +103,7 @@ static int fair_queueing_fill_message(Link *link, QDisc *qdisc, sd_netlink_messa
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_u32(
|
||||
int config_parse_fq_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -167,7 +167,7 @@ int config_parse_fair_queueing_u32(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_size(
|
||||
int config_parse_fq_size(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -235,7 +235,7 @@ int config_parse_fair_queueing_size(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_bool(
|
||||
int config_parse_fq_bool(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -281,7 +281,7 @@ int config_parse_fair_queueing_bool(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_usec(
|
||||
int config_parse_fq_usec(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -341,7 +341,7 @@ int config_parse_fair_queueing_usec(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_fair_queueing_max_rate(
|
||||
int config_parse_fq_max_rate(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -22,8 +22,8 @@ typedef struct FairQueueing {
|
||||
DEFINE_QDISC_CAST(FQ, FairQueueing);
|
||||
extern const QDiscVTable fq_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fair_queueing_max_rate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_usec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fq_max_rate);
|
||||
|
@ -65,7 +65,7 @@ static int generic_random_early_detection_verify(QDisc *qdisc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_generic_random_early_detection_u32(
|
||||
int config_parse_gred_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -131,7 +131,7 @@ int config_parse_generic_random_early_detection_u32(
|
||||
|
||||
return 0;
|
||||
}
|
||||
int config_parse_generic_random_early_detection_bool(
|
||||
int config_parse_gred_bool(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -16,5 +16,5 @@ typedef struct GenericRandomEarlyDetection {
|
||||
DEFINE_QDISC_CAST(GRED, GenericRandomEarlyDetection);
|
||||
extern const QDiscVTable gred_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_generic_random_early_detection_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_generic_random_early_detection_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_gred_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_gred_bool);
|
||||
|
@ -37,7 +37,7 @@ static int heavy_hitter_filter_fill_message(Link *link, QDisc *qdisc, sd_netlink
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_heavy_hitter_filter_packet_limit(
|
||||
int config_parse_hhf_packet_limit(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -14,4 +14,4 @@ typedef struct HeavyHitterFilter {
|
||||
DEFINE_QDISC_CAST(HHF, HeavyHitterFilter);
|
||||
extern const QDiscVTable hhf_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_heavy_hitter_filter_packet_limit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hhf_packet_limit);
|
||||
|
@ -45,7 +45,7 @@ static int hierarchy_token_bucket_fill_message(Link *link, QDisc *qdisc, sd_netl
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hierarchy_token_bucket_default_class(
|
||||
int config_parse_htb_default_class(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -97,7 +97,7 @@ int config_parse_hierarchy_token_bucket_default_class(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hierarchy_token_bucket_u32(
|
||||
int config_parse_htb_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -239,7 +239,7 @@ static int hierarchy_token_bucket_class_fill_message(Link *link, TClass *tclass,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hierarchy_token_bucket_class_u32(
|
||||
int config_parse_htb_class_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -292,7 +292,7 @@ int config_parse_hierarchy_token_bucket_class_u32(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hierarchy_token_bucket_class_size(
|
||||
int config_parse_htb_class_size(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -375,7 +375,7 @@ int config_parse_hierarchy_token_bucket_class_size(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hierarchy_token_bucket_class_rate(
|
||||
int config_parse_htb_class_rate(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -15,8 +15,8 @@ typedef struct HierarchyTokenBucket {
|
||||
DEFINE_QDISC_CAST(HTB, HierarchyTokenBucket);
|
||||
extern const QDiscVTable htb_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hierarchy_token_bucket_default_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hierarchy_token_bucket_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_htb_default_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_htb_u32);
|
||||
|
||||
typedef struct HierarchyTokenBucketClass {
|
||||
TClass meta;
|
||||
@ -34,6 +34,6 @@ typedef struct HierarchyTokenBucketClass {
|
||||
DEFINE_TCLASS_CAST(HTB, HierarchyTokenBucketClass);
|
||||
extern const TClassVTable htb_tclass_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hierarchy_token_bucket_class_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hierarchy_token_bucket_class_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hierarchy_token_bucket_class_rate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_htb_class_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_htb_class_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_htb_class_rate);
|
||||
|
@ -48,7 +48,7 @@ static int network_emulator_fill_message(Link *link, QDisc *qdisc, sd_netlink_me
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_network_emulator_delay(
|
||||
int config_parse_netem_delay(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -109,7 +109,7 @@ int config_parse_network_emulator_delay(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_network_emulator_rate(
|
||||
int config_parse_netem_rate(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -169,7 +169,7 @@ int config_parse_network_emulator_rate(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_network_emulator_packet_limit(
|
||||
int config_parse_netem_packet_limit(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -19,6 +19,6 @@ typedef struct NetworkEmulator {
|
||||
DEFINE_QDISC_CAST(NETEM, NetworkEmulator);
|
||||
extern const QDiscVTable netem_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_network_emulator_delay);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_network_emulator_rate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_network_emulator_packet_limit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_netem_delay);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_netem_rate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_netem_packet_limit);
|
||||
|
@ -52,7 +52,7 @@ static int quick_fair_queueing_class_fill_message(Link *link, TClass *tclass, sd
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_quick_fair_queueing_weight(
|
||||
int config_parse_qfq_weight(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -112,7 +112,7 @@ int config_parse_quick_fair_queueing_weight(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_quick_fair_queueing_max_packet(
|
||||
int config_parse_qfq_max_packet(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -23,5 +23,5 @@ typedef struct QuickFairQueueingClass {
|
||||
DEFINE_TCLASS_CAST(QFQ, QuickFairQueueingClass);
|
||||
extern const TClassVTable qfq_tclass_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_weight);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_max_packet);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_qfq_weight);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_qfq_max_packet);
|
||||
|
@ -47,7 +47,7 @@ static int stochastic_fair_blue_fill_message(Link *link, QDisc *qdisc, sd_netlin
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_stochastic_fair_blue_u32(
|
||||
int config_parse_sfb_u32(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -14,4 +14,4 @@ typedef struct StochasticFairBlue {
|
||||
DEFINE_QDISC_CAST(SFB, StochasticFairBlue);
|
||||
extern const QDiscVTable sfb_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_stochastic_fair_blue_u32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sfb_u32);
|
||||
|
@ -30,7 +30,7 @@ static int stochastic_fairness_queueing_fill_message(Link *link, QDisc *qdisc, s
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_stochastic_fairness_queueing_perturb_period(
|
||||
int config_parse_sfq_perturb_period(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -14,4 +14,4 @@ typedef struct StochasticFairnessQueueing {
|
||||
DEFINE_QDISC_CAST(SFQ, StochasticFairnessQueueing);
|
||||
extern const QDiscVTable sfq_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_stochastic_fairness_queueing_perturb_period);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sfq_perturb_period);
|
||||
|
@ -108,7 +108,7 @@ static int token_bucket_filter_fill_message(Link *link, QDisc *qdisc, sd_netlink
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_token_bucket_filter_size(
|
||||
int config_parse_tbf_size(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -181,7 +181,7 @@ int config_parse_token_bucket_filter_size(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_token_bucket_filter_rate(
|
||||
int config_parse_tbf_rate(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -242,7 +242,7 @@ int config_parse_token_bucket_filter_rate(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_token_bucket_filter_latency(
|
||||
int config_parse_tbf_latency(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -20,6 +20,6 @@ typedef struct TokenBucketFilter {
|
||||
DEFINE_QDISC_CAST(TBF, TokenBucketFilter);
|
||||
extern const QDiscVTable tbf_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_token_bucket_filter_latency);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_token_bucket_filter_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_token_bucket_filter_rate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tbf_latency);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tbf_size);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tbf_rate);
|
||||
|
@ -41,7 +41,7 @@ const QDiscVTable teql_vtable = {
|
||||
.is_ready = trivial_link_equalizer_is_ready,
|
||||
};
|
||||
|
||||
int config_parse_trivial_link_equalizer_id(
|
||||
int config_parse_teql_id(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -13,4 +13,4 @@ typedef struct TrivialLinkEqualizer {
|
||||
DEFINE_QDISC_CAST(TEQL, TrivialLinkEqualizer);
|
||||
extern const QDiscVTable teql_vtable;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_trivial_link_equalizer_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_teql_id);
|
||||
|
@ -5377,7 +5377,7 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int progress_bytes(uint64_t n_bytes, void *userdata) {
|
||||
static int progress_bytes(uint64_t n_bytes, uint64_t bps, void *userdata) {
|
||||
Partition *p = ASSERT_PTR(userdata);
|
||||
unsigned percent;
|
||||
|
||||
@ -5395,6 +5395,17 @@ static int progress_bytes(uint64_t n_bytes, void *userdata) {
|
||||
if (!ratelimit_below(&p->progress_ratelimit))
|
||||
return 0;
|
||||
|
||||
if (bps != UINT64_MAX)
|
||||
(void) draw_progress_barf(
|
||||
percent,
|
||||
"%s %s %s %s/%s %s/s",
|
||||
strna(p->copy_blocks_path),
|
||||
glyph(GLYPH_ARROW_RIGHT),
|
||||
strna(p->definition_path),
|
||||
FORMAT_BYTES(p->copy_blocks_done),
|
||||
FORMAT_BYTES(p->copy_blocks_size),
|
||||
FORMAT_BYTES(bps));
|
||||
else
|
||||
(void) draw_progress_barf(
|
||||
percent,
|
||||
"%s %s %s %s/%s",
|
||||
|
@ -18,9 +18,9 @@ struct ConfigPerfItem;
|
||||
%struct-type
|
||||
%includes
|
||||
%%
|
||||
Service.Name, config_parse_dnssd_registered_service_name, 0, 0
|
||||
Service.Type, config_parse_dnssd_registered_service_type, 0, 0
|
||||
Service.SubType, config_parse_dnssd_registered_service_subtype, 0, 0
|
||||
Service.Name, config_parse_dnssd_name, 0, 0
|
||||
Service.Type, config_parse_dnssd_type, 0, 0
|
||||
Service.SubType, config_parse_dnssd_subtype, 0, 0
|
||||
Service.Port, config_parse_ip_port, 0, offsetof(DnssdRegisteredService, port)
|
||||
Service.Priority, config_parse_uint16, 0, offsetof(DnssdRegisteredService, priority)
|
||||
Service.Weight, config_parse_uint16, 0, offsetof(DnssdRegisteredService, weight)
|
||||
|
@ -413,7 +413,7 @@ int dnssd_signal_conflict(Manager *manager, const char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dnssd_registered_service_name(
|
||||
int config_parse_dnssd_name(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -467,7 +467,7 @@ int config_parse_dnssd_registered_service_name(
|
||||
return free_and_strdup_warn(&s->name_template, rvalue);
|
||||
}
|
||||
|
||||
int config_parse_dnssd_registered_service_type(
|
||||
int config_parse_dnssd_type(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -503,7 +503,7 @@ int config_parse_dnssd_registered_service_type(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dnssd_registered_service_subtype(
|
||||
int config_parse_dnssd_subtype(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
@ -63,7 +63,7 @@ int dnssd_signal_conflict(Manager *manager, const char *name);
|
||||
|
||||
const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_registered_service_name);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_registered_service_subtype);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_registered_service_type);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_name);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_subtype);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_type);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
|
||||
|
@ -26,12 +26,13 @@
|
||||
#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "selinux-util.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "set.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "sync-util.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "umask-util.h"
|
||||
#include "user-util.h"
|
||||
@ -263,6 +264,10 @@ int copy_bytes_full(
|
||||
}
|
||||
}
|
||||
|
||||
usec_t start_timestamp = USEC_INFINITY;
|
||||
if (progress)
|
||||
start_timestamp = now(CLOCK_MONOTONIC);
|
||||
|
||||
for (;;) {
|
||||
ssize_t n;
|
||||
size_t m;
|
||||
@ -511,7 +516,13 @@ int copy_bytes_full(
|
||||
try_sendfile = false;
|
||||
|
||||
if (progress) {
|
||||
r = progress(n, userdata);
|
||||
usec_t t = now(CLOCK_MONOTONIC);
|
||||
usec_t d = usec_sub_unsigned(t, start_timestamp);
|
||||
uint64_t bps = UINT64_MAX;
|
||||
if (d > USEC_PER_SEC * 3U)
|
||||
bps = (uint64_t) (copied_total / ((double) d / USEC_PER_SEC));
|
||||
|
||||
r = progress(n, bps, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ typedef enum DenyType {
|
||||
_DENY_TYPE_INVALID = -EINVAL,
|
||||
} DenyType;
|
||||
|
||||
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);
|
||||
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, uint64_t bytes_per_second, void *userdata);
|
||||
typedef int (*copy_progress_path_t)(const char *path, const struct stat *st, void *userdata);
|
||||
|
||||
int copy_file_fd_at_full(int dir_fdf, const char *from, int to, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata);
|
||||
|
@ -393,6 +393,8 @@ static int make_credential_host_secret(
|
||||
if (fd < 0)
|
||||
return log_debug_errno(fd, "Failed to create temporary file for credential host secret: %m");
|
||||
|
||||
CLEANUP_TMPFILE_AT(dfd, t);
|
||||
|
||||
r = chattr_secret(fd, 0);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to set file attributes for secrets file, ignoring: %m");
|
||||
@ -405,29 +407,22 @@ static int make_credential_host_secret(
|
||||
|
||||
r = crypto_random_bytes(buf.data, sizeof(buf.data));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
r = loop_write(fd, &buf, sizeof(buf));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
if (fchmod(fd, 0400) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fsync(fd) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
if (fchmod(fd, 0400) < 0)
|
||||
return -errno;
|
||||
|
||||
warn_not_encrypted(fd, flags, dirname, fn);
|
||||
|
||||
r = link_tmpfile_at(fd, dfd, t, fn, LINK_TMPFILE_SYNC);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to link host key into place: %m");
|
||||
goto fail;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to link host key into place: %m");
|
||||
|
||||
t = mfree(t); /* disarm CLEANUP_TMPFILE_AT() */
|
||||
|
||||
if (ret) {
|
||||
void *copy;
|
||||
@ -440,12 +435,6 @@ static int make_credential_host_secret(
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (t && unlinkat(dfd, t, 0) < 0)
|
||||
log_debug_errno(errno, "Failed to remove temporary credential key: %m");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret) {
|
||||
|
@ -89,7 +89,10 @@ static DLSYM_PROTOTYPE(elf_version) = NULL;
|
||||
static DLSYM_PROTOTYPE(gelf_getphdr) = NULL;
|
||||
static DLSYM_PROTOTYPE(gelf_getnote) = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_dw(void) {
|
||||
#if HAVE_ELFUTILS
|
||||
int r;
|
||||
|
||||
ELF_NOTE_DLOPEN("dw",
|
||||
@ -138,9 +141,13 @@ int dlopen_dw(void) {
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int dlopen_elf(void) {
|
||||
#if HAVE_ELFUTILS
|
||||
int r;
|
||||
|
||||
ELF_NOTE_DLOPEN("elf",
|
||||
@ -165,8 +172,13 @@ int dlopen_elf(void) {
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_ELFUTILS
|
||||
|
||||
typedef struct StackContext {
|
||||
MemStream m;
|
||||
Dwfl *dwfl;
|
||||
|
@ -3,10 +3,8 @@
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
#if HAVE_ELFUTILS
|
||||
int dlopen_dw(void);
|
||||
int dlopen_elf(void);
|
||||
#endif
|
||||
|
||||
/* Parse an ELF object in a forked process, so that errors while iterating over
|
||||
* untrusted and potentially malicious data do not propagate to the main caller's process.
|
||||
|
@ -71,7 +71,10 @@ static void fido_log_propagate_handler(const char *s) {
|
||||
log_debug("libfido2: %s", strempty(s));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_libfido2(void) {
|
||||
#if HAVE_LIBFIDO2
|
||||
int r;
|
||||
|
||||
ELF_NOTE_DLOPEN("fido2",
|
||||
@ -136,8 +139,13 @@ int dlopen_libfido2(void) {
|
||||
sym_fido_set_log_handler(fido_log_propagate_handler);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
|
||||
static int verify_features(
|
||||
fido_dev_t *d,
|
||||
const char *path,
|
||||
|
@ -16,6 +16,8 @@ typedef enum Fido2EnrollFlags {
|
||||
_FIDO2ENROLL_TYPE_INVALID = -EINVAL,
|
||||
} Fido2EnrollFlags;
|
||||
|
||||
int dlopen_libfido2(void);
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
#include <fido.h>
|
||||
|
||||
@ -70,8 +72,6 @@ extern DLSYM_PROTOTYPE(fido_init);
|
||||
extern DLSYM_PROTOTYPE(fido_set_log_handler);
|
||||
extern DLSYM_PROTOTYPE(fido_strerr);
|
||||
|
||||
int dlopen_libfido2(void);
|
||||
|
||||
static inline void fido_cbor_info_free_wrapper(fido_cbor_info_t **p) {
|
||||
if (*p)
|
||||
sym_fido_cbor_info_free(p);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "password-quality-util.h"
|
||||
#include "password-quality-util-passwdqc.h"
|
||||
#include "strv.h"
|
||||
|
||||
#if HAVE_PASSWDQC
|
||||
@ -18,22 +18,6 @@ DLSYM_PROTOTYPE(passwdqc_params_free) = NULL;
|
||||
DLSYM_PROTOTYPE(passwdqc_check) = NULL;
|
||||
DLSYM_PROTOTYPE(passwdqc_random) = NULL;
|
||||
|
||||
int dlopen_passwdqc(void) {
|
||||
ELF_NOTE_DLOPEN("passwdqc",
|
||||
"Support for password quality checks",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
"libpasswdqc.so.1");
|
||||
|
||||
return dlopen_many_sym_or_warn(
|
||||
&passwdqc_dl, "libpasswdqc.so.1", LOG_DEBUG,
|
||||
DLSYM_ARG(passwdqc_params_reset),
|
||||
DLSYM_ARG(passwdqc_params_load),
|
||||
DLSYM_ARG(passwdqc_params_parse),
|
||||
DLSYM_ARG(passwdqc_params_free),
|
||||
DLSYM_ARG(passwdqc_check),
|
||||
DLSYM_ARG(passwdqc_random));
|
||||
}
|
||||
|
||||
static int pwqc_allocate_context(passwdqc_params_t **ret) {
|
||||
|
||||
_cleanup_(sym_passwdqc_params_freep) passwdqc_params_t *params = NULL;
|
||||
@ -144,3 +128,23 @@ int check_password_quality(
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_passwdqc(void) {
|
||||
#if HAVE_PASSWDQC
|
||||
ELF_NOTE_DLOPEN("passwdqc",
|
||||
"Support for password quality checks",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
"libpasswdqc.so.1");
|
||||
|
||||
return dlopen_many_sym_or_warn(
|
||||
&passwdqc_dl, "libpasswdqc.so.1", LOG_DEBUG,
|
||||
DLSYM_ARG(passwdqc_params_reset),
|
||||
DLSYM_ARG(passwdqc_params_load),
|
||||
DLSYM_ARG(passwdqc_params_parse),
|
||||
DLSYM_ARG(passwdqc_params_free),
|
||||
DLSYM_ARG(passwdqc_check),
|
||||
DLSYM_ARG(passwdqc_random));
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
@ -15,11 +15,11 @@ extern DLSYM_PROTOTYPE(passwdqc_params_free);
|
||||
extern DLSYM_PROTOTYPE(passwdqc_check);
|
||||
extern DLSYM_PROTOTYPE(passwdqc_random);
|
||||
|
||||
int dlopen_passwdqc(void);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(passwdqc_params_t*, sym_passwdqc_params_free, NULL);
|
||||
|
||||
int suggest_passwords(void);
|
||||
int check_password_quality(const char *password, const char *old, const char *username, char **ret_error);
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_passwdqc(void);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "log.h"
|
||||
#include "password-quality-util.h"
|
||||
#include "password-quality-util-pwquality.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
@ -24,24 +25,6 @@ DLSYM_PROTOTYPE(pwquality_read_config) = NULL;
|
||||
DLSYM_PROTOTYPE(pwquality_set_int_value) = NULL;
|
||||
DLSYM_PROTOTYPE(pwquality_strerror) = NULL;
|
||||
|
||||
int dlopen_pwquality(void) {
|
||||
ELF_NOTE_DLOPEN("pwquality",
|
||||
"Support for password quality checks",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
"libpwquality.so.1");
|
||||
|
||||
return dlopen_many_sym_or_warn(
|
||||
&pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
|
||||
DLSYM_ARG(pwquality_check),
|
||||
DLSYM_ARG(pwquality_default_settings),
|
||||
DLSYM_ARG(pwquality_free_settings),
|
||||
DLSYM_ARG(pwquality_generate),
|
||||
DLSYM_ARG(pwquality_get_str_value),
|
||||
DLSYM_ARG(pwquality_read_config),
|
||||
DLSYM_ARG(pwquality_set_int_value),
|
||||
DLSYM_ARG(pwquality_strerror));
|
||||
}
|
||||
|
||||
static void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {
|
||||
char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
|
||||
const char *path;
|
||||
@ -163,3 +146,25 @@ int check_password_quality(const char *password, const char *old, const char *us
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_pwquality(void) {
|
||||
#if HAVE_PWQUALITY
|
||||
ELF_NOTE_DLOPEN("pwquality",
|
||||
"Support for password quality checks",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
"libpwquality.so.1");
|
||||
|
||||
return dlopen_many_sym_or_warn(
|
||||
&pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
|
||||
DLSYM_ARG(pwquality_check),
|
||||
DLSYM_ARG(pwquality_default_settings),
|
||||
DLSYM_ARG(pwquality_free_settings),
|
||||
DLSYM_ARG(pwquality_generate),
|
||||
DLSYM_ARG(pwquality_get_str_value),
|
||||
DLSYM_ARG(pwquality_read_config),
|
||||
DLSYM_ARG(pwquality_set_int_value),
|
||||
DLSYM_ARG(pwquality_strerror));
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ extern DLSYM_PROTOTYPE(pwquality_read_config);
|
||||
extern DLSYM_PROTOTYPE(pwquality_set_int_value);
|
||||
extern DLSYM_PROTOTYPE(pwquality_strerror);
|
||||
|
||||
int dlopen_pwquality(void);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pwquality_settings_t*, sym_pwquality_free_settings, NULL);
|
||||
|
||||
int suggest_passwords(void);
|
||||
int check_password_quality(const char *password, const char *old, const char *username, char **ret_error);
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_pwquality(void);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
#include <qrencode.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ansi-color.h"
|
||||
@ -18,12 +19,15 @@
|
||||
#define UNICODE_LOWER_HALF_BLOCK UTF8("▄")
|
||||
#define UNICODE_UPPER_HALF_BLOCK UTF8("▀")
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
static void *qrcode_dl = NULL;
|
||||
|
||||
static DLSYM_PROTOTYPE(QRcode_encodeString) = NULL;
|
||||
static DLSYM_PROTOTYPE(QRcode_free) = NULL;
|
||||
#endif
|
||||
|
||||
int dlopen_qrencode(void) {
|
||||
#if HAVE_QRENCODE
|
||||
int r;
|
||||
|
||||
ELF_NOTE_DLOPEN("qrencode",
|
||||
@ -41,8 +45,13 @@ int dlopen_qrencode(void) {
|
||||
}
|
||||
|
||||
return r;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
|
||||
static void print_border(FILE *output, unsigned width, unsigned row, unsigned column) {
|
||||
assert(output);
|
||||
assert(width);
|
||||
@ -176,6 +185,8 @@ static void write_qrcode(FILE *output, QRcode *qr, unsigned row, unsigned column
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(QRcode*, sym_QRcode_free, NULL);
|
||||
|
||||
#endif
|
||||
|
||||
int print_qrcode_full(
|
||||
FILE *out,
|
||||
const char *header,
|
||||
@ -186,6 +197,7 @@ int print_qrcode_full(
|
||||
unsigned tty_height,
|
||||
bool check_tty) {
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
int r;
|
||||
|
||||
/* If this is not a UTF-8 system or ANSI colors aren't supported/disabled don't print any QR
|
||||
@ -235,5 +247,7 @@ int print_qrcode_full(
|
||||
fputc('\n', out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
int dlopen_qrencode(void);
|
||||
|
||||
int print_qrcode_full(
|
||||
FILE *out,
|
||||
const char *header,
|
||||
@ -15,19 +12,8 @@ int print_qrcode_full(
|
||||
unsigned tty_width,
|
||||
unsigned tty_height,
|
||||
bool check_tty);
|
||||
#else
|
||||
static inline int print_qrcode_full(
|
||||
FILE *out,
|
||||
const char *header,
|
||||
const char *string,
|
||||
unsigned row,
|
||||
unsigned column,
|
||||
unsigned tty_width,
|
||||
unsigned tty_height,
|
||||
bool check_tty) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
int dlopen_qrencode(void);
|
||||
|
||||
static inline int print_qrcode(FILE *out, const char *header, const char *string) {
|
||||
return print_qrcode_full(out, header, string, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, true);
|
||||
|
@ -217,7 +217,10 @@ static int dlopen_tpm2_mu(void) {
|
||||
DLSYM_ARG(Tss2_MU_UINT32_Marshal));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_tpm2(void) {
|
||||
#if HAVE_TPM2
|
||||
int r;
|
||||
|
||||
r = dlopen_tpm2_esys();
|
||||
@ -233,8 +236,13 @@ int dlopen_tpm2(void) {
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_TPM2
|
||||
|
||||
void Esys_Freep(void *p) {
|
||||
assert(p);
|
||||
|
||||
|
@ -39,14 +39,14 @@ static inline bool TPM2_PCR_MASK_VALID(uint32_t pcr_mask) {
|
||||
|
||||
#define TPM2_N_HASH_ALGORITHMS 4U
|
||||
|
||||
int dlopen_tpm2(void);
|
||||
|
||||
#if HAVE_TPM2
|
||||
|
||||
#include <tss2/tss2_esys.h> /* IWYU pragma: export */
|
||||
#include <tss2/tss2_mu.h> /* IWYU pragma: export */
|
||||
#include <tss2/tss2_rc.h> /* IWYU pragma: export */
|
||||
|
||||
int dlopen_tpm2(void);
|
||||
|
||||
typedef struct Tpm2Context {
|
||||
unsigned n_ref;
|
||||
|
||||
|
@ -127,11 +127,12 @@ static int read_definitions(
|
||||
const char *suffix,
|
||||
const char *node) {
|
||||
|
||||
_cleanup_strv_free_ char **files = NULL;
|
||||
ConfFile **files = NULL;
|
||||
Transfer **transfers = NULL, **disabled = NULL;
|
||||
size_t n_transfers = 0, n_disabled = 0;
|
||||
size_t n_files = 0, n_transfers = 0, n_disabled = 0;
|
||||
int r;
|
||||
|
||||
CLEANUP_ARRAY(files, n_files, conf_file_free_many);
|
||||
CLEANUP_ARRAY(transfers, n_transfers, free_transfers);
|
||||
CLEANUP_ARRAY(disabled, n_disabled, free_transfers);
|
||||
|
||||
@ -139,19 +140,20 @@ static int read_definitions(
|
||||
assert(dirs);
|
||||
assert(suffix);
|
||||
|
||||
r = conf_files_list_strv(&files, suffix, arg_root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, dirs);
|
||||
r = conf_files_list_strv_full(suffix, arg_root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, dirs, &files, &n_files);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enumerate sysupdate.d/*%s definitions: %m", suffix);
|
||||
|
||||
STRV_FOREACH(p, files) {
|
||||
FOREACH_ARRAY(i, files, n_files) {
|
||||
_cleanup_(transfer_freep) Transfer *t = NULL;
|
||||
Transfer **appended;
|
||||
ConfFile *e = *i;
|
||||
|
||||
t = transfer_new(c);
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
r = transfer_read_definition(t, *p, dirs, c->features);
|
||||
r = transfer_read_definition(t, e->result, dirs, c->features);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -176,7 +178,7 @@ static int read_definitions(
|
||||
}
|
||||
|
||||
static int context_read_definitions(Context *c, const char* node, bool requires_enabled_transfers) {
|
||||
_cleanup_strv_free_ char **dirs = NULL, **files = NULL;
|
||||
_cleanup_strv_free_ char **dirs = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
@ -205,22 +207,26 @@ static int context_read_definitions(Context *c, const char* node, bool requires_
|
||||
if (!dirs)
|
||||
return log_oom();
|
||||
|
||||
r = conf_files_list_strv(&files,
|
||||
".feature",
|
||||
arg_root,
|
||||
ConfFile **files = NULL;
|
||||
size_t n_files = 0;
|
||||
|
||||
CLEANUP_ARRAY(files, n_files, conf_file_free_many);
|
||||
|
||||
r = conf_files_list_strv_full(".feature", arg_root,
|
||||
CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED,
|
||||
(const char**) dirs);
|
||||
(const char**) dirs, &files, &n_files);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enumerate sysupdate.d/*.feature definitions: %m");
|
||||
|
||||
STRV_FOREACH(p, files) {
|
||||
FOREACH_ARRAY(i, files, n_files) {
|
||||
_cleanup_(feature_unrefp) Feature *f = NULL;
|
||||
ConfFile *e = *i;
|
||||
|
||||
f = feature_new();
|
||||
if (!f)
|
||||
return log_oom();
|
||||
|
||||
r = feature_read_definition(f, *p, (const char**) dirs);
|
||||
r = feature_read_definition(f, e->result, (const char**) dirs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1542,8 +1548,6 @@ static int verb_components(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
|
||||
_cleanup_set_free_ Set *names = NULL;
|
||||
_cleanup_free_ char **z = NULL; /* We use simple free() rather than strv_free() here, since set_free() will free the strings for us */
|
||||
char **l = CONF_PATHS_STRV("");
|
||||
bool has_default_component = false;
|
||||
int r;
|
||||
|
||||
@ -1553,65 +1557,49 @@ static int verb_components(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
ConfFile **directories = NULL;
|
||||
size_t n_directories = 0;
|
||||
|
||||
r = chase_and_opendir(*i, arg_root, CHASE_PREFIX_ROOT, &p, &d);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
CLEANUP_ARRAY(directories, n_directories, conf_file_free_many);
|
||||
|
||||
r = conf_files_list_strv_full(".d", arg_root, CONF_FILES_DIRECTORY, (const char * const *) CONF_PATHS_STRV(""), &directories, &n_directories);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open directory '%s': %m", *i);
|
||||
return log_error_errno(r, "Failed to enumerate directories: %m");
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
struct dirent *de;
|
||||
const char *e, *a;
|
||||
FOREACH_ARRAY(i, directories, n_directories) {
|
||||
ConfFile *e = *i;
|
||||
|
||||
de = readdir_ensure_type(d);
|
||||
if (!de) {
|
||||
if (errno != 0)
|
||||
return log_error_errno(errno, "Failed to enumerate directory '%s': %m", p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (de->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
if (streq(de->d_name, "sysupdate.d")) {
|
||||
if (streq(e->name, "sysupdate.d")) {
|
||||
has_default_component = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
e = startswith(de->d_name, "sysupdate.");
|
||||
if (!e)
|
||||
const char *s = startswith(e->name, "sysupdate.");
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
a = endswith(e, ".d");
|
||||
const char *a = endswith(s, ".d");
|
||||
if (!a)
|
||||
continue;
|
||||
|
||||
n = strndup(e, a - e);
|
||||
_cleanup_free_ char *n = strndup(s, a - s);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
r = component_name_valid(n);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to validate component name: %m");
|
||||
return log_error_errno(r, "Unable to validate component name '%s': %m", n);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = set_ensure_consume(&names, &string_hash_ops_free, TAKE_PTR(n));
|
||||
r = set_ensure_put(&names, &string_hash_ops_free, n);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return log_error_errno(r, "Failed to add component to set: %m");
|
||||
}
|
||||
return log_error_errno(r, "Failed to add component '%s' to set: %m", n);
|
||||
TAKE_PTR(n);
|
||||
}
|
||||
|
||||
z = set_get_strv(names);
|
||||
/* We use simple free() rather than strv_free() here, since set_free() will free the strings for us */
|
||||
_cleanup_free_ char **z = set_get_strv(names);
|
||||
if (!z)
|
||||
return log_oom();
|
||||
|
||||
|
@ -68,8 +68,8 @@ simple_tests += files(
|
||||
'test-bus-unit-util.c',
|
||||
'test-bus-util.c',
|
||||
'test-calendarspec.c',
|
||||
'test-cgroup-setup.c',
|
||||
'test-cgroup-util.c',
|
||||
'test-cgroup.c',
|
||||
'test-chase.c',
|
||||
'test-chid.c',
|
||||
'test-clock.c',
|
||||
|
@ -3,43 +3,11 @@
|
||||
#include "cgroup-setup.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(cg_split_spec) {
|
||||
char *c, *p;
|
||||
|
||||
ASSERT_OK_ZERO(cg_split_spec("foobar:/", &c, &p));
|
||||
ASSERT_STREQ(c, "foobar");
|
||||
ASSERT_STREQ(p, "/");
|
||||
c = mfree(c);
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_OK_ZERO(cg_split_spec("foobar:", &c, &p));
|
||||
c = mfree(c);
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_FAIL(cg_split_spec("foobar:asdfd", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec(":///", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec(":", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec("", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec("fo/obar:/", &c, &p));
|
||||
|
||||
ASSERT_OK(cg_split_spec("/", &c, &p));
|
||||
ASSERT_NULL(c);
|
||||
ASSERT_STREQ(p, "/");
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_OK(cg_split_spec("foo", &c, &p));
|
||||
ASSERT_STREQ(c, "foo");
|
||||
ASSERT_NULL(p);
|
||||
c = mfree(c);
|
||||
}
|
||||
|
||||
TEST(cg_create) {
|
||||
int r;
|
||||
|
||||
@ -118,45 +86,4 @@ TEST(cg_create) {
|
||||
ASSERT_OK(cg_trim(test_b, true));
|
||||
}
|
||||
|
||||
TEST(id) {
|
||||
_cleanup_free_ char *p = NULL, *p2 = NULL;
|
||||
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
|
||||
uint64_t id, id2;
|
||||
int r;
|
||||
|
||||
r = cg_all_unified();
|
||||
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
|
||||
return (void) log_tests_skipped("cgroupfs is not mounted");
|
||||
if (r == 0)
|
||||
return (void) log_tests_skipped("skipping cgroupid test, not running in unified mode");
|
||||
ASSERT_OK_POSITIVE(r);
|
||||
|
||||
fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
|
||||
ASSERT_OK(fd);
|
||||
|
||||
ASSERT_OK(fd_get_path(fd, &p));
|
||||
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
|
||||
|
||||
ASSERT_OK(cg_fd_get_cgroupid(fd, &id));
|
||||
|
||||
fd2 = cg_cgroupid_open(fd, id);
|
||||
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(fd2))
|
||||
log_notice("Skipping open-by-cgroup-id test because lacking privs.");
|
||||
else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
|
||||
log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");
|
||||
else {
|
||||
ASSERT_OK(fd2);
|
||||
|
||||
ASSERT_OK(fd_get_path(fd2, &p2));
|
||||
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
|
||||
|
||||
ASSERT_OK(cg_fd_get_cgroupid(fd2, &id2));
|
||||
|
||||
ASSERT_EQ(id, id2);
|
||||
|
||||
ASSERT_OK_EQ(inode_same_at(fd, NULL, fd2, NULL, AT_EMPTY_PATH), true);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
@ -11,6 +11,7 @@
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "special.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
@ -334,6 +335,36 @@ TEST(controller_is_valid) {
|
||||
assert_se(!cg_controller_is_valid("tatü"));
|
||||
}
|
||||
|
||||
TEST(cg_split_spec) {
|
||||
char *c, *p;
|
||||
|
||||
ASSERT_OK_ZERO(cg_split_spec("foobar:/", &c, &p));
|
||||
ASSERT_STREQ(c, "foobar");
|
||||
ASSERT_STREQ(p, "/");
|
||||
c = mfree(c);
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_OK_ZERO(cg_split_spec("foobar:", &c, &p));
|
||||
c = mfree(c);
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_FAIL(cg_split_spec("foobar:asdfd", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec(":///", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec(":", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec("", &c, &p));
|
||||
ASSERT_FAIL(cg_split_spec("fo/obar:/", &c, &p));
|
||||
|
||||
ASSERT_OK(cg_split_spec("/", &c, &p));
|
||||
ASSERT_NULL(c);
|
||||
ASSERT_STREQ(p, "/");
|
||||
p = mfree(p);
|
||||
|
||||
ASSERT_OK(cg_split_spec("foo", &c, &p));
|
||||
ASSERT_STREQ(c, "foo");
|
||||
ASSERT_NULL(p);
|
||||
c = mfree(c);
|
||||
}
|
||||
|
||||
static void test_slice_to_path_one(const char *unit, const char *path, int error) {
|
||||
_cleanup_free_ char *ret = NULL;
|
||||
int r;
|
||||
@ -432,7 +463,7 @@ TEST(cg_get_keyed_attribute) {
|
||||
int r;
|
||||
|
||||
r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val);
|
||||
if (IN_SET(r, -ENOMEDIUM, -ENOENT) || ERRNO_IS_PRIVILEGE(r)) {
|
||||
if (r == -ENOMEDIUM || ERRNO_IS_PRIVILEGE(r)) {
|
||||
log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__);
|
||||
return;
|
||||
}
|
||||
@ -473,4 +504,45 @@ TEST(bfq_weight_conversion) {
|
||||
assert_se(BFQ_WEIGHT(10000) == 1000);
|
||||
}
|
||||
|
||||
TEST(cgroupid) {
|
||||
_cleanup_free_ char *p = NULL, *p2 = NULL;
|
||||
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
|
||||
uint64_t id, id2;
|
||||
int r;
|
||||
|
||||
r = cg_all_unified();
|
||||
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
|
||||
return (void) log_tests_skipped("cgroupfs is not mounted");
|
||||
if (r == 0)
|
||||
return (void) log_tests_skipped("skipping cgroupid test, not running in unified mode");
|
||||
ASSERT_OK_POSITIVE(r);
|
||||
|
||||
fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
|
||||
ASSERT_OK(fd);
|
||||
|
||||
ASSERT_OK(fd_get_path(fd, &p));
|
||||
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
|
||||
|
||||
ASSERT_OK(cg_fd_get_cgroupid(fd, &id));
|
||||
|
||||
fd2 = cg_cgroupid_open(fd, id);
|
||||
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(fd2))
|
||||
log_notice("Skipping open-by-cgroup-id test because lacking privs.");
|
||||
else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
|
||||
log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");
|
||||
else {
|
||||
ASSERT_OK(fd2);
|
||||
|
||||
ASSERT_OK(fd_get_path(fd2, &p2));
|
||||
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
|
||||
|
||||
ASSERT_OK(cg_fd_get_cgroupid(fd2, &id2));
|
||||
|
||||
ASSERT_EQ(id, id2);
|
||||
|
||||
ASSERT_OK_EQ(inode_same_at(fd, NULL, fd2, NULL, AT_EMPTY_PATH), true);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include "tests.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
#define ASSERT_DLOPEN(func, cond) \
|
||||
cond ? ASSERT_OK(func()) : ASSERT_ERROR(func(), EOPNOTSUPP)
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
@ -26,78 +29,25 @@ static int run(int argc, char **argv) {
|
||||
* where .so versions change and distributions update, but systemd doesn't have the new so names
|
||||
* around yet. */
|
||||
|
||||
#if HAVE_LIBIDN2 || HAVE_LIBIDN
|
||||
assert_se(dlopen_idn() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBCRYPTSETUP
|
||||
assert_se(dlopen_cryptsetup() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_PASSWDQC
|
||||
assert_se(dlopen_passwdqc() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_PWQUALITY
|
||||
assert_se(dlopen_pwquality() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_QRENCODE
|
||||
assert_se(dlopen_qrencode() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_TPM2
|
||||
assert_se(dlopen_tpm2() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
assert_se(dlopen_libfido2() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
assert_se(dlopen_bpf() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_ELFUTILS
|
||||
assert_se(dlopen_dw() >= 0);
|
||||
assert_se(dlopen_elf() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_PCRE2
|
||||
assert_se(dlopen_pcre2() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_P11KIT
|
||||
assert_se(dlopen_p11kit() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBARCHIVE
|
||||
assert_se(dlopen_libarchive() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LZ4
|
||||
assert_se(dlopen_lz4() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_ZSTD
|
||||
assert_se(dlopen_zstd() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_XZ
|
||||
assert_se(dlopen_lzma() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
assert_se(initialize_libgcrypt(/* secmem= */ false) >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_KMOD
|
||||
assert_se(dlopen_libkmod() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_APPARMOR
|
||||
assert_se(dlopen_libapparmor() >= 0);
|
||||
#endif
|
||||
ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2 || HAVE_LIBIDN);
|
||||
ASSERT_DLOPEN(dlopen_cryptsetup, HAVE_LIBCRYPTSETUP);
|
||||
ASSERT_DLOPEN(dlopen_passwdqc, HAVE_PASSWDQC);
|
||||
ASSERT_DLOPEN(dlopen_pwquality, HAVE_PWQUALITY);
|
||||
ASSERT_DLOPEN(dlopen_qrencode, HAVE_QRENCODE);
|
||||
ASSERT_DLOPEN(dlopen_tpm2, HAVE_TPM2);
|
||||
ASSERT_DLOPEN(dlopen_libfido2, HAVE_LIBFIDO2);
|
||||
ASSERT_DLOPEN(dlopen_bpf, HAVE_LIBBPF);
|
||||
ASSERT_DLOPEN(dlopen_dw, HAVE_ELFUTILS);
|
||||
ASSERT_DLOPEN(dlopen_elf, HAVE_ELFUTILS);
|
||||
ASSERT_DLOPEN(dlopen_pcre2, HAVE_PCRE2);
|
||||
ASSERT_DLOPEN(dlopen_p11kit, HAVE_P11KIT);
|
||||
ASSERT_DLOPEN(dlopen_libarchive, HAVE_LIBARCHIVE);
|
||||
ASSERT_DLOPEN(dlopen_lz4, HAVE_LZ4);
|
||||
ASSERT_DLOPEN(dlopen_zstd, HAVE_ZSTD);
|
||||
ASSERT_DLOPEN(dlopen_lzma, HAVE_XZ);
|
||||
ASSERT_DLOPEN(dlopen_gcrypt, HAVE_GCRYPT);
|
||||
ASSERT_DLOPEN(dlopen_libkmod, HAVE_KMOD);
|
||||
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1613,6 +1613,9 @@ static int intro(void) {
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0)
|
||||
return log_tests_skipped("not privileged");
|
||||
|
||||
if (running_in_chroot() > 0)
|
||||
return log_tests_skipped("running in chroot");
|
||||
|
||||
if (enter_cgroup_subroot(NULL) == -ENOMEDIUM)
|
||||
return log_tests_skipped("cgroupfs not available");
|
||||
|
||||
|
@ -42,6 +42,22 @@ static void test_file(void) {
|
||||
assert_se(startswith(__FILE__, RELATIVE_SOURCE_PATH "/"));
|
||||
}
|
||||
|
||||
static void test_log_once_impl(void) {
|
||||
log_once(LOG_INFO, "This should be logged in LOG_INFO at first, then in LOG_DEBUG later.");
|
||||
log_once(LOG_DEBUG, "This should be logged only once in LOG_DEBUG.");
|
||||
ASSERT_ERROR(log_once_errno(LOG_INFO, SYNTHETIC_ERRNO(ENOANO),
|
||||
"This should be logged with errno in LOG_INFO at first, then in LOG_DEBUG later: %m"),
|
||||
ENOANO);
|
||||
ASSERT_ERROR(log_once_errno(LOG_DEBUG, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"This should be logged only once with errno in LOG_DEBUG: %m"),
|
||||
EBADMSG);
|
||||
}
|
||||
|
||||
static void test_log_once(void) {
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
test_log_once_impl();
|
||||
}
|
||||
|
||||
static void test_log_struct(void) {
|
||||
log_struct(LOG_INFO,
|
||||
"MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),
|
||||
@ -233,6 +249,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN);
|
||||
|
||||
test_log_once();
|
||||
|
||||
for (int target = 0; target < _LOG_TARGET_MAX; target++) {
|
||||
log_set_target(target);
|
||||
log_open();
|
||||
|
@ -1102,4 +1102,20 @@ TEST(u64_multiply_safe) {
|
||||
assert_se(u64_multiply_safe(UINT64_MAX, UINT64_MAX) == 0);
|
||||
}
|
||||
|
||||
static void test_once_impl(void) {
|
||||
static unsigned count = 0;
|
||||
|
||||
if (ONCE) {
|
||||
log_info("This should be logged only once.");
|
||||
count++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST(once) {
|
||||
for (unsigned i = 0; i < 20; i++)
|
||||
test_once_impl();
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
@ -23,6 +23,23 @@
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
#define FORK_COMMON_FLAGS \
|
||||
(FORK_CLOSE_ALL_FDS | \
|
||||
FORK_RESET_SIGNALS | \
|
||||
FORK_DEATHSIG_SIGTERM | \
|
||||
FORK_LOG | \
|
||||
FORK_REOPEN_LOG | \
|
||||
FORK_WAIT | \
|
||||
FORK_NEW_MOUNTNS | \
|
||||
FORK_MOUNTNS_SLAVE)
|
||||
|
||||
#define CHECK_PRIV \
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) \
|
||||
return (void) log_tests_skipped("Not privileged"); \
|
||||
if (running_in_chroot() > 0) \
|
||||
return (void) log_tests_skipped("running in chroot");
|
||||
|
||||
TEST(mount_option_mangle) {
|
||||
char *opts = NULL;
|
||||
@ -132,11 +149,9 @@ TEST(mount_flags_to_string) {
|
||||
TEST(bind_remount_recursive) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *tmp = NULL;
|
||||
_cleanup_free_ char *subdir = NULL;
|
||||
int r;
|
||||
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
|
||||
(void) log_tests_skipped("not running privileged");
|
||||
return;
|
||||
}
|
||||
CHECK_PRIV;
|
||||
|
||||
assert_se(mkdtemp_malloc("/tmp/XXXXXX", &tmp) >= 0);
|
||||
subdir = path_join(tmp, "subdir");
|
||||
@ -144,15 +159,9 @@ TEST(bind_remount_recursive) {
|
||||
assert_se(mkdir(subdir, 0755) >= 0);
|
||||
|
||||
FOREACH_STRING(p, "/usr", "/sys", "/", tmp) {
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(bind-remount-recursive)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) { /* child */
|
||||
struct statvfs svfs;
|
||||
/* child */
|
||||
assert_se(detach_mount_namespace() >= 0);
|
||||
|
||||
/* Check that the subdir is writable (it must be because it's in /tmp) */
|
||||
assert_se(statvfs(subdir, &svfs) >= 0);
|
||||
@ -178,29 +187,18 @@ TEST(bind_remount_recursive) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("test-remount-rec", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(bind_remount_one) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
|
||||
(void) log_tests_skipped("not running privileged");
|
||||
return;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
CHECK_PRIV;
|
||||
|
||||
ASSERT_OK(r = safe_fork("(remount-one-with-mountinfo)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) { /* child */
|
||||
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
|
||||
|
||||
assert_se(detach_mount_namespace() >= 0);
|
||||
|
||||
assert_se(fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo) >= 0);
|
||||
|
||||
assert_se(bind_remount_one_with_mountinfo("/run", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0);
|
||||
@ -212,16 +210,8 @@ TEST(bind_remount_one) {
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("test-remount-one-with-mountinfo", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
|
||||
assert_se(detach_mount_namespace() >= 0);
|
||||
|
||||
ASSERT_OK(r = safe_fork("(remount-one)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) { /* child */
|
||||
assert_se(bind_remount_one("/run", MS_RDONLY, MS_RDONLY) >= 0);
|
||||
assert_se(bind_remount_one("/run", MS_NOEXEC, MS_RDONLY|MS_NOEXEC) >= 0);
|
||||
assert_se(bind_remount_one("/proc/idontexist", MS_RDONLY, MS_RDONLY) == -ENOENT);
|
||||
@ -230,8 +220,6 @@ TEST(bind_remount_one) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(make_mount_point_inode) {
|
||||
@ -283,10 +271,7 @@ TEST(make_mount_switch_root) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
|
||||
(void) log_tests_skipped("not running privileged");
|
||||
return;
|
||||
}
|
||||
CHECK_PRIV;
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
|
||||
|
||||
@ -305,18 +290,7 @@ TEST(make_mount_switch_root) {
|
||||
};
|
||||
|
||||
FOREACH_ELEMENT(i, table) {
|
||||
r = safe_fork("(switch-root)",
|
||||
FORK_RESET_SIGNALS |
|
||||
FORK_CLOSE_ALL_FDS |
|
||||
FORK_DEATHSIG_SIGTERM |
|
||||
FORK_WAIT |
|
||||
FORK_REOPEN_LOG |
|
||||
FORK_LOG |
|
||||
FORK_NEW_MOUNTNS |
|
||||
FORK_MOUNTNS_SLAVE,
|
||||
NULL);
|
||||
assert_se(r >= 0);
|
||||
|
||||
ASSERT_OK(r = safe_fork("(switch-root)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) {
|
||||
assert_se(make_mount_point(i->path) >= 0);
|
||||
assert_se(mount_switch_root_full(i->path, /* mount_propagation_flag= */ 0, i->force_ms_move) >= 0);
|
||||
@ -357,23 +331,10 @@ TEST(umount_recursive) {
|
||||
|
||||
int r;
|
||||
|
||||
CHECK_PRIV;
|
||||
|
||||
FOREACH_ELEMENT(t, test_table) {
|
||||
|
||||
r = safe_fork("(umount-rec)",
|
||||
FORK_RESET_SIGNALS |
|
||||
FORK_CLOSE_ALL_FDS |
|
||||
FORK_DEATHSIG_SIGTERM |
|
||||
FORK_WAIT |
|
||||
FORK_REOPEN_LOG |
|
||||
FORK_LOG |
|
||||
FORK_NEW_MOUNTNS |
|
||||
FORK_MOUNTNS_SLAVE,
|
||||
NULL);
|
||||
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(r))
|
||||
return (void) log_notice("Skipping umount_recursive() test, lacking privileges");
|
||||
|
||||
assert_se(r >= 0);
|
||||
ASSERT_OK(r = safe_fork("(umount-rec)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) { /* child */
|
||||
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
|
||||
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
|
||||
@ -422,10 +383,7 @@ TEST(fd_make_mount_point) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
|
||||
(void) log_tests_skipped("not running privileged");
|
||||
return;
|
||||
}
|
||||
CHECK_PRIV;
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
|
||||
|
||||
@ -433,18 +391,7 @@ TEST(fd_make_mount_point) {
|
||||
assert_se(s);
|
||||
assert_se(mkdir(s, 0700) >= 0);
|
||||
|
||||
r = safe_fork("(make_mount-point)",
|
||||
FORK_RESET_SIGNALS |
|
||||
FORK_CLOSE_ALL_FDS |
|
||||
FORK_DEATHSIG_SIGTERM |
|
||||
FORK_WAIT |
|
||||
FORK_REOPEN_LOG |
|
||||
FORK_LOG |
|
||||
FORK_NEW_MOUNTNS |
|
||||
FORK_MOUNTNS_SLAVE,
|
||||
NULL);
|
||||
assert_se(r >= 0);
|
||||
|
||||
ASSERT_OK(r = safe_fork("(make-mount-point)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) {
|
||||
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
|
||||
|
||||
@ -468,15 +415,18 @@ TEST(fd_make_mount_point) {
|
||||
|
||||
TEST(bind_mount_submounts) {
|
||||
_cleanup_(rmdir_and_freep) char *a = NULL, *b = NULL;
|
||||
_cleanup_free_ char *x = NULL;
|
||||
int r;
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &a) >= 0);
|
||||
r = mount_nofollow_verbose(LOG_INFO, "tmpfs", a, "tmpfs", 0, NULL);
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(r))
|
||||
return (void) log_tests_skipped("Skipping bind_mount_submounts() test, lacking privileges");
|
||||
CHECK_PRIV;
|
||||
|
||||
assert_se(r >= 0);
|
||||
assert_se(mkdtemp_malloc(NULL, &a) >= 0);
|
||||
assert_se(mkdtemp_malloc(NULL, &b) >= 0);
|
||||
|
||||
ASSERT_OK(r = safe_fork("(bind-mount-submounts)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) {
|
||||
char *x;
|
||||
|
||||
ASSERT_OK(mount_nofollow_verbose(LOG_INFO, "tmpfs", a, "tmpfs", 0, NULL));
|
||||
|
||||
assert_se(x = path_join(a, "foo"));
|
||||
assert_se(touch(x) >= 0);
|
||||
@ -500,7 +450,6 @@ TEST(bind_mount_submounts) {
|
||||
assert_se(touch(x) >= 0);
|
||||
free(x);
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &b) >= 0);
|
||||
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", b, "tmpfs", 0, NULL) >= 0);
|
||||
|
||||
assert_se(x = path_join(b, "x"));
|
||||
@ -531,9 +480,13 @@ TEST(bind_mount_submounts) {
|
||||
|
||||
assert_se(x = path_join(b, "y"));
|
||||
assert_se(path_is_mount_point(x) > 0);
|
||||
free(x);
|
||||
|
||||
assert_se(umount_recursive(a, 0) >= 0);
|
||||
assert_se(umount_recursive(b, 0) >= 0);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(path_is_network_fs_harder) {
|
||||
@ -553,26 +506,12 @@ TEST(path_is_network_fs_harder) {
|
||||
log_debug("path_is_network_fs_harder_at(root, %s) → %i: %s", q, r, r < 0 ? STRERROR(r) : yes_no(r));
|
||||
}
|
||||
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
|
||||
(void) log_tests_skipped("not running privileged");
|
||||
return;
|
||||
}
|
||||
CHECK_PRIV;
|
||||
|
||||
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
||||
assert_se(mkdtemp_malloc("/tmp/test-mount-util.path_is_network_fs_harder.XXXXXXX", &t) >= 0);
|
||||
|
||||
r = safe_fork("(make_mount-point)",
|
||||
FORK_RESET_SIGNALS |
|
||||
FORK_CLOSE_ALL_FDS |
|
||||
FORK_DEATHSIG_SIGTERM |
|
||||
FORK_WAIT |
|
||||
FORK_REOPEN_LOG |
|
||||
FORK_LOG |
|
||||
FORK_NEW_MOUNTNS |
|
||||
FORK_MOUNTNS_SLAVE,
|
||||
NULL);
|
||||
ASSERT_OK(r);
|
||||
|
||||
ASSERT_OK(r = safe_fork("(path-is-network-fs-harder)", FORK_COMMON_FLAGS, NULL));
|
||||
if (r == 0) {
|
||||
ASSERT_OK(mount_nofollow_verbose(LOG_INFO, "tmpfs", t, "tmpfs", 0, NULL));
|
||||
ASSERT_OK_ZERO(path_is_network_fs_harder(t));
|
||||
@ -587,7 +526,7 @@ TEST(path_is_network_fs_harder) {
|
||||
}
|
||||
|
||||
TEST(umountat) {
|
||||
int r;
|
||||
CHECK_PRIV;
|
||||
|
||||
_cleanup_(rm_rf_physical_and_freep) char *p = NULL;
|
||||
_cleanup_close_ int dfd = mkdtemp_open(NULL, O_CLOEXEC, &p);
|
||||
@ -597,11 +536,7 @@ TEST(umountat) {
|
||||
|
||||
_cleanup_free_ char *q = ASSERT_PTR(path_join(p, "foo"));
|
||||
|
||||
r = mount_nofollow_verbose(LOG_ERR, "tmpfs", q, "tmpfs", 0, NULL);
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(r))
|
||||
return (void) log_tests_skipped("not running privileged");
|
||||
|
||||
ASSERT_OK(r);
|
||||
ASSERT_OK(mount_nofollow_verbose(LOG_ERR, "tmpfs", q, "tmpfs", 0, NULL));
|
||||
ASSERT_OK(umountat_detach_verbose(LOG_ERR, dfd, "foo"));
|
||||
ASSERT_ERROR(umountat_detach_verbose(LOG_ERR, dfd, "foo"), EINVAL);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
static void test_mount_propagation_flag_one(const char *name, int ret, unsigned long expected) {
|
||||
unsigned long flags;
|
||||
@ -455,6 +456,12 @@ static int intro(void) {
|
||||
/* let's move into our own mount namespace with all propagation from the host turned off, so
|
||||
* that /proc/self/mountinfo is static and constant for the whole time our test runs. */
|
||||
|
||||
if (running_in_chroot() > 0) {
|
||||
/* We cannot remount file system with MS_PRIVATE when running in chroot. */
|
||||
log_notice("Running in chroot, proceeding in originating mount namespace.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNS) < 0) {
|
||||
if (!ERRNO_IS_PRIVILEGE(errno))
|
||||
return log_error_errno(errno, "Failed to detach mount namespace: %m");
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "locale-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
@ -655,7 +656,6 @@ TEST(safe_atoux64) {
|
||||
|
||||
TEST(safe_atod) {
|
||||
double d;
|
||||
char *e;
|
||||
|
||||
ASSERT_ERROR(safe_atod("junk", &d), EINVAL);
|
||||
|
||||
@ -663,39 +663,18 @@ TEST(safe_atod) {
|
||||
assert_se(fabs(d - 0.2244) < 0.000001);
|
||||
|
||||
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
|
||||
|
||||
errno = 0;
|
||||
strtod("0,5", &e);
|
||||
assert_se(*e == ',');
|
||||
|
||||
ASSERT_ERROR(safe_atod("", &d), EINVAL);
|
||||
|
||||
/* Check if this really is locale independent */
|
||||
if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
|
||||
_cleanup_(freelocalep) locale_t loc =
|
||||
newlocale(LC_NUMERIC_MASK, "de_DE.utf8", (locale_t) 0);
|
||||
if (!loc)
|
||||
return (void) log_tests_skipped_errno(errno, "locale de_DE.utf8 not found");
|
||||
|
||||
ASSERT_OK_ZERO(safe_atod("0.2244", &d));
|
||||
assert_se(fabs(d - 0.2244) < 0.000001);
|
||||
|
||||
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
|
||||
|
||||
errno = 0;
|
||||
assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
|
||||
|
||||
ASSERT_ERROR(safe_atod("", &d), EINVAL);
|
||||
}
|
||||
|
||||
/* And check again, reset */
|
||||
ASSERT_NOT_NULL(setlocale(LC_NUMERIC, "C"));
|
||||
|
||||
ASSERT_OK_ZERO(safe_atod("0.2244", &d));
|
||||
assert_se(fabs(d - 0.2244) < 0.000001);
|
||||
|
||||
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
|
||||
|
||||
errno = 0;
|
||||
strtod("0,5", &e);
|
||||
assert_se(*e == ',');
|
||||
|
||||
ASSERT_ERROR(safe_atod("", &d), EINVAL);
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,13 @@
|
||||
# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
|
||||
#endif
|
||||
|
||||
static bool have_seccomp_privs(void) {
|
||||
return geteuid() == 0 && have_effective_cap(CAP_SYS_ADMIN) > 0; /* If we are root but CAP_SYS_ADMIN we can't do caps (unless we also do NNP) */
|
||||
}
|
||||
#define CHECK_SECCOMP(refuse_container) \
|
||||
if (!is_seccomp_available()) \
|
||||
return (void) log_tests_skipped("Seccomp not available"); \
|
||||
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) \
|
||||
return (void) log_tests_skipped("Not privileged"); \
|
||||
if (refuse_container && detect_container() > 0) \
|
||||
return (void) log_tests_skipped("Running in container");
|
||||
|
||||
TEST(parse_syscall_and_errno) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
@ -166,17 +170,11 @@ TEST(syscall_filter_set_find) {
|
||||
}
|
||||
|
||||
TEST(filter_sets) {
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
int r;
|
||||
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
for (unsigned i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
|
||||
pid_t pid;
|
||||
|
||||
#if HAVE_VALGRIND_VALGRIND_H
|
||||
if (RUNNING_ON_VALGRIND && IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_BASIC_IO, SYSCALL_FILTER_SET_SIGNAL)) {
|
||||
@ -195,11 +193,9 @@ TEST(filter_sets) {
|
||||
|
||||
log_info("Testing %s", syscall_filter_sets[i].name);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) { /* Child? */
|
||||
int fd, r;
|
||||
ASSERT_OK(r = safe_fork("(filter_sets)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
int fd;
|
||||
|
||||
/* If we look at the default set (or one that includes it), allow-list instead of deny-list */
|
||||
if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT,
|
||||
@ -222,8 +218,6 @@ TEST(filter_sets) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,12 +257,10 @@ TEST(filter_sets_ordered) {
|
||||
TEST(restrict_namespace) {
|
||||
char *s = NULL;
|
||||
unsigned long ul;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!have_namespaces()) {
|
||||
log_notice("Testing without namespaces, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_namespaces())
|
||||
return (void) log_tests_skipped("Testing without namespaces");
|
||||
|
||||
assert_se(namespace_flags_to_string(0, &s) == 0 && isempty(s));
|
||||
s = mfree(s);
|
||||
@ -297,19 +289,10 @@ TEST(restrict_namespace) {
|
||||
assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
|
||||
s = mfree(s);
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(restrict-namespace)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
|
||||
assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0);
|
||||
|
||||
@ -337,7 +320,7 @@ TEST(restrict_namespace) {
|
||||
assert_se(setns(0, 0) == -1);
|
||||
assert_se(errno == EPERM);
|
||||
|
||||
pid = raw_clone(CLONE_NEWNS);
|
||||
pid_t pid = raw_clone(CLONE_NEWNS);
|
||||
assert_se(pid >= 0);
|
||||
if (pid == 0)
|
||||
_exit(EXIT_SUCCESS);
|
||||
@ -357,37 +340,21 @@ TEST(restrict_namespace) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(protect_sysctl) {
|
||||
pid_t pid;
|
||||
_cleanup_free_ char *seccomp = NULL;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
int r;
|
||||
|
||||
/* in containers _sysctl() is likely missing anyway */
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ true);
|
||||
|
||||
_cleanup_free_ char *seccomp = NULL;
|
||||
assert_se(get_proc_field("/proc/self/status", "Seccomp", &seccomp) == 0);
|
||||
if (!streq(seccomp, "0"))
|
||||
log_warning("Warning: seccomp filter detected, results may be unreliable for %s", __func__);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(protect-sysctl)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
#if defined __NR__sysctl && __NR__sysctl >= 0
|
||||
assert_se(syscall(__NR__sysctl, NULL) < 0);
|
||||
assert_se(IN_SET(errno, EFAULT, ENOSYS));
|
||||
@ -409,32 +376,16 @@ TEST(protect_sysctl) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(protect_syslog) {
|
||||
pid_t pid;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
int r;
|
||||
|
||||
/* in containers syslog() is likely missing anyway */
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ true);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(protect-syslog)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
#if defined __NR_syslog && __NR_syslog >= 0
|
||||
assert_se(syscall(__NR_syslog, -1, NULL, 0) < 0);
|
||||
assert_se(errno == EINVAL);
|
||||
@ -449,26 +400,15 @@ TEST(protect_syslog) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("syslogseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(restrict_address_families) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(restrict-address-families)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
int fd;
|
||||
Set *s;
|
||||
|
||||
@ -536,34 +476,23 @@ TEST(restrict_address_families) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(restrict_realtime) {
|
||||
pid_t pid;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
int r;
|
||||
|
||||
/* in containers RT privs are likely missing anyway */
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ true);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(restrict-realtime)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
/* On some CI environments, the restriction may be already enabled. */
|
||||
if (sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0) {
|
||||
if (errno == ENOSYS) {
|
||||
log_tests_skipped("sched_setscheduler() is not available or already filtered");
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
log_full_errno(errno == EPERM ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
"Failed to set scheduler parameter for FIFO: %m");
|
||||
assert(errno == EPERM);
|
||||
@ -591,21 +520,13 @@ TEST(restrict_realtime) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(memory_deny_write_execute_mmap) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
#if HAVE_VALGRIND_VALGRIND_H
|
||||
if (RUNNING_ON_VALGRIND) {
|
||||
log_notice("Running on valgrind, skipping %s", __func__);
|
||||
@ -617,10 +538,8 @@ TEST(memory_deny_write_execute_mmap) {
|
||||
return;
|
||||
#endif
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(memory_deny_write_execute_mmap)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
void *p;
|
||||
|
||||
p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
@ -649,14 +568,11 @@ TEST(memory_deny_write_execute_mmap) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(memory_deny_write_execute_shmat) {
|
||||
int shmid;
|
||||
pid_t pid;
|
||||
uint32_t arch;
|
||||
int r, shmid;
|
||||
|
||||
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
||||
log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap));
|
||||
@ -666,14 +582,8 @@ TEST(memory_deny_write_execute_shmat) {
|
||||
log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmdt));
|
||||
}
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs() || have_effective_cap(CAP_IPC_OWNER) <= 0) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
#if HAVE_VALGRIND_VALGRIND_H
|
||||
if (RUNNING_ON_VALGRIND) {
|
||||
log_notice("Running on valgrind, skipping %s", __func__);
|
||||
@ -688,10 +598,8 @@ TEST(memory_deny_write_execute_shmat) {
|
||||
shmid = shmget(IPC_PRIVATE, page_size(), 0);
|
||||
assert_se(shmid >= 0);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(memory-deny-write-execute)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
void *p;
|
||||
|
||||
p = shmat(shmid, NULL, 0);
|
||||
@ -722,26 +630,15 @@ TEST(memory_deny_write_execute_shmat) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(restrict_archs) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(restrict-archs)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
|
||||
assert_se(access("/", F_OK) >= 0);
|
||||
@ -760,26 +657,15 @@ TEST(restrict_archs) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(load_syscall_filter_set_raw) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(load-filter)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
_cleanup_hashmap_free_ Hashmap *s = NULL;
|
||||
|
||||
assert_se(access("/", F_OK) >= 0);
|
||||
@ -873,26 +759,15 @@ TEST(load_syscall_filter_set_raw) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(native_syscalls_filtered) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(native-syscalls)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
_cleanup_set_free_ Set *arch_s = NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *s = NULL;
|
||||
|
||||
@ -931,32 +806,21 @@ TEST(native_syscalls_filtered) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("nativeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
TEST(lock_personality) {
|
||||
unsigned long current_opinionated;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
assert_se(opinionated_personality(¤t_opinionated) >= 0);
|
||||
|
||||
log_info("current personality=0x%lX", (unsigned long) safe_personality(PERSONALITY_INVALID));
|
||||
log_info("current opinionated personality=0x%lX", current_opinionated);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(lock-personality)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
unsigned long current;
|
||||
|
||||
assert_se(seccomp_lock_personality(current_opinionated) >= 0);
|
||||
@ -988,8 +852,6 @@ TEST(lock_personality) {
|
||||
assert_se((current & OPINIONATED_PERSONALITY_MASK) == current_opinionated);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int real_open(const char *path, int flags, mode_t mode) {
|
||||
@ -1023,21 +885,12 @@ static int try_fchmodat2(int dirfd, const char *path, mode_t mode, int flags) {
|
||||
}
|
||||
|
||||
TEST(restrict_suid_sgid) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
pid = fork();
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(suid-sgid)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
|
||||
int fd = -EBADF, k = -EBADF;
|
||||
const char *z;
|
||||
@ -1224,8 +1077,6 @@ TEST(restrict_suid_sgid) {
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void test_seccomp_suppress_sync_child(void) {
|
||||
@ -1258,25 +1109,15 @@ static void test_seccomp_suppress_sync_child(void) {
|
||||
}
|
||||
|
||||
TEST(seccomp_suppress_sync) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
if (!have_seccomp_privs()) {
|
||||
log_notice("Not privileged, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
CHECK_SECCOMP(/* skip_container = */ false);
|
||||
|
||||
ASSERT_OK_ERRNO(pid = fork());
|
||||
|
||||
if (pid == 0) {
|
||||
ASSERT_OK(r = safe_fork("(suppress-sync)", FORK_LOG | FORK_WAIT, NULL));
|
||||
if (r == 0) {
|
||||
test_seccomp_suppress_sync_child();
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
ASSERT_EQ(wait_for_terminate_and_check("seccomp_suppress_sync", pid, WAIT_LOG), EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
@ -151,6 +151,7 @@ udev_binaries_dict = [
|
||||
include_directories('.', 'net'),
|
||||
],
|
||||
'dependencies' : udev_dependencies,
|
||||
'link_with' : udev_link_with,
|
||||
'install_rpath' : udev_rpath,
|
||||
'install_tag' : 'udev',
|
||||
'extract' : udevadm_extract_sources,
|
||||
|
@ -638,7 +638,7 @@ static usec_t extra_timeout_usec(void) {
|
||||
|
||||
parsed = true;
|
||||
|
||||
e = getenv("SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC");
|
||||
e = secure_getenv("SYSTEMD_UDEV_EXTRA_TIMEOUT_SEC");
|
||||
if (!e)
|
||||
return saved;
|
||||
|
||||
|
@ -1011,7 +1011,9 @@ static int parse_token(
|
||||
op = OP_ASSIGN;
|
||||
|
||||
if (streq(value, "dump"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DUMP, op, NULL, NULL, /* is_case_insensitive = */ false, token_str);
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DUMP, op, NULL, UINT_TO_PTR(SD_JSON_FORMAT_OFF), /* is_case_insensitive = */ false, token_str);
|
||||
else if (streq(value, "dump-json"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_DUMP, op, NULL, UINT_TO_PTR(SD_JSON_FORMAT_NEWLINE), /* is_case_insensitive = */ false, token_str);
|
||||
else if (streq(value, "string_escape=none"))
|
||||
r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_NONE, op, NULL, NULL, /* is_case_insensitive = */ false, token_str);
|
||||
else if (streq(value, "string_escape=replace"))
|
||||
@ -2593,6 +2595,8 @@ static int udev_rule_apply_token_to_event(
|
||||
return token_match_string(event, token, event->program_result, /* log_result = */ true);
|
||||
|
||||
case TK_A_OPTIONS_DUMP: {
|
||||
sd_json_format_flags_t flags = PTR_TO_UINT(token->data);
|
||||
|
||||
log_event_info(event, token, "Dumping current state:");
|
||||
|
||||
_cleanup_(memstream_done) MemStream m = {};
|
||||
@ -2600,7 +2604,7 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!f)
|
||||
return log_oom();
|
||||
|
||||
(void) dump_event(event, SD_JSON_FORMAT_OFF, f);
|
||||
(void) dump_event(event, flags, f);
|
||||
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
r = memstream_finalize(&m, &buf, NULL);
|
||||
|
@ -628,7 +628,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_TPM_STATE:
|
||||
if (path_is_absolute(optarg) && path_is_valid(optarg)) {
|
||||
if (path_is_valid(optarg) && (path_is_absolute(optarg) || path_startswith(optarg, "./"))) {
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm_state_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2094,24 +2094,30 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
}
|
||||
|
||||
if (arg_image) {
|
||||
_cleanup_free_ char *escaped_image = NULL;
|
||||
|
||||
assert(!arg_directory);
|
||||
|
||||
r = strv_extend(&cmdline, "-drive");
|
||||
if (r < 0)
|
||||
if (strv_extend(&cmdline, "-drive") < 0)
|
||||
return log_oom();
|
||||
|
||||
escaped_image = escape_qemu_value(arg_image);
|
||||
_cleanup_free_ char *escaped_image = escape_qemu_value(arg_image);
|
||||
if (!escaped_image)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=raw,discard=%s", escaped_image, on_off(arg_discard_disk));
|
||||
if (r < 0)
|
||||
if (strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=raw,discard=%s", escaped_image, on_off(arg_discard_disk)) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extend_many(&cmdline, "-device", "virtio-blk-pci,drive=vmspawn,bootindex=1");
|
||||
if (r < 0)
|
||||
_cleanup_free_ char *image_fn = NULL;
|
||||
if (path_extract_filename(arg_image, &image_fn) < 0)
|
||||
return log_error_errno(r, "Failed to extract filename from path '%s': %m", image_fn);
|
||||
|
||||
_cleanup_free_ char *escaped_image_fn = escape_qemu_value(image_fn);
|
||||
if (!escaped_image_fn)
|
||||
return log_oom();
|
||||
|
||||
if (strv_extend(&cmdline, "-device") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (strv_extendf(&cmdline, "virtio-blk-pci,drive=vmspawn,bootindex=1,serial=%s", escaped_image_fn) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = grow_image(arg_image, arg_grow_image);
|
||||
@ -2186,21 +2192,18 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
|
||||
size_t i = 0;
|
||||
STRV_FOREACH(drive, arg_extra_drives) {
|
||||
_cleanup_free_ char *escaped_drive = NULL;
|
||||
const char *driver = NULL;
|
||||
struct stat st;
|
||||
|
||||
r = strv_extend(&cmdline, "-blockdev");
|
||||
if (r < 0)
|
||||
if (strv_extend(&cmdline, "-blockdev") < 0)
|
||||
return log_oom();
|
||||
|
||||
escaped_drive = escape_qemu_value(*drive);
|
||||
_cleanup_free_ char *escaped_drive = escape_qemu_value(*drive);
|
||||
if (!escaped_drive)
|
||||
return log_oom();
|
||||
|
||||
struct stat st;
|
||||
if (stat(*drive, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat '%s': %m", *drive);
|
||||
|
||||
const char *driver = NULL;
|
||||
if (S_ISREG(st.st_mode))
|
||||
driver = "file";
|
||||
else if (S_ISBLK(st.st_mode))
|
||||
@ -2208,16 +2211,22 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected regular file or block device, not '%s'.", *drive);
|
||||
|
||||
r = strv_extendf(&cmdline, "driver=raw,cache.direct=off,cache.no-flush=on,file.driver=%s,file.filename=%s,node-name=vmspawn_extra_%zu", driver, escaped_drive, i);
|
||||
if (r < 0)
|
||||
if (strv_extendf(&cmdline, "driver=raw,cache.direct=off,cache.no-flush=on,file.driver=%s,file.filename=%s,node-name=vmspawn_extra_%zu", driver, escaped_drive, i) < 0)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extend(&cmdline, "-device");
|
||||
_cleanup_free_ char *drive_fn = NULL;
|
||||
r = path_extract_filename(*drive, &drive_fn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract filename from path '%s': %m", *drive);
|
||||
|
||||
_cleanup_free_ char *escaped_drive_fn = escape_qemu_value(drive_fn);
|
||||
if (!escaped_drive_fn)
|
||||
return log_oom();
|
||||
|
||||
r = strv_extendf(&cmdline, "scsi-hd,drive=vmspawn_extra_%zu", i++);
|
||||
if (r < 0)
|
||||
if (strv_extend(&cmdline, "-device") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (strv_extendf(&cmdline, "scsi-hd,drive=vmspawn_extra_%zu,serial=%s", i++, escaped_drive_fn) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ if want_tests != 'false'
|
||||
test('test-udev',
|
||||
test_udev_py,
|
||||
args : ['-v'],
|
||||
env : ['UDEV_RULE_RUNNER=' + exe.full_path()],
|
||||
env : test_env + { 'UDEV_RULE_RUNNER' : exe.full_path() },
|
||||
depends : exe,
|
||||
timeout : 180,
|
||||
suite : 'udev')
|
||||
|
@ -35,12 +35,12 @@ preprocess() {
|
||||
}
|
||||
|
||||
compare() {
|
||||
if ! diff -u "$TESTDIR/etc/passwd" <(preprocess "$1.expected-passwd" "$3"); then
|
||||
if ! diff -u "$TESTDIR/etc/passwd" <(preprocess "$1.expected-passwd" "$3") >&2; then
|
||||
echo >&2 "**** Unexpected output for $f $2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! diff -u "$TESTDIR/etc/group" <(preprocess "$1.expected-group" "$3"); then
|
||||
if ! diff -u "$TESTDIR/etc/group" <(preprocess "$1.expected-group" "$3") >&2; then
|
||||
echo >&2 "**** Unexpected output for $f $2"
|
||||
exit 1
|
||||
fi
|
||||
@ -167,7 +167,7 @@ for f in $(find "$SOURCE"/unhappy-*.input | sort -V); do
|
||||
prepare_testdir "${f%.input}"
|
||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||
SYSTEMD_LOG_LEVEL=info "$SYSUSERS" --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
|
||||
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err"; then
|
||||
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err" >&2; then
|
||||
echo >&2 "**** Unexpected error output for $f"
|
||||
cat >&2 "$TESTDIR/err"
|
||||
exit 1
|
||||
|
@ -20,8 +20,7 @@ ConditionDirectoryNotEmpty=|/sysusr/usr/lib/repart.d
|
||||
ConditionDirectoryNotEmpty=|/sysusr/usr/local/lib/repart.d
|
||||
|
||||
DefaultDependencies=no
|
||||
Wants=modprobe@loop.service modprobe@dm_mod.service
|
||||
After=initrd-usr-fs.target modprobe@loop.service modprobe@dm_mod.service systemd-tpm2-setup-early.service
|
||||
After=initrd-usr-fs.target systemd-tpm2-setup-early.service systemd-tmpfiles-setup-dev.service
|
||||
Before=initrd-root-fs.target factory-reset-now.target
|
||||
Conflicts=shutdown.target initrd-switch-root.target
|
||||
Before=shutdown.target initrd-switch-root.target
|
||||
|
Loading…
x
Reference in New Issue
Block a user