mirror of
https://git.proxmox.com/git/systemd
synced 2025-10-18 13:31:59 +00:00
New upstream version 249.6
This commit is contained in:
parent
ce5f39bdc4
commit
2223c7731a
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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; \
|
||||
})
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -1651,6 +1651,8 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_setup();
|
||||
|
||||
cryptsetup_enable_logging(NULL);
|
||||
|
||||
umask(0022);
|
||||
|
||||
if (argc < 2 || argc > 3)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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.");
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -1 +0,0 @@
|
||||
../TEST-01-BASIC/Makefile
|
@ -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 "$@"
|
@ -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',
|
||||
|
1
test/test-keymap-util/kbd-model-map
Symbolic link
1
test/test-keymap-util/kbd-model-map
Symbolic link
@ -0,0 +1 @@
|
||||
../../src/locale/kbd-model-map
|
@ -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
|
||||
|
@ -1,2 +0,0 @@
|
||||
[Path]
|
||||
PathExists=/tmp/test63
|
@ -1,5 +0,0 @@
|
||||
[Unit]
|
||||
ConditionPathExists=!/tmp/nonexistent
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
@ -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'
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user