New upstream version 246.6

This commit is contained in:
Michael Biebl 2020-09-21 18:40:40 +02:00
parent 7de6915edf
commit 883b242a8a
33 changed files with 199 additions and 84 deletions

3
TODO
View File

@ -581,6 +581,9 @@ Features:
* sd-bus: add vtable flag, that may be used to request client creds implicitly * sd-bus: add vtable flag, that may be used to request client creds implicitly
and asynchronously before dispatching the operation and asynchronously before dispatching the operation
* sd-bus: parse addresses given in sd_bus_set_addresses immediately and not
only when used. Add unit tests.
* make use of ethtool veth peer info in machined, for automatically finding out * make use of ethtool veth peer info in machined, for automatically finding out
host-side interface pointing to the container. host-side interface pointing to the container.

View File

@ -10,3 +10,4 @@
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@> <!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@> <!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
<!ENTITY DEBUGTTY @DEBUGTTY@> <!ENTITY DEBUGTTY @DEBUGTTY@>
<!ENTITY RC_LOCAL_PATH @RC_LOCAL_PATH@>

View File

@ -556,10 +556,13 @@
<listitem><para>Takes a file system path. Configures where to place the user's home directory. When <listitem><para>Takes a file system path. Configures where to place the user's home directory. When
LUKS2 storage is used refers to the path to the loopback file, otherwise to the path to the home LUKS2 storage is used refers to the path to the loopback file, otherwise to the path to the home
directory. When unspecified defaults to <filename>/home/$USER.home</filename> when LUKS storage is directory (which may be in <filename>/home/</filename> or any other accessible filesystem). When
used and <filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for unspecified defaults to <filename>/home/$USER.home</filename> when LUKS storage is used and
the <literal>cifs</literal> storage mechanism. To use LUKS2 storage on a regular block device (for <filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for the
example a USB stick) pass the path to the block device here.</para></listitem> <literal>cifs</literal> storage mechanism. To use LUKS2 storage on a regular block device (for
example a USB stick) pass the path to the block device here. Specifying the path to a directory here
when using LUKS2 storage is not allowed. Similar, specifying the path to a regular file or device
node is not allowed if any of the other storage backends are used.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -1,8 +1,11 @@
<?xml version="1.0"?> <?xml version='1.0'?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
<!ENTITY % entities SYSTEM "custom-entities.ent" >
%entities;
]>
<!-- SPDX-License-Identifier: LGPL-2.1+ --> <!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'> <refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'>
<refentryinfo> <refentryinfo>
<title>systemd-rc-local-generator</title> <title>systemd-rc-local-generator</title>
@ -16,7 +19,7 @@
<refnamediv> <refnamediv>
<refname>systemd-rc-local-generator</refname> <refname>systemd-rc-local-generator</refname>
<refpurpose>Compatibility generator for starting <filename>/etc/rc.local</filename> during boot</refpurpose> <refpurpose>Compatibility generator for starting <filename>&RC_LOCAL_PATH;</filename> during boot</refpurpose>
</refnamediv> </refnamediv>
<refsynopsisdiv> <refsynopsisdiv>
@ -27,17 +30,17 @@
<title>Description</title> <title>Description</title>
<para><filename>systemd-rc-local-generator</filename> is a generator that checks whether <para><filename>systemd-rc-local-generator</filename> is a generator that checks whether
<filename>/etc/rc.local</filename> exists and is executable, and if it is pulls the <filename>&RC_LOCAL_PATH;</filename> exists and is executable, and if it is pulls the
<filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running this script <filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running
during late boot. Note that the script will be run with slightly different semantics than the original System V this script during late boot. Note that the script will be run with slightly different semantics than the
version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The original System V version, which was run "last" in the boot process, which is a concept that does not
script is run after <filename>network.target</filename>, but in parallel with most other regular system translate to systemd. The script is run after <filename>network.target</filename>, but in parallel with
services.</para> most other regular system services.</para>
<para>Support for <filename>/etc/rc.local</filename> is provided <para>Support for <filename>&RC_LOCAL_PATH;</filename> is provided for compatibility with specific System
for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of V systems only. However, it is strongly recommended to avoid making use of this script today, and instead
this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run provide proper unit files with appropriate dependencies for any scripts to run during the boot process.
during the boot process.</para> Note that the path to the script is set a compile time and varies between distributions.</para>
<para><filename>systemd-rc-local-generator</filename> implements <para><filename>systemd-rc-local-generator</filename> implements
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>

