New upstream version 249.6

This commit is contained in:
Michael Biebl 2021-11-10 22:35:14 +01:00
parent ce5f39bdc4
commit 2223c7731a
64 changed files with 539 additions and 490 deletions

View File

@ -58,6 +58,10 @@
hostnames. If you rely on that lookup being provided by DNS, you might
want to order things differently.
</para>
<para>Communication between <command>nss-resolve</command> and
<filename>systemd-resolved.service</filename> takes place via the
<filename>/run/systemd/resolve/io.systemd.Resolve</filename> <constant>AF_UNIX</constant> socket.</para>
</refsect1>
<refsect1>

View File

@ -45,14 +45,24 @@
<refsect1>
<title>Description</title>
<para><function>sd_listen_fds()</function> may be invoked by a
daemon to check for file descriptors passed by the service manager as
part of the socket-based activation logic. It returns the number
of received file descriptors. If no file descriptors have been
received, zero is returned. The first file descriptor may be found
at file descriptor number 3
(i.e. <constant>SD_LISTEN_FDS_START</constant>), the remaining
descriptors follow at 4, 5, 6, …, if any.</para>
<para><function>sd_listen_fds()</function> may be invoked by a daemon to check for file descriptors
passed by the service manager as part of the socket-based activation logic. It returns the number of
received file descriptors. If no file descriptors have been received, zero is returned. The first file
descriptor may be found at file descriptor number 3 (i.e. <constant>SD_LISTEN_FDS_START</constant>), the
remaining descriptors follow at 4, 5, 6, …, if any.</para>
<para>The file descriptors passed this way may be closed at will by the processes receiving them: it's up
to the processes themselves to close them after use or whether to leave them open until the process exits
(in which case the kernel closes them automatically). Note that the file descriptors received by daemons
are duplicates of the file descriptors the service manager originally allocated and bound and of which it
continously keeps a copy (except if <varname>Accept=yes</varname> is used). This means any socket option
changes and other changes made to the sockets will visible to the service manager too. Most importanly
this means it's generally not a good idea to invoke <citerefentry
project='man-pages'><refentrytitle>shutdown</refentrytitle><manvolnum>2</manvolnum></citerefentry> on
such sockets, since it will shut down communication on the file descriptor the service manager holds for
the same socket, too. Also note that if a daemon is restarted (and its associated sockets are not) it
will receive file descriptors to the very same sockets as the earlier invocations, thus all socket
options applied then will still apply.</para>
<para>If a daemon receives more than one file descriptor, they will be passed in the same order as
configured in the systemd socket unit file (see

View File

@ -65,6 +65,13 @@
that are shown are additionally filtered by <option>--type=</option> and <option>--state=</option> if those
options are specified.</para>
<para>Note that this command does not show unit templates, but only instances of unit
templates. Units templates that aren't instantiated are not runnable, and will thus never show up
in the output of this command. Specifically this means that <filename>foo@.service</filename>
will never be shown in this list — unless instantiated, e.g. as
<filename>foo@bar.service</filename>. Use <command>list-unit-files</command> (see below) for
listing installed unit template files.</para>
<para>Produces output similar to
<programlisting> UNIT LOAD ACTIVE SUB DESCRIPTION
sys-module-fuse.device loaded active plugged /sys/module/fuse
@ -81,11 +88,11 @@ ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
123 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
</programlisting>
The header and the last unit of a given type are underlined if the
terminal supports that. A colored dot is shown next to services which
were masked, not found, or otherwise failed.</para>
To show all installed unit files use 'systemctl list-unit-files'.</programlisting></para>
<para>The header and the last unit of a given type are underlined if the terminal supports
that. A colored dot is shown next to services which were masked, not found, or otherwise
failed.</para>
<para>The LOAD column shows the load state, one of <constant>loaded</constant>,
<constant>not-found</constant>, <constant>bad-setting</constant>, <constant>error</constant>,
@ -694,10 +701,13 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<term><command>list-unit-files</command> <optional><replaceable>PATTERN…</replaceable></optional></term>
<listitem>
<para>List unit files installed on the system, in combination with their enablement state (as reported by
<command>is-enabled</command>). If one or more <replaceable>PATTERN</replaceable>s are specified, only unit
files whose name matches one of them are shown (patterns matching unit file system paths are not
supported).</para>
<para>List unit files installed on the system, in combination with their enablement state (as
reported by <command>is-enabled</command>). If one or more <replaceable>PATTERN</replaceable>s
are specified, only unit files whose name matches one of them are shown (patterns matching unit
file system paths are not supported).</para>
<para>Unlike <command>list-units</command> this command will list template units in addition to
explicitly instantiated units.</para>
</listitem>
</varlistentry>

View File

@ -58,6 +58,23 @@
area, which is not available in other encryption formats.</para>
</refsect1>
<refsect1>
<title>Limitations</title>
<para>Note that currently when enrolling a new key of one of the five supported types listed above, it is
required to first provide a passphrase or recovery key (i.e. one of the latter two key types). For
example, it's currently not possible to unlock a device with a FIDO2 key in order to enroll a new FIDO2
key. Instead, in order to enroll a new FIDO2 key, it is necessary to provide an already enrolled regular
passphrase or recovery key. Thus, if in future key roll-over is desired it's generally recommended to
combine TPM2, FIDO2, PKCS#11 key enrollment with enrolling a regular passphrase or recovery key.</para>
<para>Also note that support for enrolling multiple FIDO2 tokens is currently not too useful, as while
unlocking <command>systemd-cryptsetup</command> cannot identify which token is currently plugged in and
thus does not know which authentication request to send to the device. This limitation does not apply to
tokens enrolled via PKCS#11 — because tokens of this type may be identified immediately, before
authentication.</para>
</refsect1>
<refsect1>
<title>Options</title>

View File

@ -17,7 +17,7 @@
<refnamediv>
<refname>systemd-veritysetup-generator</refname>
<refpurpose>Unit generator for integrity protected block devices</refpurpose>
<refpurpose>Unit generator for verity protected block devices</refpurpose>
</refnamediv>
<refsynopsisdiv>
@ -28,7 +28,7 @@
<title>Description</title>
<para><filename>systemd-veritysetup-generator</filename> is a generator that translates kernel command line options
configuring integrity-protected block devices (verity) into native systemd units early at boot and when
configuring verity protected block devices into native systemd units early at boot and when
configuration of the system manager is reloaded. This will create
<citerefentry><refentrytitle>systemd-veritysetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
units as necessary.</para>
@ -66,7 +66,7 @@
data devices to use are automatically derived from the specified hash value. Specifically, the data partition
device is looked for under a GPT partition UUID derived from the first 128bit of the root hash, the hash
partition device is looked for under a GPT partition UUID derived from the last 128bit of the root hash. Hence
it is usually sufficient to specify the root hash to boot from an integrity protected root file system, as
it is usually sufficient to specify the root hash to boot from a verity protected root file system, as
device paths are automatically determined from it — as long as the partition table is properly set up.</para>
</listitem>
</varlistentry>
@ -76,7 +76,7 @@
<term><varname>systemd.verity_root_hash=</varname></term>
<listitem><para>These two settings take block device paths as arguments and may be used to explicitly
configure the data partition and hash partition to use for setting up the integrity protection for the root file
configure the data partition and hash partition to use for setting up the verity protection for the root file
system. If not specified, these paths are automatically derived from the <varname>roothash=</varname> argument
(see above).</para></listitem>
</varlistentry>

View File

@ -18,7 +18,7 @@
<refnamediv>
<refname>systemd-veritysetup@.service</refname>
<refname>systemd-veritysetup</refname>
<refpurpose>Disk integrity protection logic</refpurpose>
<refpurpose>Disk verity protection logic</refpurpose>
</refnamediv>
<refsynopsisdiv>
@ -29,12 +29,12 @@
<refsect1>
<title>Description</title>
<para><filename>systemd-veritysetup@.service</filename> is a service responsible for setting up integrity
protection (verity) block devices. It should be instantiated for each device that requires integrity
<para><filename>systemd-veritysetup@.service</filename> is a service responsible for setting up verity
protection block devices. It should be instantiated for each device that requires verity
protection.</para>
<para>At early boot and when the system manager configuration is reloaded kernel command line configuration for
integrity protected block devices is translated into <filename>systemd-veritysetup@.service</filename> units by
verity protected block devices is translated into <filename>systemd-veritysetup@.service</filename> units by
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<para><filename>systemd-veritysetup@.service</filename> calls <command>systemd-veritysetup</command>.</para>

View File

@ -33,12 +33,12 @@ This is based on crypttab(5).
<title>Description</title>
<para>The <filename>/etc/veritytab</filename> file describes
verity integrity protected block devices that are set up during
verity protected block devices that are set up during
system boot.</para>
<para>Empty lines and lines starting with the <literal>#</literal>
character are ignored. Each of the remaining lines describes one
verity integrity protected block device. Fields are delimited by
verity protected block device. Fields are delimited by
white space.</para>
<para>Each line is in the form<programlisting><replaceable>volume-name</replaceable> <replaceable>data-device</replaceable> <replaceable>hash-device</replaceable> <replaceable>roothash</replaceable> <replaceable>options</replaceable></programlisting>
@ -65,7 +65,7 @@ This is based on crypttab(5).
<term><option>restart-on-corruption</option></term>
<term><option>panic-on-corruption</option></term>
<listitem><para>Defines what to do if data integrity problem is detected (data corruption). Without these
<listitem><para>Defines what to do if a data verity problem is detected (data corruption). Without these
options kernel fails the IO operation with I/O error. With <literal>--ignore-corruption</literal> option the
corruption is only logged. With <literal>--restart-on-corruption</literal> or
<literal>--panic-on-corruption</literal> the kernel is restarted (panicked) immediately.
@ -149,18 +149,18 @@ This is based on crypttab(5).
<varlistentry>
<term><option>x-initrd.attach</option></term>
<listitem><para>Setup this verity integrity protected block device in the initramfs, similarly to
<listitem><para>Setup this verity protected block device in the initramfs, similarly to
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
units marked with <option>x-initrd.mount</option>.</para>
<para>Although it's not necessary to mark the mount entry for the root file system with
<option>x-initrd.mount</option>, <option>x-initrd.attach</option> is still recommended with
the verity integrity protected block device containing the root file system as otherwise systemd
the verity protected block device containing the root file system as otherwise systemd
will attempt to detach the device during the regular system shutdown while it's still in
use. With this option the device will still be detached but later after the root file
system is unmounted.</para>
<para>All other verity integrity protected block devices that contain file systems mounted in the
<para>All other verity protected block devices that contain file systems mounted in the
initramfs should use this option.</para>
</listitem>
</varlistentry>
@ -176,7 +176,7 @@ This is based on crypttab(5).
<title>Examples</title>
<example>
<title>/etc/veritytab example</title>
<para>Set up two verity integrity protected block devices. One using device blocks, another using files.</para>
<para>Set up two verity protected block devices. One using device blocks, another using files.</para>
<programlisting>usr PARTUUID=783e45ae-7aa3-484a-beef-a80ff9c19cbb PARTUUID=21dc1dfe-4c33-8b48-98a9-918a22eb3e37 36e3f740ad502e2c25e2a23d9c7c17bf0fdad2300b7580842d4b7ec1fb0fa263 auto
data /etc/data /etc/hash a5ee4b42f70ae1f46a08a7c92c2e0a20672ad2f514792730f5d49d7606ab8fdf auto

View File

@ -2493,18 +2493,17 @@ endif
if conf.get('ENABLE_LOCALED') == 1
if conf.get('HAVE_XKBCOMMON') == 1
# logind will load libxkbcommon.so dynamically on its own
deps = [libdl]
extra_includes = [libxkbcommon.get_pkgconfig_variable('includedir')]
# logind will load libxkbcommon.so dynamically on its own, but we still
# need to specify where the headers are
deps = [libdl, libxkbcommon.partial_dependency(compile_args: true)]
else
deps = []
extra_includes = []
endif
executable(
'systemd-localed',
systemd_localed_sources,
include_directories : includes + extra_includes,
include_directories : includes,
link_with : [libshared],
dependencies : deps,
install_rpath : rootlibexecdir,

View File

@ -858,8 +858,8 @@ int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
void sigkill_wait(pid_t pid) {
assert(pid > 1);
if (kill(pid, SIGKILL) >= 0)
(void) wait_for_terminate(pid, NULL);
(void) kill(pid, SIGKILL);
(void) wait_for_terminate(pid, NULL);
}
void sigkill_waitp(pid_t *pid) {
@ -876,8 +876,8 @@ void sigkill_waitp(pid_t *pid) {
void sigterm_wait(pid_t pid) {
assert(pid > 1);
if (kill_and_sigcont(pid, SIGTERM) >= 0)
(void) wait_for_terminate(pid, NULL);
(void) kill_and_sigcont(pid, SIGTERM);
(void) wait_for_terminate(pid, NULL);
}
int kill_and_sigcont(pid_t pid, int sig) {

View File

@ -79,7 +79,7 @@ int dir_is_empty_at(int dir_fd, const char *path) {
} else {
/* Note that DUPing is not enough, as the internal pointer
* would still be shared and moved by FOREACH_DIRENT. */
fd = fd_reopen(dir_fd, O_CLOEXEC);
fd = fd_reopen(dir_fd, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
if (fd < 0)
return fd;
}

View File

@ -159,12 +159,13 @@ static int detect_vm_dmi_vendor(void) {
{ "VMware", VIRTUALIZATION_VMWARE }, /* https://kb.vmware.com/s/article/1009458 */
{ "VMW", VIRTUALIZATION_VMWARE },
{ "innotek GmbH", VIRTUALIZATION_ORACLE },
{ "Oracle Corporation", VIRTUALIZATION_ORACLE },
{ "VirtualBox", VIRTUALIZATION_ORACLE },
{ "Xen", VIRTUALIZATION_XEN },
{ "Bochs", VIRTUALIZATION_BOCHS },
{ "Parallels", VIRTUALIZATION_PARALLELS },
/* https://wiki.freebsd.org/bhyve */
{ "BHYVE", VIRTUALIZATION_BHYVE },
{ "Microsoft", VIRTUALIZATION_MICROSOFT },
};
int r;

View File

@ -134,7 +134,7 @@ static BOOLEAN line_edit(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
err = console_key_read(&key, TRUE);
err = console_key_read(&key, 0);
if (EFI_ERROR(err))
continue;
@ -387,7 +387,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"OsIndicationsSupported: %d\n", indvar);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
console_key_read(&key, 0);
Print(L"timeout: %u\n", config->timeout_sec);
if (config->timeout_sec_efivar >= 0)
@ -432,7 +432,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
console_key_read(&key, 0);
for (UINTN i = 0; i < config->entry_count; i++) {
ConfigEntry *entry;
@ -482,7 +482,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
entry->path, entry->next_name);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
console_key_read(&key, 0);
}
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -509,11 +509,10 @@ static BOOLEAN menu_run(
UINTN y_max;
CHAR16 *status;
CHAR16 *clearline;
INTN timeout_remain;
UINTN timeout_remain = config->timeout_sec;
INT16 idx;
BOOLEAN exit = FALSE;
BOOLEAN run = TRUE;
BOOLEAN wait = FALSE;
graphics_mode(FALSE);
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
@ -527,7 +526,7 @@ static BOOLEAN menu_run(
err = console_set_mode(&config->console_mode, config->console_mode_change);
if (EFI_ERROR(err)) {
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
log_error_stall(L"Error switching console mode to %lu: %r", (UINT64)config->console_mode, err);
}
} else
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -538,12 +537,6 @@ static BOOLEAN menu_run(
y_max = 25;
}
/* we check 10 times per second for a keystroke */
if (config->timeout_sec > 0)
timeout_remain = config->timeout_sec * 10;
else
timeout_remain = -1;
idx_highlight = config->idx_default;
idx_highlight_prev = 0;
@ -643,7 +636,7 @@ static BOOLEAN menu_run(
if (timeout_remain > 0) {
FreePool(status);
status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10);
status = PoolPrint(L"Boot in %d s.", timeout_remain);
}
/* print status at last line of screen */
@ -664,27 +657,18 @@ static BOOLEAN menu_run(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
}
err = console_key_read(&key, wait);
if (EFI_ERROR(err)) {
/* timeout reached */
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : 0);
if (err == EFI_TIMEOUT) {
timeout_remain--;
if (timeout_remain == 0) {
exit = TRUE;
break;
}
/* sleep and update status */
if (timeout_remain > 0) {
uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
timeout_remain--;
continue;
}
/* timeout disabled, wait for next key */
wait = TRUE;
/* update status */
continue;
}
timeout_remain = -1;
} else
timeout_remain = 0;
/* clear status after keystroke */
if (status) {
@ -787,7 +771,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
status = PoolPrint(L"Menu timeout set to %d s.", config->timeout_sec_efivar);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){
@ -795,7 +779,7 @@ static BOOLEAN menu_run(
efivar_set(
LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_config > 0)
status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
status = PoolPrint(L"Menu timeout of %d s is defined by configuration file.",
config->timeout_sec_config);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@ -813,7 +797,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.",
status = PoolPrint(L"Menu timeout set to %d s.",
config->timeout_sec_efivar);
else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@ -1221,8 +1205,7 @@ static VOID config_entry_bump_counters(
break;
if (r != EFI_BUFFER_TOO_SMALL || file_info_size * 2 < file_info_size) {
Print(L"\nFailed to get file info for '%s': %r\n", old_path, r);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"Failed to get file info for '%s': %r", old_path, r);
return;
}
@ -1234,8 +1217,7 @@ static VOID config_entry_bump_counters(
StrCpy(file_info->FileName, entry->next_name);
r = uefi_call_wrapper(handle->SetInfo, 4, handle, &EfiFileInfoGuid, file_info_size, file_info);
if (EFI_ERROR(r)) {
Print(L"\nFailed to rename '%s' to '%s', ignoring: %r\n", old_path, entry->next_name, r);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, r);
return;
}
@ -2165,18 +2147,12 @@ static EFI_STATUS image_start(
EFI_STATUS err;
path = FileDevicePath(entry->device, entry->loader);
if (!path) {
Print(L"Error getting device path.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_INVALID_PARAMETER;
}
if (!path)
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path.");
err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image);
if (EFI_ERROR(err)) {
Print(L"Error loading %s: %r", entry->loader, err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err);
if (config->options_edit)
options = config->options_edit;
@ -2190,8 +2166,7 @@ static EFI_STATUS image_start(
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
Print(L"Error getting LoadedImageProtocol handle: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"Error getting LoadedImageProtocol handle: %r", err);
goto out_unload;
}
loaded_image->LoadOptions = options;
@ -2202,10 +2177,8 @@ static EFI_STATUS image_start(
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) {
Print(L"Unable to add image options measurement: %r", err);
uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
}
if (EFI_ERROR(err))
log_error_stall(L"Unable to add image options measurement: %r", err);
#endif
}
@ -2231,9 +2204,7 @@ static EFI_STATUS reboot_into_firmware(VOID) {
return err;
err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL);
Print(L"Error calling ResetSystem: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
return log_error_status_stall(err, L"Error calling ResetSystem: %r", err);
}
static VOID config_free(Config *config) {
@ -2305,30 +2276,21 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
Print(L"Error getting a LoadedImageProtocol handle: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
/* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) {
Print(L"Unable to open root directory.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_LOAD_ERROR;
}
if (!root_dir)
return log_error_status_stall(EFI_LOAD_ERROR, L"Unable to open root directory.", EFI_LOAD_ERROR);
if (secure_boot_enabled() && shim_loaded()) {
err = security_policy_install();
if (EFI_ERROR(err)) {
Print(L"Error installing security policy: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error installing security policy: %r", err);
}
/* the filesystem path to this image, to prevent adding ourselves to the menu */
@ -2367,8 +2329,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
}
if (config.entry_count == 0) {
Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
goto out;
}
@ -2392,13 +2353,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
else {
UINT64 key;
err = console_key_read(&key, FALSE);
if (err == EFI_NOT_READY) {
uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
err = console_key_read(&key, FALSE);
}
/* Block up to 100ms to give firmware time to get input working. */
err = console_key_read(&key, 100 * 1000);
if (!EFI_ERROR(err)) {
INT16 idx;
@ -2440,8 +2396,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = image_start(image, &config, entry);
if (EFI_ERROR(err)) {
graphics_mode(FALSE);
Print(L"\nFailed to execute %s (%s): %r\n", entry->title, entry->loader, err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"Failed to execute %s (%s): %r", entry->title, entry->loader, err);
goto out;
}

View File

@ -11,61 +11,105 @@
#define EFI_SIMPLE_TEXT_INPUT_EX_GUID &(EFI_GUID) EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
static inline void EventClosep(EFI_EVENT *event) {
if (!*event)
return;
uefi_call_wrapper(BS->CloseEvent, 1, *event);
}
/*
* Reading input from the console sounds like an easy task to do, but thanks to broken
* firmware it is actually a nightmare.
*
* There is a ConIn and TextInputEx API for this. Ideally we want to use TextInputEx,
* because that gives us Ctrl/Alt/Shift key state information. Unfortunately, it is not
* always available and sometimes just non-functional.
*
* On the other hand we have ConIn, where some firmware likes to just freeze on us
* if we call ReadKeyStroke on it.
*
* Therefore, we use WaitForEvent on both ConIn and TextInputEx (if available) along
* with a timer event. The timer ensures there is no need to call into functions
* that might freeze on us, while still allowing us to show a timeout counter.
*/
EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked;
UINTN index;
EFI_INPUT_KEY k;
EFI_STATUS err;
_cleanup_(EventClosep) EFI_EVENT timer = NULL;
EFI_EVENT events[3] = { ST->ConIn->WaitForKey };
UINTN n_events = 1;
if (!checked) {
err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
if (EFI_ERROR(err))
if (EFI_ERROR(err) ||
uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx) == EFI_INVALID_PARAMETER)
/* If WaitForKeyEx fails here, the firmware pretends it talks this
* protocol, but it really doesn't. */
TextInputEx = NULL;
else
events[n_events++] = TextInputEx->WaitForKeyEx;
checked = TRUE;
}
/* wait until key is pressed */
if (wait)
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
if (timeout_usec > 0) {
err = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error creating timer event: %r", err);
if (TextInputEx) {
EFI_KEY_DATA keydata;
UINT64 keypress;
/* SetTimer expects 100ns units for some reason. */
err = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerRelative, timeout_usec * 10);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error arming timer event: %r", err);
err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
if (!EFI_ERROR(err)) {
UINT32 shift = 0;
/* do not distinguish between left and right keys */
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
shift |= EFI_CONTROL_PRESSED;
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
shift |= EFI_ALT_PRESSED;
};
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
if (keypress > 0) {
*key = keypress;
return 0;
}
}
events[n_events++] = timer;
}
err = uefi_call_wrapper(BS->WaitForEvent, 3, n_events, events, &index);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error waiting for events: %r", err);
if (timeout_usec > 0 && timer == events[index])
return EFI_TIMEOUT;
/* TextInputEx might be ready too even if ConIn got to signal first. */
if (TextInputEx && !EFI_ERROR(uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx))) {
EFI_KEY_DATA keydata;
UINT64 keypress;
UINT32 shift = 0;
err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
if (EFI_ERROR(err))
return err;
/* do not distinguish between left and right keys */
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
shift |= EFI_CONTROL_PRESSED;
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
shift |= EFI_ALT_PRESSED;
};
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
if (keypress > 0) {
*key = keypress;
return EFI_SUCCESS;
}
return EFI_NOT_READY;
}
/* fallback for firmware which does not support SimpleTextInputExProtocol
*
* This is also called in case ReadKeyStrokeEx did not return a key, because
* some broken firmwares offer SimpleTextInputExProtocol, but never actually
* handle any key. */
err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
if (EFI_ERROR(err))
return err;
*key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
return 0;
return EFI_SUCCESS;
}
static EFI_STATUS change_mode(UINTN mode) {

View File

@ -16,5 +16,5 @@ enum console_mode_change_type {
CONSOLE_MODE_MAX,
};
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec);
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how);

View File

@ -35,10 +35,8 @@ static EFI_STATUS acquire_rng(UINTN size, VOID **ret) {
return log_oom();
err = uefi_call_wrapper(rng->GetRNG, 3, rng, NULL, size, data);
if (EFI_ERROR(err)) {
Print(L"Failed to acquire RNG data: %r\n", err);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err);
*ret = TAKE_PTR(data);
return EFI_SUCCESS;
@ -149,14 +147,12 @@ static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND)
Print(L"Failed to read LoaderSystemToken EFI variable: %r", err);
log_error_stall(L"Failed to read LoaderSystemToken EFI variable: %r", err);
return err;
}
if (size <= 0) {
Print(L"System token too short, ignoring.");
return EFI_NOT_FOUND;
}
if (size <= 0)
return log_error_status_stall(EFI_NOT_FOUND, L"System token too short, ignoring.");
*ret = TAKE_PTR(data);
*ret_size = size;
@ -209,8 +205,7 @@ static VOID validate_sha256(void) {
sha256_finish_ctx(&hash, result);
if (CompareMem(result, array[i].hash, HASH_VALUE_SIZE) != 0) {
Print(L"SHA256 failed validation.\n");
uefi_call_wrapper(BS->Stall, 1, 120 * 1000 * 1000);
log_error_stall(L"SHA256 failed validation.");
return;
}
}
@ -246,7 +241,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, (CHAR16*) L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL);
if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED)
Print(L"Failed to open random seed file: %r\n", err);
log_error_stall(L"Failed to open random seed file: %r", err);
return err;
}
@ -255,15 +250,11 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
return log_oom();
size = info->FileSize;
if (size < RANDOM_MAX_SIZE_MIN) {
Print(L"Random seed file is too short?\n");
return EFI_INVALID_PARAMETER;
}
if (size < RANDOM_MAX_SIZE_MIN)
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too short.");
if (size > RANDOM_MAX_SIZE_MAX) {
Print(L"Random seed file is too large?\n");
return EFI_INVALID_PARAMETER;
}
if (size > RANDOM_MAX_SIZE_MAX)
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large.");
seed = AllocatePool(size);
if (!seed)
@ -271,20 +262,14 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
rsize = size;
err = uefi_call_wrapper(handle->Read, 3, handle, &rsize, seed);
if (EFI_ERROR(err)) {
Print(L"Failed to read random seed file: %r\n", err);
return err;
}
if (rsize != size) {
Print(L"Short read on random seed file\n");
return EFI_PROTOCOL_ERROR;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to read random seed file: %r", err);
if (rsize != size)
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file.");
err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0);
if (EFI_ERROR(err)) {
Print(L"Failed to seek to beginning of random seed file: %r\n", err);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
/* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good
* idea to use it because it helps us for cases where users mistakenly include a random seed in
@ -299,27 +284,19 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
/* Update the random seed on disk before we use it */
wsize = size;
err = uefi_call_wrapper(handle->Write, 3, handle, &wsize, new_seed);
if (EFI_ERROR(err)) {
Print(L"Failed to write random seed file: %r\n", err);
return err;
}
if (wsize != size) {
Print(L"Short write on random seed file\n");
return EFI_PROTOCOL_ERROR;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
if (wsize != size)
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
err = uefi_call_wrapper(handle->Flush, 1, handle);
if (EFI_ERROR(err)) {
Print(L"Failed to flush random seed file: %r\n");
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
/* We are good to go */
err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
if (EFI_ERROR(err)) {
Print(L"Failed to write random seed to EFI variable: %r\n", err);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Failed to write random seed to EFI variable: %r", err);
return EFI_SUCCESS;
}

View File

@ -36,18 +36,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
if (EFI_ERROR(err)) {
Print(L"Unable to locate embedded .linux section: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err);
if (szs[0] > 0)
cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0];
@ -72,10 +66,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) {
Print(L"Unable to add image options measurement: %r", err);
uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
}
if (EFI_ERROR(err))
log_error_stall(L"Unable to add image options measurement: %r", err);
#endif
}
@ -126,7 +118,5 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
graphics_mode(FALSE);
Print(L"Execution of embedded linux image failed: %r\n", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
return log_error_status_stall(err, L"Execution of embedded linux image failed: %r", err);
}

View File

@ -411,8 +411,21 @@ EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN s
return err;
}
VOID log_error_stall(const CHAR16 *fmt, ...) {
va_list args;
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
Print(L"\n");
va_start(args, fmt);
VPrint(fmt, args);
va_end(args);
Print(L"\n");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
}
EFI_STATUS log_oom(void) {
Print(L"Out of memory.");
(void) uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
log_error_stall(L"Out of memory.");
return EFI_OUT_OF_RESOURCES;
}

View File

@ -74,4 +74,13 @@ static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
#define UINT64_MAX ((UINT64) -1)
#endif
VOID log_error_stall(const CHAR16 *fmt, ...);
EFI_STATUS log_oom(void);
/* This works just like log_error_errno() from userspace, but requires you
* to provide err a second time if you want to use %r in the message! */
#define log_error_status_stall(err, fmt, ...) \
({ \
log_error_stall(fmt, ##__VA_ARGS__); \
err; \
})

View File

@ -814,6 +814,12 @@ static int automount_start(Unit *u) {
if (r < 0)
return r;
r = unit_test_start_limit(u);
if (r < 0) {
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -1059,21 +1065,6 @@ static bool automount_supported(void) {
return supported;
}
static int automount_test_start_limit(Unit *u) {
Automount *a = AUTOMOUNT(u);
int r;
assert(a);
r = unit_test_start_limit(u);
if (r < 0) {
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
[AUTOMOUNT_SUCCESS] = "success",
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
@ -1136,6 +1127,4 @@ const UnitVTable automount_vtable = {
[JOB_FAILED] = "Failed to unset automount %s.",
},
},
.test_start_limit = automount_test_start_limit,
};

View File

@ -2137,7 +2137,7 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
CGroupMask delegated_mask;
const char *p;
void *pidp;
int r, q;
int ret, r;
assert(u);
@ -2164,16 +2164,16 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
delegated_mask = unit_get_delegate_mask(u);
r = 0;
ret = 0;
SET_FOREACH(pidp, pids) {
pid_t pid = PTR_TO_PID(pidp);
/* First, attach the PID to the main cgroup hierarchy */
q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
if (q < 0) {
bool again = MANAGER_IS_USER(u->manager) && ERRNO_IS_PRIVILEGE(q);
r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
if (r < 0) {
bool again = MANAGER_IS_USER(u->manager) && ERRNO_IS_PRIVILEGE(r);
log_unit_full_errno(u, again ? LOG_DEBUG : LOG_INFO, q,
log_unit_full_errno(u, again ? LOG_DEBUG : LOG_INFO, r,
"Couldn't move process "PID_FMT" to%s requested cgroup '%s': %m",
pid, again ? " directly" : "", empty_to_root(p));
@ -2192,16 +2192,17 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
continue; /* When the bus thing worked via the bus we are fully done for this PID. */
}
if (r >= 0)
r = q; /* Remember first error */
if (ret >= 0)
ret = r; /* Remember first error */
continue;
}
} else if (ret >= 0)
ret++; /* Count successful additions */
q = cg_all_unified();
if (q < 0)
return q;
if (q > 0)
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
continue;
/* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the
@ -2216,11 +2217,11 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
/* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */
if (delegated_mask & u->cgroup_realized_mask & bit) {
q = cg_attach(cgroup_controller_to_string(c), p, pid);
if (q >= 0)
r = cg_attach(cgroup_controller_to_string(c), p, pid);
if (r >= 0)
continue; /* Success! */
log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m",
log_unit_debug_errno(u, r, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m",
pid, empty_to_root(p), cgroup_controller_to_string(c));
}
@ -2231,14 +2232,14 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
if (!realized)
continue; /* Not even realized in the root slice? Then let's not bother */
q = cg_attach(cgroup_controller_to_string(c), realized, pid);
if (q < 0)
log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
r = cg_attach(cgroup_controller_to_string(c), realized, pid);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
pid, realized, cgroup_controller_to_string(c));
}
}
return r;
return ret;
}
static bool unit_has_mask_realized(

View File

@ -4059,13 +4059,17 @@ static int exec_child(
}
}
if (context->utmp_id)
if (context->utmp_id) {
const char *line = context->tty_path ?
(path_startswith(context->tty_path, "/dev/") ?: context->tty_path) :
NULL;
utmp_put_init_process(context->utmp_id, getpid_cached(), getsid(0),
context->tty_path,
line,
context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS :
context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
USER_PROCESS,
username);
}
if (uid_is_valid(uid)) {
r = chown_terminal(STDIN_FILENO, uid);
@ -4357,7 +4361,7 @@ static int exec_child(
if (fd >= 0) {
r = mac_selinux_get_child_mls_label(fd, executable, context->selinux_context, &mac_selinux_context_net);
if (r < 0) {
if (r < 0 && !context->selinux_context_ignore) {
*exit_status = EXIT_SELINUX_CONTEXT;
return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m");
}
@ -4404,7 +4408,7 @@ static int exec_child(
* process. This is the latest place before dropping capabilities. Other MAC context are set later. */
if (use_smack) {
r = setup_smack(context, executable_fd);
if (r < 0) {
if (r < 0 && !context->smack_process_label_ignore) {
*exit_status = EXIT_SMACK_PROCESS_LABEL;
return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m");
}
@ -4491,7 +4495,7 @@ static int exec_child(
if (exec_context) {
r = setexeccon(exec_context);
if (r < 0) {
if (r < 0 && !context->selinux_context_ignore) {
*exit_status = EXIT_SELINUX_CONTEXT;
return log_unit_error_errno(unit, r, "Failed to change SELinux context to %s: %m", exec_context);
}

View File

@ -1168,6 +1168,12 @@ static int mount_start(Unit *u) {
assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED));
r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -2137,21 +2143,6 @@ static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
return exec_context_get_clean_mask(&m->exec_context, ret);
}
static int mount_test_start_limit(Unit *u) {
Mount *m = MOUNT(u);
int r;
assert(m);
r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
[MOUNT_EXEC_MOUNT] = "ExecMount",
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
@ -2249,6 +2240,4 @@ const UnitVTable mount_vtable = {
[JOB_TIMEOUT] = "Timed out unmounting %s.",
},
},
.test_start_limit = mount_test_start_limit,
};

View File

@ -590,6 +590,12 @@ static int path_start(Unit *u) {
if (r < 0)
return r;
r = unit_test_start_limit(u);
if (r < 0) {
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -805,21 +811,6 @@ static void path_reset_failed(Unit *u) {
p->result = PATH_SUCCESS;
}
static int path_test_start_limit(Unit *u) {
Path *p = PATH(u);
int r;
assert(p);
r = unit_test_start_limit(u);
if (r < 0) {
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const path_type_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = "PathExists",
[PATH_EXISTS_GLOB] = "PathExistsGlob",
@ -874,6 +865,4 @@ const UnitVTable path_vtable = {
.reset_failed = path_reset_failed,
.bus_set_property = bus_path_set_property,
.test_start_limit = path_test_start_limit,
};

View File

@ -374,6 +374,12 @@ static int scope_start(Unit *u) {
scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
return r;
}
if (r == 0) {
log_unit_warning(u, "No PIDs left to attach to the scope's control group, refusing: %m");
scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
return -ECHILD;
}
log_unit_debug(u, "%i %s added to scope's control group.", r, r == 1 ? "process" : "processes");
s->result = SCOPE_SUCCESS;

View File

@ -2456,6 +2456,13 @@ static int service_start(Unit *u) {
assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
/* Make sure we don't enter a busy loop of some kind. */
r = unit_test_start_limit(u);
if (r < 0) {
service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -4451,22 +4458,6 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
return NULL;
}
static int service_test_start_limit(Unit *u) {
Service *s = SERVICE(u);
int r;
assert(s);
/* Make sure we don't enter a busy loop of some kind. */
r = unit_test_start_limit(u);
if (r < 0) {
service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
return r;
}
return 0;
}
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
[SERVICE_RESTART_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
@ -4629,6 +4620,4 @@ const UnitVTable service_vtable = {
},
.finished_job = service_finished_job,
},
.test_start_limit = service_test_start_limit,
};

View File

@ -2515,6 +2515,12 @@ static int socket_start(Unit *u) {
assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED));
r = unit_test_start_limit(u);
if (r < 0) {
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -3423,21 +3429,6 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
return exec_context_get_clean_mask(&s->exec_context, ret);
}
static int socket_test_start_limit(Unit *u) {
Socket *s = SOCKET(u);
int r;
assert(s);
r = unit_test_start_limit(u);
if (r < 0) {
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_PRE] = "ExecStartPre",
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
@ -3564,6 +3555,4 @@ const UnitVTable socket_vtable = {
[JOB_TIMEOUT] = "Timed out stopping %s.",
},
},
.test_start_limit = socket_test_start_limit,
};

View File

@ -933,6 +933,12 @@ static int swap_start(Unit *u) {
if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
return -EAGAIN;
r = unit_test_start_limit(u);
if (r < 0) {
swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -1582,21 +1588,6 @@ static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
return exec_context_get_clean_mask(&s->exec_context, ret);
}
static int swap_test_start_limit(Unit *u) {
Swap *s = SWAP(u);
int r;
assert(s);
r = unit_test_start_limit(u);
if (r < 0) {
swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
@ -1692,6 +1683,4 @@ const UnitVTable swap_vtable = {
[JOB_TIMEOUT] = "Timed out deactivating swap %s.",
},
},
.test_start_limit = swap_test_start_limit,
};

View File

@ -635,6 +635,12 @@ static int timer_start(Unit *u) {
if (r < 0)
return r;
r = unit_test_start_limit(u);
if (r < 0) {
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
return r;
}
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
@ -895,21 +901,6 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
return 0;
}
static int timer_test_start_limit(Unit *u) {
Timer *t = TIMER(u);
int r;
assert(t);
r = unit_test_start_limit(u);
if (r < 0) {
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
return r;
}
return 0;
}
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
[TIMER_ACTIVE] = "OnActiveSec",
[TIMER_BOOT] = "OnBootSec",
@ -969,6 +960,4 @@ const UnitVTable timer_vtable = {
.timezone_change = timer_timezone_change,
.bus_set_property = bus_timer_set_property,
.test_start_limit = timer_test_start_limit,
};

View File

@ -1851,13 +1851,6 @@ int unit_start(Unit *u) {
assert(u);
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
if (UNIT_VTABLE(u)->test_start_limit) {
int r = UNIT_VTABLE(u)->test_start_limit(u);
if (r < 0)
return r;
}
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */

View File

@ -649,10 +649,6 @@ typedef struct UnitVTable {
* of this type will immediately fail. */
bool (*supported)(void);
/* If this function is set, it's invoked first as part of starting a unit to allow start rate
* limiting checks to occur before we do anything else. */
int (*test_start_limit)(Unit *u);
/* The strings to print in status messages */
UnitStatusMessageFormats status_message_formats;

View File

@ -525,6 +525,7 @@ static int save_external_coredump(
if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
return log_error_errno(errno, "Failed to seek on coredump %s: %m", fn);
*ret_filename = TAKE_PTR(fn);
*ret_data_fd = TAKE_FD(fd);
*ret_size = (uint64_t) st.st_size;
*ret_truncated = truncated;

View File

@ -555,6 +555,8 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
assert(file);
assert(j);
(void) sd_journal_set_data_threshold(j, 0);
SD_JOURNAL_FOREACH_DATA(j, d, l) {
RETRIEVE(d, l, "MESSAGE_ID", mid);
RETRIEVE(d, l, "COREDUMP_PID", pid);

View File

@ -8,6 +8,10 @@
#include <sys/mount.h>
#include <sys/xattr.h>
#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#include "blkid-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
@ -1136,6 +1140,10 @@ int home_prepare_luks(
offset *= 512U;
}
} else {
#if HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
#endif
offset = info.lo_offset;
size = info.lo_sizelimit;
}
@ -1146,7 +1154,7 @@ int home_prepare_luks(
root_fd = open(user_record_home_directory(h), O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
if (root_fd < 0) {
r = log_error_errno(r, "Failed to open home directory: %m");
r = log_error_errno(errno, "Failed to open home directory: %m");
goto fail;
}
} else {
@ -1233,7 +1241,7 @@ int home_prepare_luks(
root_fd = open(subdir, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
if (root_fd < 0) {
r = log_error_errno(r, "Failed to open home directory: %m");
r = log_error_errno(errno, "Failed to open home directory: %m");
goto fail;
}
@ -2813,7 +2821,7 @@ int home_resize_luks(
if (r > 0)
log_info("Growing of partition completed.");
if (ioctl(image_fd, BLKRRPART, 0) < 0)
if (S_ISBLK(st.st_mode) && ioctl(image_fd, BLKRRPART, 0) < 0)
log_debug_errno(errno, "BLKRRPART failed on block device, ignoring: %m");
/* Tell LUKS about the new bigger size too */
@ -2887,7 +2895,7 @@ int home_resize_luks(
if (r > 0)
log_info("Shrinking of partition completed.");
if (ioctl(image_fd, BLKRRPART, 0) < 0)
if (S_ISBLK(st.st_mode) && ioctl(image_fd, BLKRRPART, 0) < 0)
log_debug_errno(errno, "BLKRRPART failed on block device, ignoring: %m");
} else {
r = home_store_embedded_identity(new_home, setup->root_fd, h->uid, embedded_home);

View File

@ -1651,6 +1651,8 @@ static int run(int argc, char *argv[]) {
log_setup();
cryptsetup_enable_logging(NULL);
umask(0022);
if (argc < 2 || argc > 3)

View File

@ -104,7 +104,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code);
int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, be32_t iaid, DHCP6IA *ia, uint16_t *ret_status_code);
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
struct in6_addr **addrs, size_t count);
int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen,

View File

@ -509,7 +509,13 @@ static int dhcp6_option_parse_pdprefix(sd_dhcp6_client *client, DHCP6Option *opt
return 0;
}
int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) {
int dhcp6_option_parse_ia(
sd_dhcp6_client *client,
DHCP6Option *iaoption,
be32_t iaid,
DHCP6IA *ia,
uint16_t *ret_status_code) {
uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX;
uint16_t iatype, optlen;
size_t iaaddr_offset;
@ -529,6 +535,14 @@ int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6I
if (len < DHCP6_OPTION_IA_NA_LEN)
return -ENOBUFS;
/* According to RFC8415, IAs which do not match the client's IAID should be ignored,
* but not necessary to ignore or refuse the whole message. */
if (((const struct ia_na*) iaoption->data)->id != iaid)
/* ENOANO indicates the option should be ignored. */
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO),
"Received an IA_NA option with a different IAID "
"from the one chosen by the client, ignoring.");
iaaddr_offset = DHCP6_OPTION_IA_NA_LEN;
memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na));
@ -547,6 +561,14 @@ int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6I
if (len < sizeof(ia->ia_pd))
return -ENOBUFS;
/* According to RFC8415, IAs which do not match the client's IAID should be ignored,
* but not necessary to ignore or refuse the whole message. */
if (((const struct ia_pd*) iaoption->data)->id != iaid)
/* ENOANO indicates the option should be ignored. */
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO),
"Received an IA_PD option with a different IAID "
"from the one chosen by the client, ignoring.");
iaaddr_offset = sizeof(ia->ia_pd);
memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd));
@ -564,13 +586,21 @@ int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6I
if (len < DHCP6_OPTION_IA_TA_LEN)
return -ENOBUFS;
/* According to RFC8415, IAs which do not match the client's IAID should be ignored,
* but not necessary to ignore or refuse the whole message. */
if (((const struct ia_ta*) iaoption->data)->id != iaid)
/* ENOANO indicates the option should be ignored. */
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO),
"Received an IA_TA option with a different IAID "
"from the one chosen by the client, ignoring.");
iaaddr_offset = DHCP6_OPTION_IA_TA_LEN;
memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta));
memcpy(&ia->ia_ta, iaoption->data, sizeof(ia->ia_ta));
break;
default:
return -ENOMSG;
return -EINVAL;
}
ia->type = iatype;

View File

@ -1119,7 +1119,6 @@ static int client_parse_message(
while (pos < len) {
DHCP6Option *option = (DHCP6Option *) &message->options[pos];
uint16_t optcode, optlen;
be32_t iaid_lease;
int status;
uint8_t *optval;
@ -1198,8 +1197,8 @@ static int client_parse_message(
break;
}
r = dhcp6_option_parse_ia(client, option, &lease->ia, &ia_na_status);
if (r < 0 && r != -ENOMSG)
r = dhcp6_option_parse_ia(client, option, client->ia_pd.ia_na.id, &lease->ia, &ia_na_status);
if (r < 0 && r != -ENOANO)
return r;
if (ia_na_status == DHCP6_STATUS_NO_ADDRS_AVAIL) {
@ -1207,16 +1206,6 @@ static int client_parse_message(
continue;
}
r = dhcp6_lease_get_iaid(lease, &iaid_lease);
if (r < 0)
return r;
if (client->ia_na.ia_na.id != iaid_lease) {
log_dhcp6_client(client, "%s has wrong IAID for IA NA",
dhcp6_message_type_to_string(message->type));
return -EINVAL;
}
if (lease->ia.addresses) {
lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1));
lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t2));
@ -1231,8 +1220,8 @@ static int client_parse_message(
break;
}
r = dhcp6_option_parse_ia(client, option, &lease->pd, &ia_pd_status);
if (r < 0 && r != -ENOMSG)
r = dhcp6_option_parse_ia(client, option, client->ia_pd.ia_pd.id, &lease->pd, &ia_pd_status);
if (r < 0 && r != -ENOANO)
return r;
if (ia_pd_status == DHCP6_STATUS_NO_PREFIX_AVAIL) {
@ -1240,16 +1229,6 @@ static int client_parse_message(
continue;
}
r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease);
if (r < 0)
return r;
if (client->ia_pd.ia_pd.id != iaid_lease) {
log_dhcp6_client(client, "%s has wrong IAID for IA PD",
dhcp6_message_type_to_string(message->type));
return -EINVAL;
}
if (lease->pd.addresses) {
lt_t1 = MIN(lt_t1, be32toh(lease->pd.ia_pd.lifetime_t1));
lt_t2 = MIN(lt_t2, be32toh(lease->pd.ia_pd.lifetime_t2));

View File

@ -287,25 +287,31 @@ static int test_option_status(sd_event *e) {
};
DHCP6Option *option;
DHCP6IA ia, pd;
be32_t iaid;
int r = 0;
log_debug("/* %s */", __func__);
memcpy(&iaid, option1 + 4, sizeof(iaid));
zero(ia);
option = (DHCP6Option *)option1;
assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
r = dhcp6_option_parse_ia(NULL, option, 0, &ia, NULL);
assert_se(r == -ENOANO);
r = dhcp6_option_parse_ia(NULL, option, iaid, &ia, NULL);
assert_se(r == 0);
assert_se(ia.addresses == NULL);
option->len = htobe16(17);
r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &ia, NULL);
assert_se(r == -ENOBUFS);
assert_se(ia.addresses == NULL);
option->len = htobe16(sizeof(DHCP6Option));
r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &ia, NULL);
assert_se(r == -ENOBUFS);
assert_se(ia.addresses == NULL);
@ -313,7 +319,7 @@ static int test_option_status(sd_event *e) {
option = (DHCP6Option *)option2;
assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len));
r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &ia, NULL);
assert_se(r >= 0);
assert_se(ia.addresses == NULL);
@ -321,7 +327,7 @@ static int test_option_status(sd_event *e) {
option = (DHCP6Option *)option3;
assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len));
r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &ia, NULL);
assert_se(r >= 0);
assert_se(ia.addresses != NULL);
dhcp6_lease_free_ia(&ia);
@ -330,7 +336,7 @@ static int test_option_status(sd_event *e) {
option = (DHCP6Option *)option4;
assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len));
r = dhcp6_option_parse_ia(NULL, option, &pd, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &pd, NULL);
assert_se(r >= 0);
assert_se(pd.addresses != NULL);
assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0);
@ -342,7 +348,7 @@ static int test_option_status(sd_event *e) {
option = (DHCP6Option *)option5;
assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len));
r = dhcp6_option_parse_ia(NULL, option, &pd, NULL);
r = dhcp6_option_parse_ia(NULL, option, iaid, &pd, NULL);
assert_se(r >= 0);
assert_se(pd.addresses != NULL);
dhcp6_lease_free_ia(&pd);
@ -447,13 +453,14 @@ static int test_advertise_option(sd_event *e) {
opt_clientid = true;
break;
case SD_DHCP6_OPTION_IA_NA:
case SD_DHCP6_OPTION_IA_NA: {
be32_t iaid = htobe32(0x0ecfa37d);
assert_se(optlen == 94);
assert_se(optval == &msg_advertise[26]);
assert_se(!memcmp(optval, &msg_advertise[26], optlen));
val = htobe32(0x0ecfa37d);
assert_se(!memcmp(optval, &val, sizeof(val)));
assert_se(!memcmp(optval, &iaid, sizeof(val)));
val = htobe32(80);
assert_se(!memcmp(optval + 4, &val, sizeof(val)));
@ -461,10 +468,10 @@ static int test_advertise_option(sd_event *e) {
val = htobe32(120);
assert_se(!memcmp(optval + 8, &val, sizeof(val)));
assert_se(dhcp6_option_parse_ia(NULL, option, &lease->ia, NULL) >= 0);
assert_se(dhcp6_option_parse_ia(NULL, option, iaid, &lease->ia, NULL) >= 0);
break;
}
case SD_DHCP6_OPTION_SERVERID:
assert_se(optlen == 14);
assert_se(optval == &msg_advertise[179]);
@ -598,6 +605,8 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
static int test_client_send_reply(DHCP6Message *request) {
DHCP6Message reply;
log_debug("/* %s */", __func__);
reply.transaction_id = request->transaction_id;
reply.type = DHCP6_REPLY;
@ -658,7 +667,7 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
assert_se(!memcmp(optval + 8, &val, sizeof(val)));
/* Then, this should refuse all addresses. */
assert_se(dhcp6_option_parse_ia(NULL, option, &lease->ia, NULL) >= 0);
assert_se(dhcp6_option_parse_ia(NULL, option, test_iaid, &lease->ia, NULL) >= 0);
break;
@ -704,6 +713,8 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
static int test_client_send_advertise(DHCP6Message *solicit) {
DHCP6Message advertise;
log_debug("/* %s */", __func__);
advertise.transaction_id = solicit->transaction_id;
advertise.type = DHCP6_ADVERTISE;
@ -899,6 +910,8 @@ int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
DHCP6Message *message;
log_debug("/* %s */", __func__);
assert_se(s == test_dhcp_fd[0]);
assert_se(server_address);
assert_se(packet);

View File

@ -178,7 +178,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
netns = ioctl(m->sock, SIOCGSKNS);
if (netns < 0)
log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns: %m");
log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns, ignoring: %m");
else {
struct stat a, b;
@ -191,9 +191,9 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
if (ERRNO_IS_PRIVILEGE(errno))
/* If we can't access PID1's netns info due to permissions, it's fine, this is a
* safety check only after all. */
log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns: %m");
log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns, ignoring: %m");
else
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns: %m");
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
} else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");

View File

@ -190,12 +190,17 @@ static void test_x11_convert_to_vconsole(void) {
}
int main(int argc, char **argv) {
_cleanup_free_ char *map = NULL;
test_setup_logging(LOG_DEBUG);
test_find_language_fallback();
test_find_converted_keymap();
test_find_legacy_keymap();
assert_se(get_testdata_dir("test-keymap-util/kbd-model-map", &map) >= 0);
assert_se(setenv("SYSTEMD_KBD_MODEL_MAP", map, 1) == 0);
test_vconsole_convert_to_x11();
test_x11_convert_to_vconsole();

View File

@ -33,6 +33,7 @@ SUBSYSTEM=="sound", TAG+="uaccess", \
# Webcams, frame grabber, TV cards
SUBSYSTEM=="video4linux", TAG+="uaccess"
SUBSYSTEM=="dvb", TAG+="uaccess"
SUBSYSTEM=="media", TAG+="uaccess"
# industrial cameras, some webcams, camcorders, set-top boxes, TV sets, audio devices, and more
SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_MIDI}=="1", TAG+="uaccess"

View File

@ -1537,7 +1537,7 @@ static int route_configure(
if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
}

View File

@ -4863,6 +4863,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
#if HAVE_LIBCRYPTSETUP
cryptsetup_enable_logging(NULL);
#endif
if (arg_image) {
assert(!arg_root);

View File

@ -359,6 +359,12 @@ int json_variant_new_real(JsonVariant **ret, long double d) {
}
REENABLE_WARNING;
/* JSON doesn't know NaN, +Infinity or -Infinity. Let's silently convert to 'null'. */
if (isnan(d) || isinf(d)) {
*ret = JSON_VARIANT_MAGIC_NULL;
return 0;
}
r = json_variant_new(&v, JSON_VARIANT_REAL, sizeof(d));
if (r < 0)
return r;

View File

@ -417,9 +417,10 @@ static int varlink_test_disconnect(Varlink *v) {
if (IN_SET(v->state, VARLINK_IDLE_CLIENT) && (v->write_disconnected || v->got_pollhup))
goto disconnect;
/* The server is still expecting to write more, but its write end is disconnected and it got a POLLHUP
* (i.e. from a disconnected client), so disconnect. */
if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE) && v->write_disconnected && v->got_pollhup)
/* We are on the server side and still want to send out more replies, but we saw POLLHUP already, and
* either got no buffered bytes to write anymore or already saw a write error. In that case we should
* shut down the varlink link. */
if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE) && (v->write_disconnected || v->output_buffer_size == 0) && v->got_pollhup)
goto disconnect;
return 0;

View File

@ -15,6 +15,10 @@
#include <sys/types.h>
#include <unistd.h>
#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#include "sd-device.h"
#include "alloc-util.h"
@ -409,6 +413,10 @@ static int delete_loopback(const char *device) {
return -EBUSY; /* propagate original error */
}
#if HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
#endif
if (FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR)) /* someone else already set LO_FLAGS_AUTOCLEAR for us? fine by us */
return -EBUSY; /* propagate original error */
@ -434,6 +442,10 @@ static int delete_loopback(const char *device) {
return 1;
}
#if HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
#endif
/* Linux makes LOOP_CLR_FD succeed whenever LO_FLAGS_AUTOCLEAR is set without actually doing
* anything. Very confusing. Let's hence not claim we did anything in this case. */
if (FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR))

