mirror of
https://github.com/systemd/systemd
synced 2025-11-10 20:34:45 +01:00
Compare commits
65 Commits
307f904d6f
...
380f0b0b5d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
380f0b0b5d | ||
|
|
83f3c4d4d7 | ||
|
|
df708956b0 | ||
|
|
a248717cd2 | ||
|
|
82850b88f6 | ||
|
|
2ccbc76efb | ||
|
|
9a4618259f | ||
|
|
6afa11c8fa | ||
|
|
86fe18ddcf | ||
|
|
61bd310be9 | ||
|
|
64ac3f1879 | ||
|
|
9c8e3e54cf | ||
|
|
f748583e3d | ||
|
|
2a998ced94 | ||
|
|
9d485e0223 | ||
|
|
9e010a8066 | ||
|
|
84f817f754 | ||
|
|
f48447bfa8 | ||
|
|
279a13734d | ||
|
|
163eaa210c | ||
|
|
af972669db | ||
|
|
8b0239e196 | ||
|
|
d6c5f1d099 | ||
|
|
524b071a6a | ||
|
|
27ed3f4c2e | ||
|
|
d9789b2296 | ||
|
|
d5f5ff3ff0 | ||
|
|
067674fd02 | ||
|
|
2c78b439c7 | ||
|
|
5541e2df06 | ||
|
|
1d696f8ced | ||
|
|
fd38588cea | ||
|
|
b64317021a | ||
|
|
433d4fca37 | ||
|
|
7e43380e98 | ||
|
|
20fd371151 | ||
|
|
c5567d6ba1 | ||
|
|
3b882d6806 | ||
|
|
0483ee5dd9 | ||
|
|
1a12193be0 | ||
|
|
711109fef3 | ||
|
|
3f04968391 | ||
|
|
ac54da0718 | ||
|
|
5e989c5ad6 | ||
|
|
1a2d944614 | ||
|
|
9c1db4cd8e | ||
|
|
29cbe93ea5 | ||
|
|
3ad1fced57 | ||
|
|
90133eace3 | ||
|
|
695fb59075 | ||
|
|
9098d3d7f9 | ||
|
|
4a8df48f20 | ||
|
|
b80d4387fa | ||
|
|
886f288db1 | ||
|
|
ba87dcfe69 | ||
|
|
21389c1e22 | ||
|
|
aabcc77c54 | ||
|
|
a70f9c7c68 | ||
|
|
e64a0ffd03 | ||
|
|
7de1f51c7c | ||
|
|
77f88042e6 | ||
|
|
76a686b648 | ||
|
|
5179e7a558 | ||
|
|
af954efb16 | ||
|
|
e155b83d3f |
2
.github/workflows/mkosi.yml
vendored
2
.github/workflows/mkosi.yml
vendored
@ -137,7 +137,7 @@ jobs:
|
||||
sanitizers: ""
|
||||
llvm: 0
|
||||
cflags: "-Og"
|
||||
relabel: no
|
||||
relabel: yes
|
||||
vm: 0
|
||||
no_qemu: 0
|
||||
no_kvm: 0
|
||||
|
||||
@ -63,8 +63,11 @@ NTP servers.
|
||||
|
||||
## DNS Servers
|
||||
|
||||
By default, systemd-resolved uses Cloudflare, Google, Quad9 and DNS0 Public DNS servers
|
||||
`1.1.1.1`, `8.8.8.8`, `9.9.9.9`, `193.110.81.0`, `1.0.0.1`, `8.8.4.4`, `149.112.112.112`, `185.253.5.0`, `2606:4700:4700::1111`, `2001:4860:4860::8888`, `2620:fe::fe`, `2a0f:fc80::`, `2606:4700:4700::1001`, `2001:4860:4860::8844`, `2620:fe::9`, `2a0f:fc81::`
|
||||
By default, systemd-resolved uses Cloudflare, Google and Quad9 Public DNS servers
|
||||
`1.1.1.1`, `8.8.8.8`, `9.9.9.9`,
|
||||
`1.0.0.1`, `8.8.4.4`, `149.112.112.112`,
|
||||
`2606:4700:4700::1111`, `2001:4860:4860::8888`, `2620:fe::fe`,
|
||||
`2606:4700:4700::1001`, `2001:4860:4860::8844`, `2620:fe::9`
|
||||
as fallback, if no other DNS configuration is available.
|
||||
|
||||
Use `-Ddns-servers=` to direct systemd-resolved to different fallback
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#
|
||||
# Match string formats:
|
||||
# id-input:modalias:<modalias>
|
||||
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
|
||||
#
|
||||
# To add local entries, create a new file
|
||||
# /etc/udev/hwdb.d/61-input-id-local.hwdb
|
||||
@ -47,9 +48,20 @@
|
||||
# id-input:modalias:input:b0003v1234pABCD*
|
||||
# ID_INPUT_TOUCHPAD=1
|
||||
# ID_INPUT=1
|
||||
#
|
||||
# id-input:usb:v12abp34cd:name:SomeVendor *:*
|
||||
# ID_INPUT_TOUCHPAD=1
|
||||
# ID_INPUT=1
|
||||
#
|
||||
# For technical reasons the hexadecimal vid/pid in the modalias match are
|
||||
# uppercase but lowercase in the bus/vid/pid/name match.
|
||||
|
||||
# Sort by brand, model
|
||||
|
||||
# Any i2c device with a Mouse suffix in the name is not a pointing stick
|
||||
id-input:i2c:*:name:*Mouse:
|
||||
ID_INPUT_POINTINGSTICK=0
|
||||
|
||||
# Code Mercenaries Hard- und Software GmbH Virtual RC USB
|
||||
id-input:modalias:input:b0003v07C0p1125*
|
||||
ID_INPUT_MOUSE=
|
||||
|
||||
@ -75,7 +75,7 @@ UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
|
||||
TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
|
||||
'evdev': ('name', 'atkbd', 'input'),
|
||||
'fb': ('pci', 'vmbus'),
|
||||
'id-input': ('modalias'),
|
||||
'id-input': ('modalias', 'bluetooth', 'i2c', 'usb'),
|
||||
'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'),
|
||||
'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'),
|
||||
'keyboard': ('name', ),
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
|
||||
<para>Capsule names may be chosen freely by the user, however, they must be suitable as UNIX filenames
|
||||
(i.e. 255 characters max, and contain no <literal>/</literal>), and when prefixed with
|
||||
<literal>p-</literal> be suitable as a user name matching strict POSIX rules, see <ulink
|
||||
<literal>c-</literal> be suitable as a user name matching strict POSIX rules, see <ulink
|
||||
url="https://systemd.io/USER_NAMES">User/Group Name Syntax</ulink> for details.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
|
||||
@ -346,7 +346,6 @@ $ ukify build \
|
||||
<programlisting># systemd-cryptenroll --tpm2-device=auto \
|
||||
--tpm2-public-key=tpm2-pcr-public-key.pem \
|
||||
--tpm2-signature=tpm2-pcr-signature.json \
|
||||
--tpm2-pcrs="" \
|
||||
/dev/sda5</programlisting>
|
||||
|
||||
<para>And then unlock the device with the signature:</para>
|
||||
|
||||
@ -4351,7 +4351,7 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>exec-condition</literal></entry>
|
||||
<entry>Service did not run because <varname>ExecCondition=</varname> failed.</entry>
|
||||
<entry>Service did not run because <varname>ExecCondition=</varname> failed (that is its command exited with an exit status of 1 through 254 (inclusive)).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>oom-kill</literal></entry>
|
||||
|
||||
@ -367,7 +367,7 @@ option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', '
|
||||
description : 'DNS-over-TLS support')
|
||||
option('dns-servers', type : 'string',
|
||||
description : 'space-separated list of default DNS servers',
|
||||
value : '1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google 9.9.9.9#dns.quad9.net 193.110.81.0#dns0.eu 1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google 149.112.112.112#dns.quad9.net 185.253.5.0#dns0.eu 2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google 2620:fe::fe#dns.quad9.net 2a0f:fc80::#dns0.eu 2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google 2620:fe::9#dns.quad9.net 2a0f:fc81::#dns0.eu')
|
||||
value : '1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google 9.9.9.9#dns.quad9.net 1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google 149.112.112.112#dns.quad9.net 2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google 2620:fe::fe#dns.quad9.net 2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google 2620:fe::9#dns.quad9.net')
|
||||
option('ntp-servers', type : 'string',
|
||||
description : 'space-separated list of default NTP servers',
|
||||
value : 'time1.google.com time2.google.com time3.google.com time4.google.com')
|
||||
|
||||
@ -13,4 +13,4 @@ ACTION!="remove", SUBSYSTEM=="block", \
|
||||
OPTIONS+="watch"
|
||||
|
||||
# Reset access rights to each loopback device once it gets detached.
|
||||
SUBSYSTEM=="block", ACTION=="change", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660"
|
||||
ACTION=="change", SUBSYSTEM=="block", KERNEL=="loop*", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660"
|
||||
|
||||
@ -5,4 +5,15 @@ ACTION=="remove", GOTO="id_input_end"
|
||||
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
|
||||
SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:"
|
||||
|
||||
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
|
||||
KERNELS=="input*", ATTRS{id/bustype}=="0003", \
|
||||
IMPORT{builtin}="hwdb 'id-input:usb:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="id_input_end"
|
||||
KERNELS=="input*", ATTRS{id/bustype}=="0005", \
|
||||
IMPORT{builtin}="hwdb 'id-input:bluetooth:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="id_input_end"
|
||||
KERNELS=="input*", ATTRS{id/bustype}=="0018", \
|
||||
IMPORT{builtin}="hwdb 'id-input:i2c:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="id_input_end"
|
||||
|
||||
LABEL="id_input_end"
|
||||
|
||||
@ -4,40 +4,13 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "assert-util.h"
|
||||
#include "env-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "log.h"
|
||||
|
||||
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
|
||||
|
||||
/* Akin to glibc's __abort_msg; which is private and we hence cannot
|
||||
* use here. */
|
||||
static char *log_abort_msg = NULL;
|
||||
|
||||
void log_set_assert_return_is_critical(bool b) {
|
||||
assert_return_is_critical = b;
|
||||
}
|
||||
|
||||
void log_set_assert_return_is_critical_from_env(void) {
|
||||
static int cached = INT_MIN;
|
||||
int r;
|
||||
|
||||
if (cached == INT_MIN) {
|
||||
r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL");
|
||||
if (r < 0 && r != -ENXIO)
|
||||
log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m");
|
||||
|
||||
cached = r;
|
||||
}
|
||||
|
||||
if (cached >= 0)
|
||||
log_set_assert_return_is_critical(cached);
|
||||
}
|
||||
|
||||
bool log_get_assert_return_is_critical(void) {
|
||||
return assert_return_is_critical;
|
||||
}
|
||||
|
||||
static void log_assert(
|
||||
int level,
|
||||
const char *text,
|
||||
@ -73,8 +46,8 @@ _noreturn_ void log_assert_failed_unreachable(const char *file, int line, const
|
||||
}
|
||||
|
||||
void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
|
||||
|
||||
if (assert_return_is_critical)
|
||||
/* log_get_assert_return_is_critical is a weak symbol. It may be NULL. */
|
||||
if (log_get_assert_return_is_critical && log_get_assert_return_is_critical())
|
||||
log_assert_failed(text, file, line, func);
|
||||
|
||||
PROTECT_ERRNO;
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
|
||||
/* Logging for various assertions */
|
||||
|
||||
void log_set_assert_return_is_critical(bool b);
|
||||
void log_set_assert_return_is_critical_from_env(void);
|
||||
bool log_get_assert_return_is_critical(void) _pure_;
|
||||
bool log_get_assert_return_is_critical(void) _weak_ _pure_;
|
||||
|
||||
void log_assert_failed_return(const char *text, const char *file, int line, const char *func);
|
||||
|
||||
|
||||
@ -164,9 +164,8 @@ int efi_get_variable(
|
||||
}
|
||||
|
||||
int efi_get_variable_string(const char *variable, char **ret) {
|
||||
_cleanup_free_ void *s = NULL;
|
||||
_cleanup_free_ void *s = NULL, *x = NULL;
|
||||
size_t ss = 0;
|
||||
char *x;
|
||||
int r;
|
||||
|
||||
assert(variable);
|
||||
@ -180,7 +179,7 @@ int efi_get_variable_string(const char *variable, char **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
if (ret)
|
||||
*ret = x;
|
||||
*ret = TAKE_PTR(x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -22,6 +22,6 @@ static struct mempool pool_name = { \
|
||||
.at_least = alloc_at_least, \
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool mempool_enabled(void);
|
||||
bool mempool_enabled(void) _weak_ _pure_;
|
||||
|
||||
void mempool_trim(struct mempool *mp);
|
||||
|
||||
@ -1518,30 +1518,40 @@ int path_glob_can_match(const char *pattern, const char *prefix, char **ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* default_PATH(void) {
|
||||
#if HAVE_SPLIT_BIN
|
||||
static int split = -1;
|
||||
static bool dir_is_split(const char *a, const char *b) {
|
||||
int r;
|
||||
|
||||
/* Check whether /usr/sbin is not a symlink and return the appropriate $PATH.
|
||||
* On error fall back to the safe value with both directories as configured… */
|
||||
|
||||
if (split < 0)
|
||||
STRV_FOREACH_PAIR(bin, sbin, STRV_MAKE("/usr/bin", "/usr/sbin",
|
||||
"/usr/local/bin", "/usr/local/sbin")) {
|
||||
r = inode_same(*bin, *sbin, AT_NO_AUTOMOUNT);
|
||||
if (r > 0 || r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", using compat $PATH: %m",
|
||||
*bin, *sbin);
|
||||
split = true;
|
||||
break;
|
||||
}
|
||||
if (split < 0)
|
||||
split = false;
|
||||
if (split)
|
||||
return DEFAULT_PATH_WITH_SBIN;
|
||||
#endif
|
||||
return DEFAULT_PATH_WITHOUT_SBIN;
|
||||
r = inode_same(a, b, AT_NO_AUTOMOUNT);
|
||||
if (r < 0 && r != -ENOENT) {
|
||||
log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", assuming split directories: %m", a, b);
|
||||
return true;
|
||||
}
|
||||
return r == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* default_PATH(void) {
|
||||
#if HAVE_SPLIT_BIN
|
||||
static const char *default_path = NULL;
|
||||
|
||||
/* Return one of the three sets of paths:
|
||||
* a) split /usr/s?bin, /usr/local/sbin doesn't matter.
|
||||
* b) merged /usr/s?bin, /usr/sbin is a symlink, but /usr/local/sbin is not,
|
||||
* c) fully merged, neither /usr/sbin nor /usr/local/sbin are symlinks,
|
||||
*
|
||||
* On error the fallback to the safe value with both directories as configured is returned.
|
||||
*/
|
||||
|
||||
if (default_path)
|
||||
return default_path;
|
||||
|
||||
if (dir_is_split("/usr/sbin", "/usr/bin"))
|
||||
return (default_path = DEFAULT_PATH_WITH_FULL_SBIN); /* a */
|
||||
if (dir_is_split("/usr/local/sbin", "/usr/local/bin"))
|
||||
return (default_path = DEFAULT_PATH_WITH_LOCAL_SBIN); /* b */
|
||||
return (default_path = DEFAULT_PATH_WITHOUT_SBIN); /* c */
|
||||
#else
|
||||
return DEFAULT_PATH_WITHOUT_SBIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -9,10 +9,11 @@
|
||||
#define PATH_MERGED_BIN(x) x "bin"
|
||||
#define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
|
||||
|
||||
#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
|
||||
#define DEFAULT_PATH_WITH_FULL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
|
||||
#define DEFAULT_PATH_WITH_LOCAL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
|
||||
#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
|
||||
|
||||
#define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
|
||||
#define DEFAULT_PATH_COMPAT DEFAULT_PATH_WITH_FULL_SBIN ":" PATH_SPLIT_BIN("/")
|
||||
|
||||
const char* default_PATH(void);
|
||||
|
||||
|
||||
@ -144,6 +144,16 @@ FreezerState freezer_state_finish(FreezerState state) {
|
||||
return freezer_state_finish_table[state];
|
||||
}
|
||||
|
||||
FreezerState freezer_state_objective(FreezerState state) {
|
||||
FreezerState objective;
|
||||
|
||||
objective = freezer_state_finish(state);
|
||||
if (objective == FREEZER_FROZEN_BY_PARENT)
|
||||
objective = FREEZER_FROZEN;
|
||||
|
||||
return objective;
|
||||
}
|
||||
|
||||
static const char* const unit_marker_table[_UNIT_MARKER_MAX] = {
|
||||
[UNIT_MARKER_NEEDS_RELOAD] = "needs-reload",
|
||||
[UNIT_MARKER_NEEDS_RESTART] = "needs-restart",
|
||||
|
||||
@ -325,6 +325,7 @@ UnitActiveState unit_active_state_from_string(const char *s) _pure_;
|
||||
const char* freezer_state_to_string(FreezerState i) _const_;
|
||||
FreezerState freezer_state_from_string(const char *s) _pure_;
|
||||
FreezerState freezer_state_finish(FreezerState i) _const_;
|
||||
FreezerState freezer_state_objective(FreezerState state) _const_;
|
||||
|
||||
const char* unit_marker_to_string(UnitMarker m) _const_;
|
||||
UnitMarker unit_marker_from_string(const char *s) _pure_;
|
||||
|
||||
@ -114,12 +114,20 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (arg_show_unit == SHOW_UNIT_USER)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Cannot combine --unit with --user-unit.");
|
||||
|
||||
arg_show_unit = SHOW_UNIT_SYSTEM;
|
||||
if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
case ARG_USER_UNIT:
|
||||
if (arg_show_unit == SHOW_UNIT_SYSTEM)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Cannot combine --user-unit with --unit.");
|
||||
|
||||
arg_show_unit = SHOW_UNIT_USER;
|
||||
if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
|
||||
return log_oom();
|
||||
|
||||
@ -905,8 +905,16 @@ static int get_supplementary_groups(
|
||||
bool keep_groups = false;
|
||||
if (user && gid_is_valid(gid) && gid != 0) {
|
||||
/* First step, initialize groups from /etc/groups */
|
||||
if (initgroups(user, gid) < 0)
|
||||
return -errno;
|
||||
if (initgroups(user, gid) < 0) {
|
||||
/* If our primary gid is already the one specified in Group= (i.e. we're running in
|
||||
* user mode), gracefully handle the case where we have no privilege to re-initgroups().
|
||||
*
|
||||
* Note that group memberships of the current user might have been modified, but
|
||||
* the change will only take effect after re-login. It's better to continue on with
|
||||
* existing credentials rather than erroring out. */
|
||||
if (!ERRNO_IS_PRIVILEGE(errno) || gid != getgid())
|
||||
return -errno;
|
||||
}
|
||||
|
||||
keep_groups = true;
|
||||
}
|
||||
@ -1230,6 +1238,11 @@ static int exec_context_get_tty_for_pam(const ExecContext *context, char **ret)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IN_SET(context->std_input, EXEC_INPUT_TTY, EXEC_INPUT_TTY_FAIL, EXEC_INPUT_TTY_FORCE)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Next, let's try to use the TTY specified in TTYPath=. */
|
||||
const char *t = exec_context_tty_path(context);
|
||||
if (!t) {
|
||||
@ -4469,6 +4482,12 @@ static void log_command_line(
|
||||
|
||||
static bool exec_needs_cap_sys_admin(const ExecContext *context, const ExecParameters *params) {
|
||||
assert(context);
|
||||
assert(params);
|
||||
|
||||
/* We only want to ever imply PrivateUsers= for user managers, as they're not expected to setuid() to
|
||||
* other users, unlike the system manager which needs all users to be around. */
|
||||
if (params->runtime_scope != RUNTIME_SCOPE_USER)
|
||||
return false;
|
||||
|
||||
return context->private_users != PRIVATE_USERS_NO ||
|
||||
context->private_tmp != PRIVATE_TMP_NO ||
|
||||
|
||||
@ -1390,6 +1390,7 @@ static int mount_start(Unit *u) {
|
||||
|
||||
static int mount_stop(Unit *u) {
|
||||
Mount *m = ASSERT_PTR(MOUNT(u));
|
||||
int r;
|
||||
|
||||
switch (m->state) {
|
||||
|
||||
@ -1401,21 +1402,22 @@ static int mount_stop(Unit *u) {
|
||||
|
||||
case MOUNT_MOUNTING:
|
||||
case MOUNT_MOUNTING_DONE:
|
||||
case MOUNT_REMOUNTING:
|
||||
/* If we are still waiting for /bin/mount, we go directly into kill mode. */
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS);
|
||||
return 0;
|
||||
|
||||
case MOUNT_REMOUNTING:
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
/* If we are already waiting for a hung remount, convert this to the matching unmounting state */
|
||||
mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM);
|
||||
return 0;
|
||||
assert(pidref_is_set(&m->control_pid));
|
||||
|
||||
r = pidref_kill_and_sigcont(&m->control_pid, SIGKILL);
|
||||
if (r < 0)
|
||||
log_unit_debug_errno(u, r,
|
||||
"Failed to kill remount process " PID_FMT ", ignoring: %m",
|
||||
m->control_pid.pid);
|
||||
|
||||
_fallthrough_;
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
/* as above */
|
||||
mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL);
|
||||
return 0;
|
||||
|
||||
case MOUNT_MOUNTED:
|
||||
mount_enter_unmounting(m);
|
||||
return 1;
|
||||
@ -2404,7 +2406,6 @@ char* mount_get_where_escaped(const Mount *m) {
|
||||
}
|
||||
|
||||
char* mount_get_what_escaped(const Mount *m) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
const char *s = NULL;
|
||||
|
||||
assert(m);
|
||||
@ -2413,14 +2414,10 @@ char* mount_get_what_escaped(const Mount *m) {
|
||||
s = m->parameters_proc_self_mountinfo.what;
|
||||
else if (m->from_fragment && m->parameters_fragment.what)
|
||||
s = m->parameters_fragment.what;
|
||||
if (!s)
|
||||
return strdup("");
|
||||
|
||||
if (s) {
|
||||
escaped = utf8_escape_invalid(s);
|
||||
if (!escaped)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return escaped ? TAKE_PTR(escaped) : strdup("");
|
||||
return utf8_escape_invalid(s);
|
||||
}
|
||||
|
||||
char* mount_get_options_escaped(const Mount *m) {
|
||||
|
||||
@ -366,6 +366,18 @@
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="SetShowStatus"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="SetEnvironment"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="UnsetEnvironment"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="UnsetAndSetEnvironment"/>
|
||||
|
||||
<!-- Managed via polkit or other criteria: org.freedesktop.systemd1.Job interface -->
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
|
||||
@ -414,7 +414,7 @@ static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) {
|
||||
static void service_reset_watchdog(Service *s) {
|
||||
assert(s);
|
||||
|
||||
if (freezer_state_finish(UNIT(s)->freezer_state) != FREEZER_RUNNING) {
|
||||
if (freezer_state_objective(UNIT(s)->freezer_state) != FREEZER_RUNNING) {
|
||||
log_unit_debug(UNIT(s), "Service is currently %s, skipping resetting watchdog.",
|
||||
freezer_state_to_string(UNIT(s)->freezer_state));
|
||||
return;
|
||||
@ -1425,7 +1425,7 @@ static int service_coldplug(Unit *u) {
|
||||
(void) unit_setup_exec_runtime(u);
|
||||
|
||||
if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_REFRESH_EXTENSIONS, SERVICE_MOUNTING) &&
|
||||
freezer_state_finish(u->freezer_state) == FREEZER_RUNNING)
|
||||
freezer_state_objective(u->freezer_state) == FREEZER_RUNNING)
|
||||
service_start_watchdog(s);
|
||||
|
||||
if (UNIT_ISSET(s->accept_socket)) {
|
||||
@ -5643,18 +5643,33 @@ int service_determine_exec_selinux_label(Service *s, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int service_cgroup_freezer_action(Unit *u, FreezerAction action) {
|
||||
static int service_freezer_action(Unit *u, FreezerAction action) {
|
||||
Service *s = ASSERT_PTR(SERVICE(u));
|
||||
FreezerState old_objective, new_objective;
|
||||
int r;
|
||||
|
||||
old_objective = freezer_state_objective(u->freezer_state);
|
||||
|
||||
r = unit_cgroup_freezer_action(u, action);
|
||||
if (r <= 0)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (action == FREEZER_FREEZE)
|
||||
service_stop_watchdog(s);
|
||||
else if (action == FREEZER_THAW)
|
||||
service_reset_watchdog(s);
|
||||
new_objective = freezer_state_objective(u->freezer_state);
|
||||
|
||||
/* Note that we cannot trivially check the retval of unit_cgroup_freezer_action() here, since
|
||||
* that signals whether the operation is ongoing from *kernel's PoV*. If the freeze operation
|
||||
* is aborted, the frozen attribute of the cgroup would never have been flipped in kernel,
|
||||
* and unit_cgroup_freezer_action() will happily return 0, yet the watchdog still needs to be reset;
|
||||
* vice versa. */
|
||||
|
||||
if (old_objective != new_objective) {
|
||||
if (new_objective == FREEZER_FROZEN)
|
||||
service_stop_watchdog(s);
|
||||
else if (new_objective == FREEZER_RUNNING)
|
||||
service_reset_watchdog(s);
|
||||
else
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -5796,7 +5811,7 @@ const UnitVTable service_vtable = {
|
||||
.live_mount = service_live_mount,
|
||||
.can_live_mount = service_can_live_mount,
|
||||
|
||||
.freezer_action = service_cgroup_freezer_action,
|
||||
.freezer_action = service_freezer_action,
|
||||
|
||||
.serialize = service_serialize,
|
||||
.deserialize_item = service_deserialize_item,
|
||||
|
||||
@ -392,7 +392,8 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
continue;
|
||||
|
||||
if (v->base == TIMER_CALENDAR) {
|
||||
usec_t b, rebased, random_offset = 0;
|
||||
bool rebase_after_boot_time = false;
|
||||
usec_t b, random_offset = 0;
|
||||
|
||||
if (t->random_offset_usec != 0)
|
||||
random_offset = timer_get_fixed_delay_hash(t) % t->random_offset_usec;
|
||||
@ -417,8 +418,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
b = t->last_trigger.realtime;
|
||||
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
|
||||
b = UNIT(t)->inactive_exit_timestamp.realtime - random_offset;
|
||||
else
|
||||
else {
|
||||
b = ts.realtime - random_offset;
|
||||
rebase_after_boot_time = true;
|
||||
}
|
||||
|
||||
r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
|
||||
if (r < 0)
|
||||
@ -426,14 +429,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
|
||||
v->next_elapse += random_offset;
|
||||
|
||||
/* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
|
||||
* time has already passed, set the time when systemd first started as the scheduled
|
||||
* time. Note that we base this on the monotonic timestamp of the boot, not the
|
||||
* realtime one, since the wallclock might have been off during boot. */
|
||||
rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
|
||||
CLOCK_MONOTONIC, CLOCK_REALTIME);
|
||||
if (v->next_elapse < rebased)
|
||||
v->next_elapse = rebased;
|
||||
if (rebase_after_boot_time) {
|
||||
/* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
|
||||
* time has already passed, set the time when systemd first started as the scheduled
|
||||
* time. Note that we base this on the monotonic timestamp of the boot, not the
|
||||
* realtime one, since the wallclock might have been off during boot. */
|
||||
usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
|
||||
CLOCK_MONOTONIC, CLOCK_REALTIME);
|
||||
if (v->next_elapse < rebased)
|
||||
v->next_elapse = rebased;
|
||||
}
|
||||
|
||||
if (!found_realtime)
|
||||
t->next_elapse_realtime = v->next_elapse;
|
||||
|
||||
@ -6436,9 +6436,7 @@ void unit_next_freezer_state(Unit *u, FreezerAction action, FreezerState *ret_ne
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
objective = freezer_state_finish(next);
|
||||
if (objective == FREEZER_FROZEN_BY_PARENT)
|
||||
objective = FREEZER_FROZEN;
|
||||
objective = freezer_state_objective(next);
|
||||
assert(IN_SET(objective, FREEZER_RUNNING, FREEZER_FROZEN));
|
||||
|
||||
*ret_next = next;
|
||||
|
||||
@ -1294,7 +1294,7 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, PidRef *pi
|
||||
if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0)
|
||||
break;
|
||||
|
||||
if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) {
|
||||
if (IN_SET(errno, EMSGSIZE, ENOBUFS) && mh.msg_iov[0].iov_len > 0) {
|
||||
/* This field didn't fit? That's a pity. Given that this is
|
||||
* just metadata, let's truncate the field at half, and try
|
||||
* again. We append three dots, in order to show that this is
|
||||
|
||||
@ -543,7 +543,7 @@ static int resolve_filename(const char *root, char **p) {
|
||||
static int print_list(FILE* file, sd_journal *j, Table *t) {
|
||||
_cleanup_free_ char
|
||||
*mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
|
||||
*sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
|
||||
*sgnl = NULL, *exe = NULL, *comm = NULL,
|
||||
*filename = NULL, *truncated = NULL, *coredump = NULL;
|
||||
const void *d;
|
||||
size_t l;
|
||||
@ -568,14 +568,16 @@ static int print_list(FILE* file, sd_journal *j, Table *t) {
|
||||
RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl);
|
||||
RETRIEVE(d, l, "COREDUMP_EXE", exe);
|
||||
RETRIEVE(d, l, "COREDUMP_COMM", comm);
|
||||
RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline);
|
||||
RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
|
||||
RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
|
||||
RETRIEVE(d, l, "COREDUMP", coredump);
|
||||
}
|
||||
|
||||
if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Empty coredump log entry");
|
||||
if (!pid || !uid || !gid || !sgnl || !comm) {
|
||||
log_warning("Found a coredump entry without mandatory fields (PID=%s, UID=%s, GID=%s, SIGNAL=%s, COMM=%s), ignoring.",
|
||||
strna(pid), strna(uid), strna(gid), strna(sgnl), strna(comm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) parse_uid(uid, &uid_as_int);
|
||||
(void) parse_gid(gid, &gid_as_int);
|
||||
@ -614,7 +616,7 @@ static int print_list(FILE* file, sd_journal *j, Table *t) {
|
||||
TABLE_SIGNAL, normal_coredump ? signal_as_int : 0,
|
||||
TABLE_STRING, present,
|
||||
TABLE_SET_COLOR, color,
|
||||
TABLE_STRING, exe ?: comm ?: cmdline,
|
||||
TABLE_STRING, exe ?: comm,
|
||||
TABLE_SIZE, size);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "log-assert-critical.h"
|
||||
|
||||
/* The entry point into the fuzzer */
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
|
||||
@ -3778,7 +3778,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_SETENV: {
|
||||
_cleanup_free_ char **l = NULL;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *ne = NULL;
|
||||
sd_json_variant *e;
|
||||
|
||||
|
||||
@ -287,8 +287,6 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
||||
return sd_varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
||||
|
||||
if (p.user_name) {
|
||||
const char *last = NULL;
|
||||
|
||||
r = manager_get_home_by_name(m, p.user_name, &h);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -296,40 +294,37 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
|
||||
if (p.group_name) {
|
||||
if (!strv_contains(h->record->member_of, p.group_name))
|
||||
if (!strv_contains(h->record->member_of, p.group_name) &&
|
||||
!user_record_matches_user_name(h->record, p.group_name))
|
||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
|
||||
return sd_varlink_replybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||
SD_JSON_BUILD_PAIR_STRING("groupName", p.group_name));
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, h->record->member_of) {
|
||||
if (last) {
|
||||
r = sd_varlink_notifybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
last = *i;
|
||||
r = sd_varlink_notifybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||
SD_JSON_BUILD_PAIR_STRING("groupName", *i));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (last)
|
||||
return sd_varlink_replybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||
return sd_varlink_replybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||
SD_JSON_BUILD_PAIR_STRING("groupName", h->user_name));
|
||||
|
||||
} else if (p.group_name) {
|
||||
const char *last = NULL;
|
||||
|
||||
HASHMAP_FOREACH(h, m->homes_by_uid) {
|
||||
|
||||
if (!strv_contains(h->record->member_of, p.group_name))
|
||||
if (!strv_contains(h->record->member_of, p.group_name) &&
|
||||
!user_record_matches_user_name(h->record, p.group_name))
|
||||
continue;
|
||||
|
||||
if (last) {
|
||||
@ -350,34 +345,37 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
||||
} else {
|
||||
const char *last_user_name = NULL, *last_group_name = NULL;
|
||||
const char *last = NULL;
|
||||
|
||||
HASHMAP_FOREACH(h, m->homes_by_uid)
|
||||
HASHMAP_FOREACH(h, m->homes_by_uid) {
|
||||
STRV_FOREACH(j, h->record->member_of) {
|
||||
|
||||
if (last_user_name) {
|
||||
assert(last_group_name);
|
||||
|
||||
if (last) {
|
||||
r = sd_varlink_notifybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
||||
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
last_user_name = h->user_name;
|
||||
last_group_name = *j;
|
||||
r = sd_varlink_notifybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(*j)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (last_user_name) {
|
||||
assert(last_group_name);
|
||||
last = h->user_name;
|
||||
}
|
||||
|
||||
if (last)
|
||||
return sd_varlink_replybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
||||
}
|
||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||
}
|
||||
|
||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||
|
||||
@ -1704,32 +1704,52 @@ static int varlink_idl_validate_field_element_type(const sd_varlink_field *field
|
||||
|
||||
case SD_VARLINK_BOOL:
|
||||
if (!sd_json_variant_is_boolean(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a bool, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be a bool, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
break;
|
||||
|
||||
case SD_VARLINK_INT:
|
||||
/* Allow strings here too, since integers with > 53 bits are often passed in as strings */
|
||||
if (!sd_json_variant_is_integer(v) && !sd_json_variant_is_unsigned(v) && !sd_json_variant_is_string(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an int, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be an int, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
break;
|
||||
|
||||
case SD_VARLINK_FLOAT:
|
||||
if (!sd_json_variant_is_number(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a float, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be a float, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
break;
|
||||
|
||||
case SD_VARLINK_STRING:
|
||||
if (!sd_json_variant_is_string(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a string, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be a string, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
break;
|
||||
|
||||
case SD_VARLINK_OBJECT:
|
||||
if (!sd_json_variant_is_object(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an object, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be an object, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
break;
|
||||
|
||||
@ -1758,7 +1778,10 @@ static int varlink_idl_validate_field(const sd_varlink_field *field, sd_json_var
|
||||
sd_json_variant *i;
|
||||
|
||||
if (!sd_json_variant_is_array(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an array, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an array, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
JSON_VARIANT_ARRAY_FOREACH(i, v) {
|
||||
r = varlink_idl_validate_field_element_type(field, i);
|
||||
@ -1771,7 +1794,11 @@ static int varlink_idl_validate_field(const sd_varlink_field *field, sd_json_var
|
||||
sd_json_variant *e;
|
||||
|
||||
if (!sd_json_variant_is_object(v))
|
||||
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an object, but it is not, refusing.", strna(field->name));
|
||||
return varlink_idl_log(
|
||||
SYNTHETIC_ERRNO(EMEDIUMTYPE),
|
||||
"Field '%s' should be an object, but it is of type '%s', refusing.",
|
||||
strna(field->name),
|
||||
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
|
||||
|
||||
JSON_VARIANT_OBJECT_FOREACH(k, e, v) {
|
||||
r = varlink_idl_validate_field_element_type(field, e);
|
||||
|
||||
@ -464,6 +464,8 @@ static int help(void) {
|
||||
" --overlay-ro=PATH[:PATH...]:PATH\n"
|
||||
" Similar, but creates a read-only overlay mount\n"
|
||||
" --bind-user=NAME Bind user from host to container\n"
|
||||
" --bind-user-shell=BOOL|PATH\n"
|
||||
" Configure the shell to use for --bind-user= users\n"
|
||||
"\n%3$sInput/Output:%4$s\n"
|
||||
" --console=MODE Select how stdin/stdout/stderr and /dev/console are\n"
|
||||
" set up for the container.\n"
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "local-addresses.h"
|
||||
#include "nss-util.h"
|
||||
#include "resolve-util.h"
|
||||
@ -116,7 +117,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
|
||||
r_tuple->next = r_tuple_prev;
|
||||
r_tuple->name = r_name;
|
||||
r_tuple->family = AF_INET6;
|
||||
memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16);
|
||||
memcpy(r_tuple->addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6));
|
||||
r_tuple->scopeid = 0;
|
||||
|
||||
idx += ALIGN(sizeof(struct gaih_addrtuple));
|
||||
@ -144,7 +145,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
|
||||
r_tuple->name = r_name;
|
||||
r_tuple->family = a->family;
|
||||
r_tuple->scopeid = a->family == AF_INET6 && in6_addr_is_link_local(&a->address.in6) ? a->ifindex : 0;
|
||||
memcpy(r_tuple->addr, &a->address, 16);
|
||||
memcpy(r_tuple->addr, &a->address, FAMILY_ADDRESS_SIZE(a->family));
|
||||
|
||||
idx += ALIGN(sizeof(struct gaih_addrtuple));
|
||||
r_tuple_prev = r_tuple;
|
||||
@ -263,7 +264,7 @@ static enum nss_status fill_in_hostent(
|
||||
*(uint32_t*) r_addr = local_address_ipv4;
|
||||
idx += ALIGN(alen);
|
||||
} else if (socket_ipv6_is_enabled()) {
|
||||
memcpy(r_addr, LOCALADDRESS_IPV6, 16);
|
||||
memcpy(r_addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6));
|
||||
idx += ALIGN(alen);
|
||||
}
|
||||
|
||||
@ -463,7 +464,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
|
||||
if (!socket_ipv6_is_enabled())
|
||||
goto not_found;
|
||||
|
||||
if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) {
|
||||
if (memcmp(addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6)) == 0) {
|
||||
canonical = "localhost";
|
||||
additional_from_hostname = true;
|
||||
goto found;
|
||||
|
||||
@ -418,7 +418,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (!IN_SET(q.family, AF_INET, AF_INET6))
|
||||
if (q.family != af)
|
||||
continue;
|
||||
|
||||
if (q.address_size != FAMILY_ADDRESS_SIZE(q.family)) {
|
||||
|
||||
@ -726,7 +726,7 @@ enum nss_status _nss_systemd_getgrent_r(
|
||||
int *errnop) {
|
||||
|
||||
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
|
||||
_cleanup_free_ char **members = NULL;
|
||||
_cleanup_strv_free_ char **members = NULL;
|
||||
int r;
|
||||
|
||||
PROTECT_ERRNO;
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
|
||||
# Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
|
||||
# Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
|
||||
# DNS0: 193.110.81.0#dns0.eu 185.253.5.0#dns0.eu 2a0f:fc80::#dns0.eu 2a0f:fc81::#dns0.eu
|
||||
#
|
||||
# Using DNS= configures global DNS servers and does not suppress link-specific
|
||||
# configuration. Parallel requests will be sent to per-link DNS servers
|
||||
|
||||
@ -8,17 +8,17 @@
|
||||
#
|
||||
# Minimum rpm version supported: 4.14.0
|
||||
|
||||
%transfiletriggerin -P 900900 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerin -P 900900 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
-- This script will run after any package is initially installed or
|
||||
-- upgraded. We care about the case where a package is initially
|
||||
-- installed, because other cases are covered by the *un scriptlets,
|
||||
-- so sometimes we will reload needlessly.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload-restart"))
|
||||
|
||||
%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
||||
%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
|
||||
|
||||
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
-- On removal, we need to run daemon-reload after any units have been
|
||||
-- removed.
|
||||
-- On upgrade, we need to run daemon-reload after any new unit files
|
||||
@ -26,53 +26,53 @@ assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
|
||||
-- executed.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload"))
|
||||
|
||||
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
-- Execute daemon-reload in user managers.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))
|
||||
|
||||
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
-- We restart remaining system services that should be restarted here.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))
|
||||
|
||||
%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
||||
%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
|
||||
-- We restart remaining user services that should be restarted here.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))
|
||||
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSUSERS_DIR}}
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSUSERS_DIR}}/
|
||||
-- This script will process files installed in {{SYSUSERS_DIR}} to create
|
||||
-- specified users automatically. The priority is set such that it
|
||||
-- will run before the tmpfiles file trigger.
|
||||
assert(rpm.execute("systemd-sysusers"))
|
||||
|
||||
%transfiletriggerin -P 1000700 udev -p <lua> -- {{UDEV_HWDB_DIR}}
|
||||
%transfiletriggerin -P 1000700 udev -p <lua> -- {{UDEV_HWDB_DIR}}/
|
||||
-- This script will automatically invoke hwdb update if files have been
|
||||
-- installed or updated in {{UDEV_HWDB_DIR}}.
|
||||
assert(rpm.execute("systemd-hwdb", "update"))
|
||||
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSTEMD_CATALOG_DIR}}
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSTEMD_CATALOG_DIR}}/
|
||||
-- This script will automatically invoke journal catalog update if files
|
||||
-- have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.
|
||||
assert(rpm.execute("journalctl", "--update-catalog"))
|
||||
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{BINFMT_DIR}}
|
||||
%transfiletriggerin -P 1000700 -p <lua> -- {{BINFMT_DIR}}/
|
||||
-- This script will automatically apply binfmt rules if files have been
|
||||
-- installed or updated in {{BINFMT_DIR}}.
|
||||
if posix.access("/run/systemd/system") then
|
||||
assert(rpm.execute("{{LIBEXECDIR}}/systemd-binfmt"))
|
||||
end
|
||||
|
||||
%transfiletriggerin -P 1000600 -p <lua> -- {{TMPFILES_DIR}}
|
||||
%transfiletriggerin -P 1000600 -p <lua> -- {{TMPFILES_DIR}}/
|
||||
-- This script will process files installed in {{TMPFILES_DIR}} to create
|
||||
-- tmpfiles automatically. The priority is set such that it will run
|
||||
-- after the sysusers file trigger, but before any other triggers.
|
||||
assert(rpm.execute("systemd-tmpfiles", "--create"))
|
||||
|
||||
%transfiletriggerin -P 1000600 udev -p <lua> -- {{UDEV_RULES_DIR}}
|
||||
%transfiletriggerin -P 1000600 udev -p <lua> -- {{UDEV_RULES_DIR}}/
|
||||
-- This script will automatically update udev with new rules if files
|
||||
-- have been installed or updated in {{UDEV_RULES_DIR}}.
|
||||
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "mark-reload-system-units", "systemd-udevd.service"))
|
||||
|
||||
%transfiletriggerin -P 1000500 -p <lua> -- {{SYSCTL_DIR}}
|
||||
%transfiletriggerin -P 1000500 -p <lua> -- {{SYSCTL_DIR}}/
|
||||
-- This script will automatically apply sysctl rules if files have been
|
||||
-- installed or updated in {{SYSCTL_DIR}}.
|
||||
if posix.access("/run/systemd/system") then
|
||||
|
||||
@ -9,17 +9,17 @@
|
||||
#
|
||||
# Minimum rpm version supported: 4.14.0
|
||||
|
||||
%transfiletriggerin -P 900900 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerin -P 900900 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
# This script will run after any package is initially installed or
|
||||
# upgraded. We care about the case where a package is initially
|
||||
# installed, because other cases are covered by the *un scriptlets,
|
||||
# so sometimes we will reload needlessly.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :
|
||||
|
||||
%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
||||
%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :
|
||||
|
||||
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
# On removal, we need to run daemon-reload after any units have been
|
||||
# removed.
|
||||
# On upgrade, we need to run daemon-reload after any new unit files
|
||||
@ -27,35 +27,35 @@
|
||||
# executed.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :
|
||||
|
||||
%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
||||
%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
|
||||
# Execute daemon-reload in user managers.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :
|
||||
|
||||
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
||||
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
|
||||
# We restart remaining system services that should be restarted here.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :
|
||||
|
||||
%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
||||
%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
|
||||
# We restart remaining user services that should be restarted here.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :
|
||||
|
||||
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}
|
||||
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}/
|
||||
# This script will process files installed in {{SYSUSERS_DIR}} to create
|
||||
# specified users automatically. The priority is set such that it
|
||||
# will run before the tmpfiles file trigger.
|
||||
systemd-sysusers || :
|
||||
|
||||
%transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}
|
||||
%transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}/
|
||||
# This script will automatically invoke hwdb update if files have been
|
||||
# installed or updated in {{UDEV_HWDB_DIR}}.
|
||||
systemd-hwdb update || :
|
||||
|
||||
%transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}
|
||||
%transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}/
|
||||
# This script will automatically invoke journal catalog update if files
|
||||
# have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.
|
||||
journalctl --update-catalog || :
|
||||
|
||||
%transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}
|
||||
%transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}/
|
||||
# This script will automatically apply binfmt rules if files have been
|
||||
# installed or updated in {{BINFMT_DIR}}.
|
||||
if test -d "/run/systemd/system"; then
|
||||
@ -64,7 +64,7 @@ if test -d "/run/systemd/system"; then
|
||||
{{LIBEXECDIR}}/systemd-binfmt || :
|
||||
fi
|
||||
|
||||
%transfiletriggerin -P 1000600 -- {{TMPFILES_DIR}}
|
||||
%transfiletriggerin -P 1000600 -- {{TMPFILES_DIR}}/
|
||||
# This script will process files installed in {{TMPFILES_DIR}} to create
|
||||
# tmpfiles automatically. The priority is set such that it will run
|
||||
# after the sysusers file trigger, but before any other triggers.
|
||||
@ -72,12 +72,12 @@ if test -d "/run/systemd/system"; then
|
||||
systemd-tmpfiles --create || :
|
||||
fi
|
||||
|
||||
%transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}
|
||||
%transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}/
|
||||
# This script will automatically update udev with new rules if files
|
||||
# have been installed or updated in {{UDEV_RULES_DIR}}.
|
||||
{{SYSTEMD_UPDATE_HELPER_PATH}} mark-reload-system-units systemd-udevd.service || :
|
||||
|
||||
%transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}
|
||||
%transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}/
|
||||
# This script will automatically apply sysctl rules if files have been
|
||||
# installed or updated in {{SYSCTL_DIR}}.
|
||||
if test -d "/run/systemd/system"; then
|
||||
|
||||
@ -1133,6 +1133,8 @@ static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFla
|
||||
r = read_credential(req->credential, (void**) &buffer, &size);
|
||||
if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
|
||||
return -ENOKEY;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = strv_parse_nulstr(buffer, size);
|
||||
if (!l)
|
||||
|
||||
@ -49,6 +49,8 @@ DLSYM_PROTOTYPE(ring_buffer__free) = NULL;
|
||||
DLSYM_PROTOTYPE(ring_buffer__new) = NULL;
|
||||
DLSYM_PROTOTYPE(ring_buffer__poll) = NULL;
|
||||
|
||||
static void* bpf_dl = NULL;
|
||||
|
||||
/* new symbols available from libbpf 0.7.0 */
|
||||
int (*sym_bpf_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
|
||||
struct bpf_map* (*sym_bpf_object__next_map)(const struct bpf_object *obj, const struct bpf_map *map);
|
||||
@ -71,8 +73,8 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
|
||||
}
|
||||
|
||||
int dlopen_bpf_full(int log_level) {
|
||||
_cleanup_(dlclosep) void *dl = NULL;
|
||||
static int cached = 0;
|
||||
void *dl;
|
||||
int r;
|
||||
|
||||
if (cached != 0)
|
||||
@ -177,6 +179,8 @@ int dlopen_bpf_full(int log_level) {
|
||||
|
||||
REENABLE_WARNING;
|
||||
|
||||
bpf_dl = TAKE_PTR(dl);
|
||||
|
||||
return cached = true;
|
||||
}
|
||||
|
||||
|
||||
@ -567,6 +567,7 @@ static int image_make(
|
||||
static int pick_image_search_path(
|
||||
RuntimeScope scope,
|
||||
ImageClass class,
|
||||
const char *root,
|
||||
char ***ret) {
|
||||
|
||||
int r;
|
||||
@ -583,11 +584,11 @@ static int pick_image_search_path(
|
||||
if (scope < 0) {
|
||||
_cleanup_strv_free_ char **a = NULL, **b = NULL;
|
||||
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, &a);
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, root, &a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, &b);
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, root, &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -603,8 +604,15 @@ static int pick_image_search_path(
|
||||
|
||||
case RUNTIME_SCOPE_SYSTEM: {
|
||||
const char *ns;
|
||||
bool is_initrd;
|
||||
|
||||
r = chase_and_access("/etc/initrd-release", root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
is_initrd = r >= 0;
|
||||
|
||||
/* Use the initrd search path if there is one, otherwise use the common one */
|
||||
ns = in_initrd() && image_search_path_initrd[class] ?
|
||||
ns = is_initrd && image_search_path_initrd[class] ?
|
||||
image_search_path_initrd[class] :
|
||||
image_search_path[class];
|
||||
if (!ns)
|
||||
@ -711,7 +719,7 @@ int image_find(RuntimeScope scope,
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -902,7 +910,7 @@ int image_discover(
|
||||
assert(images);
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1797,7 +1805,7 @@ bool image_in_search_path(
|
||||
assert(image);
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -4405,8 +4405,6 @@ int verity_dissect_and_mount(
|
||||
_cleanup_strv_free_ char **extension_release = NULL;
|
||||
ImageClass class = IMAGE_SYSEXT;
|
||||
|
||||
assert(!isempty(extension_release_data->os_release_id));
|
||||
|
||||
r = load_extension_release_pairs(dest, required_class >= 0 ? required_class : IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
|
||||
if (r == -ENOENT) {
|
||||
if (required_class >= 0)
|
||||
|
||||
31
src/shared/log-assert-critical.c
Normal file
31
src/shared/log-assert-critical.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "env-util.h"
|
||||
#include "log.h"
|
||||
#include "log-assert-critical.h"
|
||||
|
||||
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
|
||||
|
||||
void log_set_assert_return_is_critical(bool b) {
|
||||
assert_return_is_critical = b;
|
||||
}
|
||||
|
||||
void log_set_assert_return_is_critical_from_env(void) {
|
||||
static int cached = INT_MIN;
|
||||
int r;
|
||||
|
||||
if (cached == INT_MIN) {
|
||||
r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL");
|
||||
if (r < 0 && r != -ENXIO)
|
||||
log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m");
|
||||
|
||||
cached = r;
|
||||
}
|
||||
|
||||
if (cached >= 0)
|
||||
log_set_assert_return_is_critical(cached);
|
||||
}
|
||||
|
||||
bool log_get_assert_return_is_critical(void) {
|
||||
return assert_return_is_critical;
|
||||
}
|
||||
7
src/shared/log-assert-critical.h
Normal file
7
src/shared/log-assert-critical.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
void log_set_assert_return_is_critical(bool b);
|
||||
void log_set_assert_return_is_critical_from_env(void);
|
||||
@ -34,14 +34,14 @@ static int check_etc_passwd_collisions(
|
||||
if (r == -ENOENT)
|
||||
return 0; /* no user database? then no user, hence no collision */
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open /etc/passwd of container: %m");
|
||||
return log_error_errno(r, "Failed to open /etc/passwd of machine: %m");
|
||||
|
||||
for (;;) {
|
||||
struct passwd *pw;
|
||||
|
||||
r = fgetpwent_sane(f, &pw);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to iterate through /etc/passwd of container: %m");
|
||||
return log_error_errno(r, "Failed to iterate through /etc/passwd of machine: %m");
|
||||
if (r == 0) /* EOF */
|
||||
return 0; /* no collision */
|
||||
|
||||
@ -69,14 +69,14 @@ static int check_etc_group_collisions(
|
||||
if (r == -ENOENT)
|
||||
return 0; /* no group database? then no group, hence no collision */
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open /etc/group of container: %m");
|
||||
return log_error_errno(r, "Failed to open /etc/group of machine: %m");
|
||||
|
||||
for (;;) {
|
||||
struct group *gr;
|
||||
|
||||
r = fgetgrent_sane(f, &gr);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to iterate through /etc/group of container: %m");
|
||||
return log_error_errno(r, "Failed to iterate through /etc/group of machine: %m");
|
||||
if (r == 0)
|
||||
return 0; /* no collision */
|
||||
|
||||
@ -115,14 +115,14 @@ static int convert_user(
|
||||
return r;
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
|
||||
"Sorry, the user '%s' already exists in the container.", u->user_name);
|
||||
"Sorry, the user '%s' already exists in the machine.", u->user_name);
|
||||
|
||||
r = check_etc_group_collisions(directory, g->group_name, GID_INVALID);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
|
||||
"Sorry, the group '%s' already exists in the container.", g->group_name);
|
||||
"Sorry, the group '%s' already exists in the machine.", g->group_name);
|
||||
|
||||
h = path_join("/run/host/home/", u->user_name);
|
||||
if (!h)
|
||||
@ -149,7 +149,7 @@ static int convert_user(
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(u->hashed_password), "hashedPassword", SD_JSON_BUILD_VARIANT(hp)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!!ssh, "sshAuthorizedKeys", SD_JSON_BUILD_VARIANT(ssh))))));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build container user record: %m");
|
||||
return log_error_errno(r, "Failed to build machine user record: %m");
|
||||
|
||||
r = group_record_build(
|
||||
&converted_group,
|
||||
@ -159,7 +159,7 @@ static int convert_user(
|
||||
SD_JSON_BUILD_PAIR_CONDITION(g->disposition >= 0, "disposition", SD_JSON_BUILD_STRING(user_disposition_to_string(g->disposition))),
|
||||
SD_JSON_BUILD_PAIR("service", JSON_BUILD_CONST_STRING("io.systemd.NSpawn"))));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build container group record: %m");
|
||||
return log_error_errno(r, "Failed to build machine group record: %m");
|
||||
|
||||
*ret_converted_user = TAKE_PTR(converted_user);
|
||||
*ret_converted_group = TAKE_PTR(converted_group);
|
||||
@ -176,7 +176,7 @@ static int find_free_uid(const char *directory, uid_t *current_uid) {
|
||||
if (*current_uid > MAP_UID_MAX)
|
||||
return log_error_errno(
|
||||
SYNTHETIC_ERRNO(EBUSY),
|
||||
"No suitable available UID in range " UID_FMT "…" UID_FMT " in container detected, can't map user.",
|
||||
"No suitable available UID in range " UID_FMT "…" UID_FMT " in machine detected, can't map user.",
|
||||
MAP_UID_MIN, MAP_UID_MAX);
|
||||
|
||||
r = check_etc_passwd_collisions(directory, NULL, *current_uid);
|
||||
@ -220,7 +220,7 @@ int machine_bind_user_prepare(
|
||||
assert(ret);
|
||||
|
||||
/* This resolves the users specified in 'bind_user', generates a minimalized JSON user + group record
|
||||
* for it to stick in the container, allocates a UID/GID for it, and updates the custom mount table,
|
||||
* for it to stick in the machine, allocates a UID/GID for it, and updates the custom mount table,
|
||||
* to include an appropriate bind mount mapping.
|
||||
*
|
||||
* This extends the passed custom_mounts/n_custom_mounts with the home directories, and allocates a
|
||||
@ -265,13 +265,13 @@ int machine_bind_user_prepare(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to resolve group of user '%s': %m", u->user_name);
|
||||
|
||||
/* We want to synthesize exactly one user + group from the host into the container. This only
|
||||
/* We want to synthesize exactly one user + group from the host into the machine. This only
|
||||
* makes sense if the user on the host has its own private group. We can't reasonably check
|
||||
* this, so we just check of the name of user and group match.
|
||||
*
|
||||
* One of these days we might want to support users in a shared/common group too, but it's
|
||||
* not clear to me how this would have to be mapped, precisely given that the common group
|
||||
* probably already exists in the container. */
|
||||
* probably already exists in the machine. */
|
||||
if (!streq(u->user_name, g->group_name))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Sorry, mapping users without private groups is currently not supported.");
|
||||
|
||||
@ -115,6 +115,7 @@ shared_sources = files(
|
||||
'libmount-util.c',
|
||||
'local-addresses.c',
|
||||
'locale-setup.c',
|
||||
'log-assert-critical.c',
|
||||
'logs-show.c',
|
||||
'loop-util.c',
|
||||
'loopback-setup.c',
|
||||
|
||||
@ -400,8 +400,8 @@ int nsresource_add_netif_tap(
|
||||
return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), SD_JSON_MANDATORY },
|
||||
{ "interfaceFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(InterfaceParams, namespace_interface_name), SD_JSON_MANDATORY },
|
||||
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), SD_JSON_MANDATORY },
|
||||
{ "interfaceFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(InterfaceParams, interface_fd_index), SD_JSON_MANDATORY },
|
||||
};
|
||||
|
||||
_cleanup_(interface_params_done) InterfaceParams p = {};
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
#include "assert-util.h"
|
||||
#include "log.h"
|
||||
#include "log-assert-critical.h"
|
||||
#include "nss-util.h"
|
||||
|
||||
sd_json_dispatch_flags_t nss_json_dispatch_flags = SD_JSON_ALLOW_EXTENSIONS;
|
||||
|
||||
@ -449,12 +449,18 @@ int rm_rf_at(int dir_fd, const char *path, RemoveFlags flags) {
|
||||
if (FLAGS_SET(flags, REMOVE_MISSING_OK) && r == -ENOENT)
|
||||
return 0;
|
||||
|
||||
if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR))
|
||||
if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR, -EPERM, -EACCES))
|
||||
return r;
|
||||
|
||||
/* Not btrfs or not a subvolume */
|
||||
/* Not btrfs or not a subvolume, or permissions are not available (but might if we go via unlinkat()) */
|
||||
}
|
||||
|
||||
/* In the next step we'll try to open the directory in order to enumerate its contents. This might
|
||||
* not work due to perms, but we might still be able to delete it, hence let's try that first. */
|
||||
if (FLAGS_SET(flags, REMOVE_ROOT | REMOVE_PHYSICAL))
|
||||
if (unlinkat(dir_fd, path, AT_REMOVEDIR) >= 0)
|
||||
return 0;
|
||||
|
||||
fd = openat_harder(dir_fd, path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME, flags, &old_mode);
|
||||
if (fd >= 0) {
|
||||
/* We have a dir */
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "forward.h"
|
||||
#include "log.h"
|
||||
#include "log-assert-critical.h"
|
||||
#include "static-destruct.h"
|
||||
#include "signal-util.h"
|
||||
#include "stdio-util.h"
|
||||
|
||||
@ -1662,9 +1662,11 @@ static const ImagePolicy *pick_image_policy(const Image *img) {
|
||||
|
||||
/* If located in /.extra/ in the initrd, then it was placed there by systemd-stub, and was
|
||||
* picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the
|
||||
* other directories we assume the appropriate level of trust was already established already. */
|
||||
* other directories we assume the appropriate level of trust was already established.)
|
||||
* With --root= we default to the regular policy, though. (To change that, the check would need
|
||||
* to prepend (or cut away) arg_root.) */
|
||||
|
||||
if (in_initrd()) {
|
||||
if (in_initrd() && !arg_root) {
|
||||
if (path_startswith(img->path, "/.extra/sysext/"))
|
||||
return &image_policy_sysext_strict;
|
||||
if (path_startswith(img->path, "/.extra/global_sysext/"))
|
||||
@ -1860,13 +1862,19 @@ static int merge_subprocess(
|
||||
if (force)
|
||||
log_debug("Force mode enabled, skipping version validation.");
|
||||
else {
|
||||
bool is_initrd;
|
||||
r = chase_and_access("/etc/initrd-release", arg_root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to check for /etc/initrd-release: %m");
|
||||
is_initrd = r >= 0;
|
||||
|
||||
r = extension_release_validate(
|
||||
img->name,
|
||||
host_os_release_id,
|
||||
host_os_release_id_like,
|
||||
host_os_release_version_id,
|
||||
host_os_release_api_level,
|
||||
in_initrd() ? "initrd" : "system",
|
||||
is_initrd ? "initrd" : "system",
|
||||
image_extension_release(img, image_class),
|
||||
image_class);
|
||||
if (r < 0)
|
||||
|
||||
@ -44,7 +44,7 @@ int verb_add_dependency(int argc, char *argv[], void *userdata) {
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
if (install_client_side()) {
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
|
||||
@ -96,8 +96,28 @@ static int parse_shutdown_time_spec(const char *t, usec_t *ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while (s <= n)
|
||||
s += USEC_PER_DAY;
|
||||
if (s <= n) {
|
||||
/* The specified time is today, but in the past. We need to schedule it for tomorrow
|
||||
* at the same time. Adding USEC_PER_DAY would be wrong across DST changes, so just
|
||||
* let mktime() normalise it. */
|
||||
int requested_hour = tm.tm_hour;
|
||||
int requested_min = tm.tm_min;
|
||||
|
||||
tm.tm_mday++;
|
||||
tm.tm_isdst = -1;
|
||||
r = mktime_or_timegm_usec(&tm, /* utc= */ false, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (tm.tm_hour != requested_hour || tm.tm_min != requested_min) {
|
||||
log_warning("Requested shutdown time %02d:%02d does not exist. "
|
||||
"Rescheduling to %02d:%02d.",
|
||||
requested_hour,
|
||||
requested_min,
|
||||
tm.tm_hour,
|
||||
tm.tm_min);
|
||||
}
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
}
|
||||
|
||||
@ -370,7 +370,8 @@ int verb_edit(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!arg_no_reload && !install_client_side()) {
|
||||
if (!arg_no_reload &&
|
||||
install_client_side() == INSTALL_CLIENT_SIDE_NO) {
|
||||
r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -103,7 +103,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
|
||||
/* If the operation was fully executed by the SysV compat, let's finish early */
|
||||
if (strv_isempty(names)) {
|
||||
if (arg_no_reload || install_client_side())
|
||||
if (arg_no_reload || install_client_side() != INSTALL_CLIENT_SIDE_NO)
|
||||
return 0;
|
||||
|
||||
r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
|
||||
@ -119,41 +119,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (install_client_side()) {
|
||||
UnitFileFlags flags;
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
CLEANUP_ARRAY(changes, n_changes, install_changes_free);
|
||||
|
||||
flags = unit_file_flags_from_args();
|
||||
|
||||
if (streq(verb, "enable")) {
|
||||
r = unit_file_enable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "disable")) {
|
||||
r = unit_file_disable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "reenable")) {
|
||||
r = unit_file_reenable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "link"))
|
||||
r = unit_file_link(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "preset"))
|
||||
r = unit_file_preset(arg_runtime_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
|
||||
else if (streq(verb, "mask"))
|
||||
r = unit_file_mask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "unmask"))
|
||||
r = unit_file_unmask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "revert"))
|
||||
r = unit_file_revert(arg_runtime_scope, arg_root, names, &changes, &n_changes);
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
install_changes_dump(r, verb, changes, n_changes, arg_quiet);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
if (install_client_side() == INSTALL_CLIENT_SIDE_NO) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
bool expect_carries_install_info = false;
|
||||
@ -275,6 +241,40 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
if (warn_trigger_operation && !arg_quiet && !arg_no_warn)
|
||||
STRV_FOREACH(unit, names)
|
||||
warn_triggering_units(bus, *unit, warn_trigger_operation, warn_trigger_ignore_masked);
|
||||
} else {
|
||||
UnitFileFlags flags;
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
CLEANUP_ARRAY(changes, n_changes, install_changes_free);
|
||||
|
||||
flags = unit_file_flags_from_args();
|
||||
|
||||
if (streq(verb, "enable")) {
|
||||
r = unit_file_enable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "disable")) {
|
||||
r = unit_file_disable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "reenable")) {
|
||||
r = unit_file_reenable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
carries_install_info = r;
|
||||
} else if (streq(verb, "link"))
|
||||
r = unit_file_link(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "preset"))
|
||||
r = unit_file_preset(arg_runtime_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
|
||||
else if (streq(verb, "mask"))
|
||||
r = unit_file_mask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "unmask"))
|
||||
r = unit_file_unmask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
|
||||
else if (streq(verb, "revert"))
|
||||
r = unit_file_revert(arg_runtime_scope, arg_root, names, &changes, &n_changes);
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
install_changes_dump(r, verb, changes, n_changes, arg_quiet);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (carries_install_info == 0 && !ignore_carries_install_info)
|
||||
@ -334,7 +334,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
if (arg_now) {
|
||||
_cleanup_strv_free_ char **new_args = NULL;
|
||||
const char *start_verb;
|
||||
bool accept_path, prohibit_templates;
|
||||
bool accept_path, prohibit_templates, dead_ok = false;
|
||||
|
||||
if (streq(verb, "enable")) {
|
||||
start_verb = "start";
|
||||
@ -344,6 +344,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
start_verb = "stop";
|
||||
accept_path = false;
|
||||
prohibit_templates = false;
|
||||
dead_ok = true; /* If the service is not running anyway, no need to stop it. */
|
||||
} else if (streq(verb, "reenable")) {
|
||||
/* Note that we use try-restart here. This matches the semantics of reenable better,
|
||||
* and allows us to glob template units. */
|
||||
@ -354,9 +355,20 @@ int verb_enable(int argc, char *argv[], void *userdata) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"--now can only be used with verb enable, disable, reenable, or mask.");
|
||||
|
||||
if (install_client_side())
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
|
||||
"--now cannot be used when systemd is not running or in conjunction with --root=/--global, refusing.");
|
||||
switch (install_client_side()) {
|
||||
case INSTALL_CLIENT_SIDE_NO:
|
||||
break;
|
||||
case INSTALL_CLIENT_SIDE_OVERRIDE:
|
||||
case INSTALL_CLIENT_SIDE_OFFLINE:
|
||||
case INSTALL_CLIENT_SIDE_NOT_BOOTED:
|
||||
if (!dead_ok)
|
||||
log_warning("Cannot %s unit with --now when systemd is not running, ignoring.", start_verb);
|
||||
return 0;
|
||||
case INSTALL_CLIENT_SIDE_ARG_ROOT:
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "--now cannot be used with --root=.");
|
||||
case INSTALL_CLIENT_SIDE_GLOBAL_SCOPE:
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "--now cannot be used with --global.");
|
||||
}
|
||||
|
||||
assert(bus);
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
|
||||
not_found = r == 0; /* Doesn't have SysV support or SYSV_UNIT_NOT_FOUND */
|
||||
enabled = r == SYSV_UNIT_ENABLED;
|
||||
|
||||
if (install_client_side())
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO)
|
||||
STRV_FOREACH(name, names) {
|
||||
UnitFileState state;
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
|
||||
unsigned c = 0;
|
||||
int r;
|
||||
|
||||
if (install_client_side()) {
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
|
||||
unsigned n_units;
|
||||
|
||||
r = unit_file_get_list(arg_runtime_scope, arg_root, arg_states, strv_skip(argv, 1), &h);
|
||||
|
||||
@ -19,7 +19,7 @@ int verb_preset_all(int argc, char *argv[], void *userdata) {
|
||||
if (should_bypass("SYSTEMD_PRESET"))
|
||||
return 0;
|
||||
|
||||
if (install_client_side()) {
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ static void emit_cmdline_warning(void) {
|
||||
static int determine_default(char **ret_name) {
|
||||
int r;
|
||||
|
||||
if (install_client_side()) {
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
|
||||
r = unit_file_get_default(arg_runtime_scope, arg_root, ret_name);
|
||||
if (r == -ERFKILL)
|
||||
return log_error_errno(r, "Failed to get default target: Unit file is masked.");
|
||||
@ -116,7 +116,7 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
if (install_client_side()) {
|
||||
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
|
||||
@ -523,7 +523,7 @@ int unit_find_paths(
|
||||
|
||||
/* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
|
||||
if (!force_client_side &&
|
||||
!install_client_side() &&
|
||||
install_client_side() == INSTALL_CLIENT_SIDE_NO &&
|
||||
!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *load_state = NULL, *dbus_path = NULL;
|
||||
@ -880,26 +880,27 @@ bool output_show_unit(const UnitInfo *u, char **patterns) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool install_client_side(void) {
|
||||
/* Decides when to execute enable/disable/... operations client-side rather than server-side. */
|
||||
|
||||
if (running_in_chroot_or_offline())
|
||||
return true;
|
||||
|
||||
if (sd_booted() <= 0)
|
||||
return true;
|
||||
|
||||
if (!isempty(arg_root))
|
||||
return true;
|
||||
|
||||
if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL)
|
||||
return true;
|
||||
InstallClientSide install_client_side(void) {
|
||||
/* Decides whether to execute enable/disable/… client-side offline operation rather than
|
||||
* server-side. */
|
||||
|
||||
/* Unsupported environment variable, mostly for debugging purposes */
|
||||
if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
|
||||
return true;
|
||||
return INSTALL_CLIENT_SIDE_OVERRIDE;
|
||||
|
||||
return false;
|
||||
if (!isempty(arg_root))
|
||||
return INSTALL_CLIENT_SIDE_ARG_ROOT;
|
||||
|
||||
if (running_in_chroot_or_offline())
|
||||
return INSTALL_CLIENT_SIDE_OFFLINE;
|
||||
|
||||
if (sd_booted() <= 0)
|
||||
return INSTALL_CLIENT_SIDE_NOT_BOOTED;
|
||||
|
||||
if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL)
|
||||
return INSTALL_CLIENT_SIDE_GLOBAL_SCOPE;
|
||||
|
||||
return INSTALL_CLIENT_SIDE_NO;
|
||||
}
|
||||
|
||||
int output_table(Table *table) {
|
||||
|
||||
@ -69,7 +69,16 @@ int unit_get_dependencies(sd_bus *bus, const char *name, char ***ret);
|
||||
const char* unit_type_suffix(const char *unit);
|
||||
bool output_show_unit(const UnitInfo *u, char **patterns);
|
||||
|
||||
bool install_client_side(void);
|
||||
typedef enum InstallClientSide {
|
||||
INSTALL_CLIENT_SIDE_NO = 0,
|
||||
INSTALL_CLIENT_SIDE_OVERRIDE,
|
||||
INSTALL_CLIENT_SIDE_ARG_ROOT,
|
||||
INSTALL_CLIENT_SIDE_OFFLINE,
|
||||
INSTALL_CLIENT_SIDE_NOT_BOOTED,
|
||||
INSTALL_CLIENT_SIDE_GLOBAL_SCOPE,
|
||||
} InstallClientSide;
|
||||
|
||||
InstallClientSide install_client_side(void);
|
||||
|
||||
int output_table(Table *table);
|
||||
|
||||
|
||||
@ -445,8 +445,8 @@ def main() -> None:
|
||||
summary = Summary.get(args)
|
||||
|
||||
# Keep list in sync with TEST-06-SELINUX.sh
|
||||
if args.name == 'TEST-06-SELINUX' and summary.distribution not in ('fedora', 'centos'):
|
||||
print('Skipping TEST-06-SELINUX, only enabled for Fedora/CentOS', file=sys.stderr)
|
||||
if args.name == 'TEST-06-SELINUX' and summary.distribution not in ('centos', 'fedora', 'opensuse'):
|
||||
print('Skipping TEST-06-SELINUX, only enabled for CentOS/Fedora/openSUSE', file=sys.stderr)
|
||||
exit(77)
|
||||
|
||||
if shell and not sys.stdin.isatty():
|
||||
|
||||
@ -81,10 +81,10 @@ valgrind_cmd = ''
|
||||
enable_debug = True
|
||||
env = {}
|
||||
wait_online_env = {}
|
||||
asan_options = None
|
||||
lsan_options = None
|
||||
ubsan_options = None
|
||||
with_coverage = False
|
||||
asan_options = os.getenv('ASAN_OPTIONS')
|
||||
lsan_options = os.getenv('LSAN_OPTIONS')
|
||||
ubsan_options = os.getenv('UBSAN_OPTIONS')
|
||||
with_coverage = os.getenv('COVERAGE_BUILD_DIR') != None
|
||||
show_journal = True # When true, show journal on stopping networkd.
|
||||
|
||||
active_units = []
|
||||
@ -487,7 +487,19 @@ def create_service_dropin(service, command, additional_settings=None):
|
||||
if ubsan_options:
|
||||
drop_in += [f'Environment=UBSAN_OPTIONS="{ubsan_options}"']
|
||||
if asan_options or lsan_options or ubsan_options:
|
||||
drop_in += ['SystemCallFilter=']
|
||||
# Disable system call filter when running with sanitizers, as they seem to call filtered syscall at
|
||||
# the very end of the execution and stuck the process. See issue #39567.
|
||||
drop_in += [
|
||||
'LockPersonality=no',
|
||||
'ProtectClock=no',
|
||||
'ProtectKernelLogs=no',
|
||||
'RestrictAddressFamilies=',
|
||||
'RestrictNamespaces=no',
|
||||
'RestrictRealtime=no',
|
||||
'RestrictSUIDSGID=no',
|
||||
'SystemCallArchitectures=',
|
||||
'SystemCallFilter=',
|
||||
]
|
||||
if use_valgrind or asan_options or lsan_options or ubsan_options:
|
||||
drop_in += ['MemoryDenyWriteExecute=no']
|
||||
if use_valgrind:
|
||||
|
||||
@ -104,10 +104,12 @@ diff /tmp/expected /tmp/output
|
||||
|
||||
# test that LogLevelMax can also suppress logging about services, not only by services
|
||||
systemctl start silent-success
|
||||
journalctl --sync
|
||||
[[ -z "$(journalctl -b -q -u silent-success.service)" ]]
|
||||
|
||||
# Test syslog identifiers exclusion
|
||||
systemctl start verbose-success.service
|
||||
journalctl --sync
|
||||
[[ -n "$(journalctl -b -q -u verbose-success.service -t systemd)" ]]
|
||||
[[ -n "$(journalctl -b -q -u verbose-success.service -t bash)" ]]
|
||||
[[ -n "$(journalctl -b -q -u verbose-success.service -T systemd)" ]]
|
||||
|
||||
@ -4,8 +4,8 @@ set -eux
|
||||
set -o pipefail
|
||||
|
||||
. /etc/os-release
|
||||
if ! [[ "$ID" =~ centos|fedora ]]; then
|
||||
echo "Skipping because only CentOS and Fedora support SELinux tests" >>/skipped
|
||||
if ! [[ "$ID" =~ centos|fedora|opensuse ]]; then
|
||||
echo "Skipping because only CentOS, Fedora and openSUSE support SELinux tests" >>/skipped
|
||||
exit 77
|
||||
fi
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ assert_eq "$(systemctl show "$UNIT_NAME.socket" -P SubState)" "listening"
|
||||
|
||||
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
|
||||
wait_for_start
|
||||
kill %%
|
||||
wait %%
|
||||
|
||||
touch "/tmp/$UNIT_NAME/flag"
|
||||
systemctl start "$UNIT_NAME-conflict2.service"
|
||||
@ -80,7 +80,7 @@ wait_for_stop
|
||||
|
||||
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
|
||||
wait_for_start
|
||||
kill %%
|
||||
wait %%
|
||||
(! systemctl -q is-active "$UNIT_NAME-conflict2.service")
|
||||
|
||||
# DeferTrigger=yes
|
||||
@ -99,7 +99,7 @@ assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
|
||||
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
|
||||
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
|
||||
(! systemctl -q is-active "$UNIT_NAME.service")
|
||||
kill %%
|
||||
wait %%
|
||||
assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
|
||||
|
||||
systemctl daemon-reload
|
||||
@ -122,7 +122,7 @@ wait_for_stop
|
||||
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
|
||||
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
|
||||
(! systemctl -q is-active "$UNIT_NAME.service")
|
||||
kill %%
|
||||
wait %%
|
||||
|
||||
rm "/tmp/$UNIT_NAME/flag"
|
||||
timeout 30 bash -c "while systemctl -q is-active '$UNIT_NAME-conflict2.service'; do sleep .2; done"
|
||||
@ -138,7 +138,7 @@ assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
|
||||
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
|
||||
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
|
||||
(! systemctl -q is-active "$UNIT_NAME.service")
|
||||
kill %%
|
||||
wait %%
|
||||
|
||||
echo "DeferTriggerMaxSec=20s" >>/run/systemd/system/"$UNIT_NAME.socket"
|
||||
systemctl daemon-reload
|
||||
|
||||
@ -50,6 +50,7 @@ trap 'touch /terminate; kill 0' RTMIN+3
|
||||
trap 'touch /poweroff' RTMIN+4
|
||||
trap 'touch /reboot' INT
|
||||
trap 'touch /trap' TRAP
|
||||
trap 'exit 0' TERM
|
||||
trap 'kill $PID' EXIT
|
||||
|
||||
# We need to wait for the sleep process asynchronously in order to allow
|
||||
@ -327,6 +328,7 @@ ip address add 192.0.2.1/24 dev hoge
|
||||
PID=0
|
||||
|
||||
trap 'kill 0' RTMIN+3
|
||||
trap 'exit 0' TERM
|
||||
trap 'kill $PID' EXIT
|
||||
|
||||
# We need to wait for the sleep process asynchronously in order to allow
|
||||
@ -441,9 +443,14 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.OpenR
|
||||
|
||||
# Terminating machine, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
|
||||
machinectl terminate long-running
|
||||
# wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
|
||||
timeout 30 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
|
||||
systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
|
||||
# Wait for the container to stop, otherwise acquiring image metadata by io.systemd.MachineImage.List below
|
||||
# may fail.
|
||||
#
|
||||
# We need to wait until the systemd-nspawn process is completely stopped, as the lock is held for almost the
|
||||
# entire life of the process (see the run() function in nspawn.c). This means that the machine gets
|
||||
# unregistered _before_ this lock is lifted which makes `machinectl status` return non-zero EC earlier than
|
||||
# we need.
|
||||
timeout 30 bash -xec 'until [[ "$(systemctl show -P ActiveState systemd-nspawn@long-running.service)" == inactive ]]; do sleep .5; done'
|
||||
|
||||
# test io.systemd.MachineImage.List
|
||||
varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep 'long-running'
|
||||
|
||||
@ -9,18 +9,6 @@ set -o pipefail
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
# Requires kernel built with certain kconfigs, as listed in README:
|
||||
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
|
||||
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
|
||||
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
|
||||
( . /etc/os-release; [ "$ID" != "debian" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
|
||||
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
|
||||
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
|
||||
verity_sig_supported=1
|
||||
else
|
||||
verity_sig_supported=0
|
||||
fi
|
||||
|
||||
systemd-dissect --json=short "$MINIMAL_IMAGE.raw" | \
|
||||
grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
|
||||
systemd-dissect "$MINIMAL_IMAGE.raw" | grep -q -F "MARKER=1"
|
||||
@ -84,7 +72,7 @@ if [[ "$verity_count" -lt 1 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
# Ensure the kernel is verifying the signature if the mkosi key is in the keyring
|
||||
if [ "$verity_sig_supported" -eq 1 ]; then
|
||||
if [ "$VERITY_SIG_SUPPORTED" -eq 1 ]; then
|
||||
veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)"
|
||||
fi
|
||||
systemd-dissect --umount "$IMAGE_DIR/mount"
|
||||
@ -472,8 +460,8 @@ RootImage=$MINIMAL_IMAGE.raw
|
||||
ExtensionImages=/tmp/app0.raw /tmp/app1.raw:nosuid
|
||||
# Relevant only for sanitizer runs
|
||||
UnsetEnvironment=LD_PRELOAD
|
||||
ExecStart=bash -c '/opt/script0.sh | grep ID'
|
||||
ExecStart=bash -c '/opt/script1.sh | grep ID'
|
||||
ExecStart=bash -o pipefail -c '/opt/script0.sh | grep ID'
|
||||
ExecStart=bash -o pipefail -c '/opt/script1.sh | grep ID'
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
EOF
|
||||
@ -490,7 +478,7 @@ mkdir "$VDIR" "$EMPTY_VDIR"
|
||||
ln -s /tmp/app0.raw "$VDIR/${VBASE}_0.raw"
|
||||
ln -s /tmp/app1.raw "$VDIR/${VBASE}_1.raw"
|
||||
|
||||
systemd-run -P -p ExtensionImages="$VDIR -$EMPTY_VDIR -$NONEXISTENT_VDIR" bash -c '/opt/script1.sh | grep ID'
|
||||
systemd-run -P -p ExtensionImages="$VDIR -$EMPTY_VDIR -$NONEXISTENT_VDIR" bash -o pipefail -c '/opt/script1.sh | grep ID'
|
||||
|
||||
rm -rf "$VDIR" "$EMPTY_VDIR"
|
||||
|
||||
@ -587,7 +575,7 @@ EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
|
||||
PrivateTmp=disconnected
|
||||
BindPaths=/tmp/markers/
|
||||
ExtensionDirectories=-${VDIR}
|
||||
ExecStart=bash -x -c ' \\
|
||||
ExecStart=bash -o pipefail -x -c ' \\
|
||||
trap "{ \\
|
||||
systemd-notify --reloading; \\
|
||||
(ls /etc | grep marker || echo no-marker) >/tmp/markers/50g; \\
|
||||
@ -628,7 +616,7 @@ EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
|
||||
PrivateTmp=disconnected
|
||||
BindPaths=/tmp/markers/
|
||||
ExtensionImages=-$VDIR2
|
||||
ExecStart=bash -x -c ' \\
|
||||
ExecStart=bash -o pipefail -x -c ' \\
|
||||
trap "{ \\
|
||||
systemd-notify --reloading; \\
|
||||
(ls /etc | grep marker || echo no-marker) >/tmp/markers/50h; \\
|
||||
@ -666,7 +654,7 @@ BindPaths=/tmp/markers/
|
||||
RootImage=$MINIMAL_IMAGE.raw
|
||||
ExtensionDirectories=-${VDIR}
|
||||
NotifyAccess=all
|
||||
ExecStart=bash -x -c ' \
|
||||
ExecStart=bash -x -o pipefail -c ' \
|
||||
trap '"'"' \
|
||||
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
|
||||
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
|
||||
@ -701,7 +689,7 @@ BindPaths=/tmp/markers/
|
||||
RootDirectory=/tmp/vpickminimg
|
||||
ExtensionDirectories=-${VDIR}
|
||||
NotifyAccess=all
|
||||
ExecStart=bash -x -c ' \
|
||||
ExecStart=bash -x -o pipefail -c ' \
|
||||
trap '"'"' \
|
||||
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
|
||||
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
|
||||
@ -731,7 +719,7 @@ RootImage=$MINIMAL_IMAGE.raw
|
||||
ExtensionImages=-$VDIR2 /tmp/app0.raw
|
||||
PrivateUsers=yes
|
||||
NotifyAccess=all
|
||||
ExecStart=bash -x -c ' \
|
||||
ExecStart=bash -x -o pipefail -c ' \
|
||||
trap '"'"' \
|
||||
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
|
||||
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
|
||||
@ -746,7 +734,7 @@ EOF
|
||||
systemctl start testservice-50k.service
|
||||
systemctl is-active testservice-50k.service
|
||||
# Ensure the kernel is verifying the signature if the mkosi key is in the keyring
|
||||
if [ "$verity_sig_supported" -eq 1 ]; then
|
||||
if [ "$VERITY_SIG_SUPPORTED" -eq 1 ]; then
|
||||
veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)"
|
||||
fi
|
||||
# First reload should pick up the v1 marker
|
||||
|
||||
@ -25,10 +25,27 @@ at_exit() {
|
||||
done < <(find "${IMAGE_DIR}" -mindepth 1 -maxdepth 1 -type d)
|
||||
|
||||
rm -rf "$IMAGE_DIR"
|
||||
|
||||
loginctl disable-linger testuser
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
|
||||
# For unprivileged tests
|
||||
loginctl enable-linger testuser
|
||||
|
||||
# Requires kernel built with certain kconfigs, as listed in README:
|
||||
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
|
||||
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
|
||||
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
|
||||
( . /etc/os-release; [ "$ID" != "debian" ] || [ -z "${VERSION_ID:-}" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
|
||||
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
|
||||
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
|
||||
export VERITY_SIG_SUPPORTED=1
|
||||
else
|
||||
export VERITY_SIG_SUPPORTED=0
|
||||
fi
|
||||
|
||||
: "Setup base images"
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
@ -102,6 +119,7 @@ fi
|
||||
udevadm control --log-level=debug
|
||||
|
||||
IMAGE_DIR="$(mktemp -d --tmpdir="" TEST-50-IMAGES.XXX)"
|
||||
chmod go+rx "$IMAGE_DIR"
|
||||
cp -v /usr/share/minimal* "$IMAGE_DIR/"
|
||||
MINIMAL_IMAGE="$IMAGE_DIR/minimal_0"
|
||||
MINIMAL_IMAGE_ROOTHASH="$(<"$MINIMAL_IMAGE.roothash")"
|
||||
|
||||
@ -1064,10 +1064,13 @@ extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
|
||||
fake_root=${roots_dir:+"$roots_dir/mutable-directory-with-invalid-permissions"}
|
||||
hierarchy=/opt
|
||||
extension_data_dir="$fake_root/var/lib/extensions.mutable$hierarchy"
|
||||
extension_data_dir_usr="$fake_root/var/lib/extensions.mutable/usr"
|
||||
|
||||
prepare_root "$fake_root" "$hierarchy"
|
||||
prepare_extension_image "$fake_root" "$hierarchy"
|
||||
prepare_extension_mutable_dir "$extension_data_dir"
|
||||
prepend_trap "rm -rf ${extension_data_dir@Q}"
|
||||
prepend_trap "rm -rf ${extension_data_dir_usr@Q}"
|
||||
prepare_hierarchy "$fake_root" "$hierarchy"
|
||||
|
||||
old_mode=$(stat --format '%#a' "$fake_root$hierarchy")
|
||||
@ -1078,6 +1081,29 @@ chmod 0700 "$extension_data_dir"
|
||||
(! run_systemd_sysext "$fake_root" --mutable=yes merge)
|
||||
)
|
||||
|
||||
( init_trap
|
||||
: "Check if merging fails in case of --root= being an initrd but the extension is not for it"
|
||||
# Since this is really about whether --root= gets prepended for the /etc/initrd-release check,
|
||||
# this also tests the more interesting reverse case that we are in the initrd and prepare
|
||||
# the mounts for the final system with --root=/sysroot
|
||||
fake_root=${roots_dir:+"$roots_dir/initrd-env-with-non-initrd-extension"}
|
||||
hierarchy=/opt
|
||||
|
||||
prepare_root "$fake_root" "$hierarchy"
|
||||
prepare_extension_image "$fake_root" "$hierarchy"
|
||||
mkdir -p "${fake_root}/etc"
|
||||
touch "${fake_root}/etc/initrd-release"
|
||||
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
|
||||
|
||||
# Should be a no-op, thus we also don't run unmerge afterwards (otherwise the test is broken)
|
||||
run_systemd_sysext "$fake_root" merge
|
||||
if run_systemd_sysext "$fake_root" status --json=pretty | jq -r '.[].extensions' | grep -v '^none$' ; then
|
||||
echo >&2 "Extension got loaded for an initrd structure passed as --root= while the extension does not declare itself compatible with the initrd scope"
|
||||
exit 1
|
||||
fi
|
||||
rm "${fake_root}/etc/initrd-release"
|
||||
)
|
||||
|
||||
} # End of run_sysext_tests
|
||||
|
||||
|
||||
|
||||
@ -15,11 +15,11 @@ set -o pipefail
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
UNIT_NAME="timer-RandomizedDelaySec-$RANDOM"
|
||||
TARGET_TS="$(date --date="tomorrow 00:10")"
|
||||
TARGET_TS="$(date --date="tomorrow 00:10" "+%a %Y-%m-%d %H:%M:%S %Z")"
|
||||
TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")"
|
||||
# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=)
|
||||
MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))"
|
||||
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")"
|
||||
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S" "+%a %Y-%m-%d %H:%M:%S %Z")"
|
||||
|
||||
# Let's make sure to return the date & time back to the original state once we're done with our time
|
||||
# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to
|
||||
|
||||
@ -19,7 +19,7 @@ systemd-analyze time || :
|
||||
systemd-analyze critical-chain || :
|
||||
# blame
|
||||
systemd-analyze blame
|
||||
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame
|
||||
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame --no-pager
|
||||
(! systemd-analyze blame --global)
|
||||
# plot
|
||||
systemd-analyze plot >/dev/null || :
|
||||
|
||||
@ -15,7 +15,7 @@ fi
|
||||
"$SD_TPM2SETUP" --version
|
||||
"$SD_TPM2SETUP" --tpm2-device=list
|
||||
"$SD_TPM2SETUP" --tpm2-device=auto
|
||||
"$SD_TPM2SETUP" --tpm2-device=/dev/tpm0
|
||||
"$SD_TPM2SETUP" --tpm2-device=/dev/tpmrm0
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=yes
|
||||
"$SD_TPM2SETUP" --early=no
|
||||
|
||||
@ -81,6 +81,11 @@ systemd-run --wait --pipe --user --machine=testuser@ \
|
||||
systemd-run --wait --pipe --user --machine=testuser@ \
|
||||
bash -xec '[[ "$PWD" == /home/testuser && -n "$INVOCATION_ID" ]]'
|
||||
|
||||
# https://github.com/systemd/systemd/issues/39038
|
||||
systemd-run --wait --machine=testuser@ --user -p User=testuser true
|
||||
systemd-run --wait --machine=testuser@ --user -p Group=testuser true
|
||||
(! systemd-run --wait --machine=testuser@ --user -p Group=testuser -p SupplementaryGroups=root true)
|
||||
|
||||
# PrivateTmp=yes implies PrivateUsers=yes for user manager, so skip this if we
|
||||
# don't have unprivileged user namespaces.
|
||||
if [[ "$(sysctl -ne kernel.apparmor_restrict_unprivileged_userns)" -ne 1 ]]; then
|
||||
|
||||
@ -11,7 +11,7 @@ assert_in systemd-socket "$(cat /proc/"$PID"/comm)"
|
||||
assert_eq "$(echo -n hello | socat - 'TCP:localhost:1234')" hello
|
||||
assert_in systemd-socket "$(cat /proc/"$PID"/comm)"
|
||||
kill "$PID"
|
||||
wait "$PID" || :
|
||||
tail --pid="$PID" -f /dev/null
|
||||
|
||||
PID=$(systemd-notify --fork -- systemd-socket-activate -l 1234 --now socat ACCEPT-FD:3 PIPE)
|
||||
for _ in {1..100}; do
|
||||
@ -24,7 +24,7 @@ for _ in {1..100}; do
|
||||
|
||||
if [[ "$(cat /proc/"$PID"/comm || :)" =~ socat ]]; then
|
||||
assert_eq "$(echo -n bye | socat - 'TCP:localhost:1234')" bye
|
||||
wait "$PID" || :
|
||||
tail --pid="$PID" -f /dev/null
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
@ -64,11 +64,13 @@ monitor_check_rr() (
|
||||
)
|
||||
|
||||
restart_resolved() {
|
||||
systemctl stop systemd-resolved-monitor.socket systemd-resolved-varlink.socket
|
||||
systemctl stop systemd-resolved.service
|
||||
(! systemctl is-failed systemd-resolved.service)
|
||||
# Reset the restart counter since we call this method a bunch of times
|
||||
# and can occasionally hit the default rate limit
|
||||
systemctl reset-failed systemd-resolved.service
|
||||
systemctl start systemd-resolved-monitor.socket systemd-resolved-varlink.socket
|
||||
systemctl start systemd-resolved.service
|
||||
systemctl service-log-level systemd-resolved.service debug
|
||||
}
|
||||
@ -183,8 +185,8 @@ EOF
|
||||
chown -R knot:knot /run/knot
|
||||
fi
|
||||
systemctl start knot
|
||||
# Wait a bit for the keys to propagate
|
||||
sleep 4
|
||||
# Wait for signed.test's zone DS records to get pushed to the parent zone
|
||||
timeout 30s bash -xec 'until knotc zone-read test. signed.test. ds | grep -E "signed\.test\. [0-9]+ DS"; do sleep 2; done'
|
||||
|
||||
systemctl status resolved-dummy-server
|
||||
networkctl status
|
||||
@ -334,6 +336,7 @@ manual_testcase_02_mdns_llmnr() {
|
||||
} >/run/systemd/resolved.conf.d/90-mdns-llmnr.conf
|
||||
restart_resolved
|
||||
# make sure networkd is not running.
|
||||
systemctl stop systemd-networkd.socket systemd-networkd-varlink.socket
|
||||
systemctl stop systemd-networkd.service
|
||||
assert_in 'no' "$(resolvectl mdns hoge)"
|
||||
assert_in 'no' "$(resolvectl llmnr hoge)"
|
||||
@ -1368,7 +1371,9 @@ testcase_15_wait_online_dns() {
|
||||
resolvectl domain dns0 ""
|
||||
|
||||
# Stop systemd-resolved before calling systemd-networkd-wait-online. It should retry connections.
|
||||
systemctl stop systemd-resolved-monitor.socket systemd-resolved-varlink.socket
|
||||
systemctl stop systemd-resolved.service
|
||||
systemctl start systemd-resolved-monitor.socket systemd-resolved-varlink.socket
|
||||
|
||||
# Begin systemd-networkd-wait-online --dns
|
||||
systemd-run -u "$unit" -p "Environment=SYSTEMD_LOG_LEVEL=debug" -p "Environment=SYSTEMD_LOG_TARGET=journal" --service-type=exec \
|
||||
|
||||
@ -342,7 +342,8 @@ EOF
|
||||
bootctl remove
|
||||
}
|
||||
|
||||
testcase_secureboot() {
|
||||
# Order this first, as other test cases mess with the ESP and might break 'bootctl status' output
|
||||
testcase_00_secureboot() {
|
||||
if [ ! -d /sys/firmware/efi ]; then
|
||||
echo "Not booted with EFI, skipping secureboot tests."
|
||||
return 0
|
||||
|
||||
@ -163,7 +163,7 @@ rm -f /tmp/core.{output,redirected}
|
||||
|
||||
# Unprivileged stuff
|
||||
# Related issue: https://github.com/systemd/systemd/issues/26912
|
||||
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --)
|
||||
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" -E SYSTEMD_PAGER --)
|
||||
# Trigger a couple of coredumps as an unprivileged user
|
||||
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
|
||||
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
(! journalctl -q -o short-monotonic --grep "didn't pass validation" | grep -v "test-varlink-idl" >>/failed)
|
||||
(! journalctl -q -o short-monotonic --grep "didn't pass validation" | grep -v "test-varlink-idl")
|
||||
|
||||
# Here, the redundant '[ ]' in the pattern is required in order not to match the logged command itself.
|
||||
(! journalctl -q -o short-monotonic --grep 'Warning: cannot close sd-bus connection[ ].*after fork' >>/failed)
|
||||
(! journalctl -q -o short-monotonic --grep 'Warning: cannot close sd-bus connection[ ].*after fork')
|
||||
|
||||
# Check if sd-executor doesn't complain about not being able to (de)serialize stuff
|
||||
(! journalctl -q -o short-monotonic --grep "[F]ailed to parse serialized line" >>/failed)
|
||||
(! journalctl -q -o short-monotonic --grep "[F]ailed to (de)?serialize \w+" >>/failed)
|
||||
(! journalctl -q -o short-monotonic --grep "[F]ailed to parse serialized line")
|
||||
(! journalctl -q -o short-monotonic --grep "[F]ailed to (de)?serialize \w+")
|
||||
|
||||
@ -323,6 +323,13 @@ EOF
|
||||
echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file"
|
||||
mksquashfs "$initdir" /tmp/app0.raw -noappend
|
||||
veritysetup format /tmp/app0.raw /tmp/app0.verity --root-hash-file /tmp/app0.roothash
|
||||
openssl smime -sign -nocerts -noattr -binary \
|
||||
-in /tmp/app0.roothash \
|
||||
-inkey /usr/share/mkosi.key \
|
||||
-signer /usr/share/mkosi.crt \
|
||||
-outform der \
|
||||
-out /tmp/app0.roothash.p7s
|
||||
chmod go+r /tmp/app0*
|
||||
|
||||
initdir="/var/tmp/conf0"
|
||||
mkdir -p "$initdir/etc/extension-release.d" "$initdir/etc/systemd/system" "$initdir/opt"
|
||||
@ -335,6 +342,13 @@ EOF
|
||||
echo MARKER_1 >"$initdir/etc/systemd/system/some_file"
|
||||
mksquashfs "$initdir" /tmp/conf0.raw -noappend
|
||||
veritysetup format /tmp/conf0.raw /tmp/conf0.verity --root-hash-file /tmp/conf0.roothash
|
||||
openssl smime -sign -nocerts -noattr -binary \
|
||||
-in /tmp/conf0.roothash \
|
||||
-inkey /usr/share/mkosi.key \
|
||||
-signer /usr/share/mkosi.crt \
|
||||
-outform der \
|
||||
-out /tmp/conf0.roothash.p7s
|
||||
chmod go+r /tmp/conf0*
|
||||
|
||||
initdir="/var/tmp/app1"
|
||||
mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Generate network units from Kernel command line
|
||||
Description=Generate Network Units from Kernel Command Line
|
||||
Documentation=man:systemd-network-generator.service(8)
|
||||
|
||||
DefaultDependencies=no
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user