View File

@ -335,18 +335,14 @@
<varlistentry> <varlistentry>
<term><varname>RemainAfterElapse=</varname></term> <term><varname>RemainAfterElapse=</varname></term>
<listitem><para>Takes a boolean argument. If true, an elapsed <listitem><para>Takes a boolean argument. If true, a timer will stay loaded, and its state remains
timer will stay loaded, and its state remains queryable. If queryable even after it elapsed and the associated unit (as configured with <varname>Unit=</varname>,
false, an elapsed timer unit that cannot elapse anymore is see above) deactivated again. If false, an elapsed timer unit that cannot elapse anymore is unloaded
unloaded. Turning this off is particularly useful for once its associated unit deactivated again. Turning this off is particularly useful for transient
transient timer units that shall disappear after they first timer units. Note that this setting has an effect when repeatedly starting a timer unit: if
elapse. Note that this setting has an effect on repeatedly <varname>RemainAfterElapse=</varname> is on, starting the timer a second time has no effect. However,
starting a timer unit that only elapses once: if if <varname>RemainAfterElapse=</varname> is off and the timer unit was already unloaded, it can be
<varname>RemainAfterElapse=</varname> is on, it will not be started again, and thus the service can be triggered multiple times. Defaults to
started again, and is guaranteed to elapse only once. However,
if <varname>RemainAfterElapse=</varname> is off, it might be
started again if it is already elapsed, and thus be triggered
multiple times. Defaults to
<varname>yes</varname>.</para></listitem> <varname>yes</varname>.</para></listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -209,7 +209,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysc
conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir)
conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper()) conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
@ -296,7 +296,7 @@ substs.set('CERTIFICATEROOT', get_option('certif
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path) substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) substs.set('RC_LOCAL_PATH', get_option('rc-local'))
substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no') substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default) substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE')) substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE'))

View File