View File

@ -741,7 +741,7 @@ static void print_status_info(
c = 0;
r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
if (r == -EBADR) {
if (r == -EBADR && arg_transport == BUS_TRANSPORT_LOCAL) {
unsigned k = 0;
pid_t extra[2];
@ -1649,11 +1649,13 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
r = sd_bus_message_enter_container(m, 'r', "ssba(ss)");
if (r < 0)
return r;
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(m, "ssb", &source, &destination, &ignore_enoent);
if (r <= 0)
break;
if (r < 0)
return bus_log_parse_error(r);
str = strjoin(ignore_enoent ? "-" : "",
source,
@ -1664,28 +1666,82 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
r = sd_bus_message_enter_container(m, 'a', "(ss)");
if (r < 0)
return r;
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0)
if (!strextend_with_separator(&str, ":", partition, ":", mount_options))
if (!strextend_with_separator(&str, ":", partition, mount_options))
return log_oom();
if (r < 0)
return r;
return bus_log_parse_error(r);
if (!strextend_with_separator(&paths, " ", str))
return log_oom();
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
bus_print_property_value(name, expected_value, flags, paths);
return 1;
} else if (streq(name, "ExtensionImages")) {
_cleanup_free_ char *paths = NULL;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sba(ss))");
if (r < 0)
return bus_log_parse_error(r);
for (;;) {
_cleanup_free_ char *str = NULL;
const char *source, *partition, *mount_options;
int ignore_enoent;
r = sd_bus_message_enter_container(m, 'r', "sba(ss)");
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
break;
r = sd_bus_message_read(m, "sb", &source, &ignore_enoent);
if (r < 0)
return bus_log_parse_error(r);
str = strjoin(ignore_enoent ? "-" : "", source);
if (!str)
return log_oom();
r = sd_bus_message_enter_container(m, 'a', "(ss)");
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0)
if (!strextend_with_separator(&str, ":", partition, mount_options))
return log_oom();
if (r < 0)
return bus_log_parse_error(r);
if (!strextend_with_separator(&paths, " ", str))
return log_oom();
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);

View File

@ -13,7 +13,6 @@ test_include_dir = include_directories('.')
path = run_command(sh, '-c', 'echo "$PATH"').stdout().strip()
test_env = environment()
test_env.set('SYSTEMD_KBD_MODEL_MAP', kbd_model_map)
test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map)
test_env.set('PATH', '@0@:@1@'.format(meson.build_root(), path))