@ -209,17 +209,21 @@ static int parse_env_file_internal(
case DOUBLE_QUOTE_VALUE_ESCAPE: case DOUBLE_QUOTE_VALUE_ESCAPE:
state = DOUBLE_QUOTE_VALUE; state = DOUBLE_QUOTE_VALUE;
if (c == '"') { if (strchr(SHELL_NEED_ESCAPE, c)) {
/* If this is a char that needs escaping, just unescape it. */
if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
return -ENOMEM; return -ENOMEM;
value[n_value++] = '"'; value[n_value++] = c;
} else if (!strchr(NEWLINE, c)) { } else if (c != '\n') {
/* If other char than what needs escaping, keep the "\" in place, like the
* real shell does. */
if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
return -ENOMEM; return -ENOMEM;
value[n_value++] = '\\'; value[n_value++] = '\\';
value[n_value++] = c; value[n_value++] = c;
} }
/* Escaped newlines (aka "continuation lines") are eaten up entirely */
break; break;
case COMMENT: case COMMENT:

View File

@ -3,11 +3,7 @@
set -eu set -eu
for i in *.h */*.h; do for i in *.h */*.h; do
if [[ $i == 'wireguard.h' ]]; then curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
curl https://raw.githubusercontent.com/WireGuard/WireGuard/master/src/uapi/$i -o $i
else
curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
fi
sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
done done

View File

@ -635,6 +635,7 @@ int fd_set_sndbuf(int fd, size_t n, bool increase) {
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size. /* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */ * So, we need to check the actual buffer size here. */
l = sizeof(value);
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1; return 1;
@ -665,6 +666,7 @@ int fd_set_rcvbuf(int fd, size_t n, bool increase) {
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size. /* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */ * So, we need to check the actual buffer size here. */
l = sizeof(value);
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1; return 1;

View File

@ -1472,7 +1472,9 @@ static int install_random_seed(const char *esp) {
} }
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size); r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size);
if (r < 0) { if (r == -ENODATA)
log_debug_errno(r, "LoaderSystemToken EFI variable is invalid (too short?), replacing.");
else if (r < 0) {
if (r != -ENOENT) if (r != -ENOENT)
return log_error_errno(r, "Failed to test system token validity: %m"); return log_error_errno(r, "Failed to test system token validity: %m");
} else { } else {

View File

@ -2396,7 +2396,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0); assert(argc >= 0);
assert(argv); assert(argv);
while ((c = getopt_long(argc, argv, "hH:M:qj", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "hH:M:qjl", options, NULL)) >= 0)
switch (c) { switch (c) {

View File

@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
assert(other); assert(other);
/* Filter out invocations with bogus state */ /* Filter out invocations with bogus state */
if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
return; assert(other->type == UNIT_MOUNT);
/* Don't propagate state changes from the mount if we are already down */ /* Don't propagate state changes from the mount if we are already down */
if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))

View File

@ -748,10 +748,23 @@ static void path_trigger_notify(Unit *u, Unit *other) {
assert(u); assert(u);
assert(other); assert(other);
/* Invoked whenever the unit we trigger changes state or gains /* Invoked whenever the unit we trigger changes state or gains or loses a job */
* or loses a job */
if (other->load_state != UNIT_LOADED) /* Filter out invocations with bogus state */
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
/* Don't propagate state changes from the triggered unit if we are already down */
if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
return;
/* Propagate start limit hit state */
if (other->start_limit_hit) {
path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT);
return;
}
/* Don't propagate anything if there's still a job queued */
if (other->job)
return; return;
if (p->state == PATH_RUNNING && if (p->state == PATH_RUNNING &&
@ -790,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
[PATH_SUCCESS] = "success", [PATH_SUCCESS] = "success",
[PATH_FAILURE_RESOURCES] = "resources", [PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
}; };
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);

View File

@ -45,6 +45,7 @@ typedef enum PathResult {
PATH_SUCCESS, PATH_SUCCESS,
PATH_FAILURE_RESOURCES, PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT, PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
_PATH_RESULT_MAX, _PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -1 _PATH_RESULT_INVALID = -1
} PathResult; } PathResult;

View File

@ -3284,13 +3284,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
assert(other); assert(other);
/* Filter out invocations with bogus state */ /* Filter out invocations with bogus state */
if (!IN_SET(other->load_state, assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
UNIT_LOADED, assert(other->type == UNIT_SERVICE);
UNIT_NOT_FOUND,
UNIT_BAD_SETTING,
UNIT_ERROR,
UNIT_MASKED) || other->type != UNIT_SERVICE)
return;
/* Don't propagate state changes from the service if we are already down */ /* Don't propagate state changes from the service if we are already down */
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)) if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))

View File

@ -746,8 +746,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
assert(u); assert(u);
assert(other); assert(other);
if (other->load_state != UNIT_LOADED) /* Filter out invocations with bogus state */
return; assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
/* Reenable all timers that depend on unit state */ /* Reenable all timers that depend on unit state */
LIST_FOREACH(value, v, t->values) LIST_FOREACH(value, v, t->values)

View File

@ -949,7 +949,7 @@ int transaction_add_job_and_dependencies(
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
* temporarily. */ * temporarily. */
if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED)) if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
if (type != JOB_STOP) { if (type != JOB_STOP) {

View File

@ -49,6 +49,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED); return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
} }
static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;
}
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
* created as a result of multiple "reasons", hence the bitmask. */ * created as a result of multiple "reasons", hence the bitmask. */

View File

@ -425,7 +425,7 @@ static int add_mount(
* the systemd mount-timeout doesn't interfere. * the systemd mount-timeout doesn't interfere.
* By placing these options first, they can be over-ridden by * By placing these options first, they can be over-ridden by
* settings in /etc/fstab. */ * settings in /etc/fstab. */
opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,", opts, ",fg"); opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,nofail,", opts, ",fg");
SET_FLAG(flags, NOFAIL, true); SET_FLAG(flags, NOFAIL, true);
} }

View File