View File

@ -306,7 +306,7 @@ static void test_path_unit(Manager *m) {
}
static void test_path_directorynotempty(Manager *m) {
const char *test_path = "/tmp/test-path_directorynotempty/";
const char *test_file, *test_path = "/tmp/test-path_directorynotempty/";
Unit *unit = NULL;
Path *path = NULL;
Service *service = NULL;
@ -328,7 +328,8 @@ static void test_path_directorynotempty(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
assert_se(mkdir_p(test_path, 0755) >= 0);
assert_se(touch(strjoina(test_path, "test_file")) >= 0);
test_file = strjoina(test_path, "test_file");
assert_se(touch(test_file) >= 0);
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
return;

View File

@ -828,6 +828,7 @@ int udev_event_spawn(UdevEvent *event,
static int rename_netif(UdevEvent *event) {
sd_device *dev = event->dev;
const char *oldname;
unsigned flags;
int ifindex, r;
if (!event->name)
@ -855,6 +856,16 @@ static int rename_netif(UdevEvent *event) {
return 0;
}
r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags);
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get link flags: %m");
if (FLAGS_SET(flags, IFF_UP)) {
log_device_info(dev, "Network interface '%s' is already up, refusing to rename to '%s'.",
oldname, event->name);
return 0;
}
/* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
r = device_add_property(dev, "ID_RENAMING", "1");
if (r < 0)

View File

@ -512,7 +512,7 @@ static int display_services(int argc, char *argv[], void *userdata) {
if (fd < 0)
return log_error_errno(r, "Failed to allocate AF_UNIX/SOCK_STREAM socket: %m");
if (connect(fd, &sockaddr.un, sockaddr_len) < 0) {
if (connect(fd, &sockaddr.sa, sockaddr_len) < 0) {
no = strjoin("No (", errno_to_name(errno), ")");
if (!no)
return log_oom();

View File

@ -100,7 +100,7 @@ static int create_device(void) {
fprintf(f,
"[Unit]\n"
"Description=Integrity Protection Setup for %%I\n"
"Description=Verity Protection Setup for %%I\n"
"Documentation=man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n"
"SourcePath=/proc/cmdline\n"
"DefaultDependencies=no\n"

View File

@ -30,7 +30,7 @@ static int help(void) {
printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH [OPTIONS]\n"
"%s detach VOLUME\n\n"
"Attach or detach an integrity protected block device.\n"
"Attach or detach a verity protected block device.\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
program_invocation_short_name,

View File

@ -1 +0,0 @@
../TEST-01-BASIC/Makefile

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -e
TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/17433"
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
do_test "$@"

View File

@ -33,8 +33,9 @@ if install_tests
install_dir : testdata_dir)
install_subdir('testsuite-52.units',
install_dir : testdata_dir)
install_subdir('testsuite-63.units',
install_dir : testdata_dir)
install_data(kbd_model_map,
install_dir : testdata_dir + '/test-keymap-util')
testsuite08_dir = testdata_dir + '/testsuite-08.units'
install_data('testsuite-08.units/-.mount',

View File

@ -0,0 +1 @@
../../src/locale/kbd-model-map

View File

@ -1,9 +1,6 @@
[Unit]
Requires=test10.socket
ConditionPathExistsGlob=/tmp/nonexistent
# Make sure we hit the socket trigger limit in the test and not the service start limit.
StartLimitInterval=1000
StartLimitBurst=1000
[Service]
ExecStart=true

View File

@ -1,2 +0,0 @@
[Path]
PathExists=/tmp/test63

View File

@ -1,5 +0,0 @@
[Unit]
ConditionPathExists=!/tmp/nonexistent
[Service]
ExecStart=true

View File

@ -1,16 +0,0 @@
[Unit]
Description=TEST-63-ISSUE-17433
[Service]
ExecStartPre=rm -f /failed /testok
Type=oneshot
ExecStart=rm -f /tmp/nonexistent
ExecStart=systemctl start test63.path
ExecStart=touch /tmp/test63
# Make sure systemd has sufficient time to hit the start limit for test63.service.
ExecStart=sleep 2
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
ExecStart=sh -x -c 'echo OK >/testok'

View File

@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Remote Verity Integrity Protected Volumes
Description=Remote Verity Protected Volumes
Documentation=man:systemd.special(7)
After=remote-fs-pre.target veritysetup-pre.target
DefaultDependencies=no

View File

@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Local Verity Integrity Protected Volumes (Pre)
Description=Local Verity Protected Volumes (Pre)
Documentation=man:systemd.special(7)
RefuseManualStart=yes
Before=veritysetup.target

View File

@ -8,5 +8,5 @@
# (at your option) any later version.
[Unit]
Description=Local Verity Integrity Protected Volumes
Description=Local Verity Protected Volumes
Documentation=man:systemd.special(7)