@ -1267,15 +1267,22 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) {
assert(h); assert(h);
switch (home_get_state(h)) { switch (home_get_state(h)) {
case HOME_INACTIVE: case HOME_INACTIVE: {
int t;
if (h->record->storage < 0) if (h->record->storage < 0)
break; /* if no storage is defined we don't know what precisely to look for, hence break; /* if no storage is defined we don't know what precisely to look for, hence
* HOME_INACTIVE is OK in that case too. */ * HOME_INACTIVE is OK in that case too. */
if (IN_SET(user_record_test_image_path(h->record), USER_TEST_MAYBE, USER_TEST_UNDEFINED)) t = user_record_test_image_path(h->record);
if (IN_SET(t, USER_TEST_MAYBE, USER_TEST_UNDEFINED))
break; /* And if the image path test isn't conclusive, let's also go on */ break; /* And if the image path test isn't conclusive, let's also go on */
_fallthrough_; if (IN_SET(t, -EBADFD, -ENOTDIR))
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Selected home image of user %s already exists or has wrong inode type.", h->user_name);
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Selected home image of user %s already exists.", h->user_name);
}
case HOME_UNFIXATED: case HOME_UNFIXATED:
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name); return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name);
case HOME_ABSENT: case HOME_ABSENT:
@ -2709,6 +2716,19 @@ int home_set_current_message(Home *h, sd_bus_message *m) {
return 1; return 1;
} }
int home_wait_for_worker(Home *h) {
assert(h);
if (h->worker_pid <= 0)
return 0;
log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
(void) wait_for_terminate(h->worker_pid, NULL);
(void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
h->worker_pid = 0;
return 1;
}
static const char* const home_state_table[_HOME_STATE_MAX] = { static const char* const home_state_table[_HOME_STATE_MAX] = {
[HOME_UNFIXATED] = "unfixated", [HOME_UNFIXATED] = "unfixated",
[HOME_ABSENT] = "absent", [HOME_ABSENT] = "absent",

View File

@ -164,5 +164,7 @@ int home_auto_login(Home *h, char ***ret_seats);
int home_set_current_message(Home *h, sd_bus_message *m); int home_set_current_message(Home *h, sd_bus_message *m);
int home_wait_for_worker(Home *h);
const char *home_state_to_string(HomeState state); const char *home_state_to_string(HomeState state);
HomeState home_state_from_string(const char *s); HomeState home_state_from_string(const char *s);

View File

@ -232,8 +232,14 @@ int manager_new(Manager **ret) {
} }
Manager* manager_free(Manager *m) { Manager* manager_free(Manager *m) {
Home *h;
Iterator i;
assert(m); assert(m);
HASHMAP_FOREACH(h, m->homes_by_worker_pid, i)
(void) home_wait_for_worker(h);
hashmap_free(m->homes_by_uid); hashmap_free(m->homes_by_uid);
hashmap_free(m->homes_by_name); hashmap_free(m->homes_by_name);
hashmap_free(m->homes_by_worker_pid); hashmap_free(m->homes_by_worker_pid);

View File

@ -18,8 +18,9 @@ fi
MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
ENTRY_DIR="/$MACHINE_ID/$KERNEL_VERSION" BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
BOOT_ROOT=${ENTRY_DIR_ABS%$ENTRY_DIR} BOOT_MNT=$(stat -c %m $BOOT_ROOT)
ENTRY_DIR=/${ENTRY_DIR_ABS#$BOOT_MNT}
if [[ $COMMAND == remove ]]; then if [[ $COMMAND == remove ]]; then
rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"

View File

@ -783,7 +783,6 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
int r; int r;
struct addrinfo *result, hints = { struct addrinfo *result, hints = {
.ai_socktype = SOCK_STREAM, .ai_socktype = SOCK_STREAM,
.ai_flags = AI_ADDRCONFIG,
}; };
assert(b); assert(b);

View File

@ -66,7 +66,10 @@ int stub_pid1(sd_id128_t uuid) {
if (pid == 0) { if (pid == 0) {
/* Return in the child */ /* Return in the child */
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0); assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
setsid();
if (setsid() < 0)
return log_error_errno(errno, "Failed to become session leader in payload process: %m");
return 0; return 0;
} }

View File

@ -2172,7 +2172,7 @@ static int setup_pts(const char *dest) {
} }
static int setup_stdio_as_dev_console(void) { static int setup_stdio_as_dev_console(void) {
int terminal; _cleanup_close_ int terminal = -1;
int r; int r;
terminal = open_terminal("/dev/console", O_RDWR); terminal = open_terminal("/dev/console", O_RDWR);
@ -2187,6 +2187,7 @@ static int setup_stdio_as_dev_console(void) {
/* invalidates 'terminal' on success and failure */ /* invalidates 'terminal' on success and failure */
r = rearrange_stdio(terminal, terminal, terminal); r = rearrange_stdio(terminal, terminal, terminal);
TAKE_FD(terminal);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m"); return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");

View File

@ -3142,7 +3142,7 @@ static int find_root(char **ret, int *ret_fd) {
if (!s) if (!s)
return log_oom(); return log_oom();
fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0777); fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
if (fd < 0) if (fd < 0)
return log_error_errno(errno, "Failed to create '%s': %m", arg_node); return log_error_errno(errno, "Failed to create '%s': %m", arg_node);

View File

@ -59,7 +59,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
assert_se(arg_dest = dest); assert_se(arg_dest = dest);
if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) { if (check_executable(RC_LOCAL_PATH) >= 0) {
log_debug("Automatically adding rc-local.service."); log_debug("Automatically adding rc-local.service.");
r = add_symlink("rc-local.service", "multi-user.target"); r = add_symlink("rc-local.service", "multi-user.target");

View File

@ -770,7 +770,12 @@ int dissect_image(
} }
} }
if (!m->partitions[PARTITION_ROOT].found) { if (m->partitions[PARTITION_ROOT].found) {
/* If we found the primary arch, then invalidate the secondary arch to avoid any ambiguities,
* since we never want to mount the secondary arch in this case. */
m->partitions[PARTITION_ROOT_SECONDARY].found = false;
m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
} else {
/* No root partition found? Then let's see if ther's one for the secondary architecture. And if not /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
* either, then check if there's a single generic one, and use that. */ * either, then check if there's a single generic one, and use that. */
@ -815,12 +820,6 @@ int dissect_image(
if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found) if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
/* If we found the primary root with the hash, then we definitely want to suppress any secondary root
* (which would be weird, after all the root hash should only be assigned to one pair of
* partitions... */
m->partitions[PARTITION_ROOT_SECONDARY].found = false;
m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
/* If we found a verity setup, then the root partition is necessarily read-only. */ /* If we found a verity setup, then the root partition is necessarily read-only. */
m->partitions[PARTITION_ROOT].rw = false; m->partitions[PARTITION_ROOT].rw = false;
@ -992,7 +991,7 @@ static int mount_partition(
/* If requested, turn on discard support. */ /* If requested, turn on discard support. */
if (fstype_can_discard(fstype) && if (fstype_can_discard(fstype) &&
((flags & DISSECT_IMAGE_DISCARD) || ((flags & DISSECT_IMAGE_DISCARD) ||
((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node)))) { ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node) > 0))) {
options = strdup("discard"); options = strdup("discard");
if (!options) if (!options)
return -ENOMEM; return -ENOMEM;

View File

@ -418,7 +418,6 @@ static int resolve_remote(Connection *c) {
static const struct addrinfo hints = { static const struct addrinfo hints = {
.ai_family = AF_UNSPEC, .ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM, .ai_socktype = SOCK_STREAM,
.ai_flags = AI_ADDRCONFIG
}; };
const char *node, *service; const char *node, *service;

View File

@ -2,6 +2,7 @@
#include "env-file.h" #include "env-file.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "macro.h" #include "macro.h"
#include "strv.h" #include "strv.h"
@ -132,6 +133,46 @@ static void test_load_env_file_5(void) {
assert_se(data[2] == NULL); assert_se(data[2] == NULL);
} }
static void test_write_and_load_env_file(void) {
const char *v;
/* Make sure that our writer, parser and the shell agree on what our env var files mean */
FOREACH_STRING(v,
"obbardc-laptop",
"obbardc\\-laptop",
"obbardc-lap\\top",
"obbardc-lap\\top",
"obbardc-lap\\\\top",
"double\"quote",
"single\'quote",
"dollar$dollar",
"newline\nnewline") {
_cleanup_(unlink_and_freep) char *p = NULL;
_cleanup_strv_free_ char **l = NULL;
_cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL;
_cleanup_pclose_ FILE *f = NULL;
size_t sz;
assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
assert_se(j = strjoin("TEST=", v));
assert_se(write_env_file(p, STRV_MAKE(j)) >= 0);
assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\""));
assert_se(f = popen(cmd, "re"));
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
assert_se(sz == strlen(v));
assert_se(streq(from_shell, v));
assert_se(load_env_file(NULL, p, &l) >= 0);
assert_se(strv_equal(l, STRV_MAKE(j)));
assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0);
assert_se(streq_ptr(w, v));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO); test_setup_logging(LOG_INFO);
@ -140,4 +181,8 @@ int main(int argc, char *argv[]) {
test_load_env_file_3(); test_load_env_file_3();
test_load_env_file_4(); test_load_env_file_4();
test_load_env_file_5(); test_load_env_file_5();
test_write_and_load_env_file();
return 0;
} }

View File

@ -151,6 +151,18 @@ static void test_parse_env_file(void) {
assert_se(r >= 0); assert_se(r >= 0);
} }
static void test_one_shell_var(const char *file, const char *variable, const char *value) {
_cleanup_free_ char *cmd = NULL, *from_shell = NULL;
_cleanup_pclose_ FILE *f = NULL;
size_t sz;
assert_se(cmd = strjoin(". ", file, " && /bin/echo -n \"$", variable, "\""));
assert_se(f = popen(cmd, "re"));
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
assert_se(sz == strlen(value));
assert_se(streq(from_shell, value));
}
static void test_parse_multiline_env_file(void) { static void test_parse_multiline_env_file(void) {
_cleanup_(unlink_tempfilep) char _cleanup_(unlink_tempfilep) char
t[] = "/tmp/test-fileio-in-XXXXXX", t[] = "/tmp/test-fileio-in-XXXXXX",
@ -162,8 +174,8 @@ static void test_parse_multiline_env_file(void) {
assert_se(fmkostemp_safe(t, "w", &f) == 0); assert_se(fmkostemp_safe(t, "w", &f) == 0);
fputs("one=BAR\\\n" fputs("one=BAR\\\n"
" VAR\\\n" "\\ \\ \\ \\ VAR\\\n"
"\tGAR\n" "\\\tGAR\n"
"#comment\n" "#comment\n"
"two=\"bar\\\n" "two=\"bar\\\n"
" var\\\n" " var\\\n"
@ -173,9 +185,13 @@ static void test_parse_multiline_env_file(void) {
" var \\\n" " var \\\n"
"\tgar \"\n", f); "\tgar \"\n", f);
fflush(f); assert_se(fflush_and_check(f) >= 0);
fclose(f); fclose(f);
test_one_shell_var(t, "one", "BAR VAR\tGAR");
test_one_shell_var(t, "two", "bar var\tgar");
test_one_shell_var(t, "tri", "bar var \tgar ");
r = load_env_file(NULL, t, &a); r = load_env_file(NULL, t, &a);
assert_se(r >= 0); assert_se(r >= 0);

View File

@ -8,16 +8,16 @@
# (at your option) any later version. # (at your option) any later version.
# This unit gets pulled automatically into multi-user.target by # This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if @RC_LOCAL_SCRIPT_PATH_START@ is executable. # systemd-rc-local-generator if @RC_LOCAL_PATH@ is executable.
[Unit] [Unit]
Description=@RC_LOCAL_SCRIPT_PATH_START@ Compatibility Description=@RC_LOCAL_PATH@ Compatibility
Documentation=man:systemd-rc-local-generator(8) Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=@RC_LOCAL_SCRIPT_PATH_START@ ConditionFileIsExecutable=@RC_LOCAL_PATH@
After=network.target After=network.target
[Service] [Service]
Type=forking Type=forking
ExecStart=@RC_LOCAL_SCRIPT_PATH_START@ start ExecStart=@RC_LOCAL_PATH@ start
TimeoutSec=0 TimeoutSec=0
RemainAfterExit=yes RemainAfterExit=yes
GuessMainPID=no GuessMainPID=no