mirror of
https://github.com/systemd/systemd.git
synced 2025-03-10 16:58:28 +03:00
Compare commits
31 Commits
c04a4937a3
...
e9f781a5a4
Author | SHA1 | Date | |
---|---|---|---|
|
e9f781a5a4 | ||
|
cb3801a4c9 | ||
|
8a135111ca | ||
|
5e837858e7 | ||
|
a3fecea5e2 | ||
|
3b9010b170 | ||
|
cf89e48028 | ||
|
3cbf00a30c | ||
|
0f67cb3606 | ||
|
5ceb38cb1e | ||
|
312cf91005 | ||
|
b1b128d0e2 | ||
|
91cdc8ab0f | ||
|
009a02b263 | ||
|
b83358b87f | ||
|
bf1ef54d30 | ||
|
8f9ea89ce4 | ||
|
5229cd839a | ||
|
595ca10f37 | ||
|
6e3f32cc56 | ||
|
1462736c7e | ||
|
f441831c9e | ||
|
4bc06da775 | ||
|
ced0ef3b35 | ||
|
e95861d909 | ||
|
0f72af536f | ||
|
0e5a83f510 | ||
|
8f114904fc | ||
|
25b1a73f71 | ||
|
a5370d35d6 | ||
|
1184626a26 |
2
TODO
2
TODO
@ -795,7 +795,7 @@ Features:
|
||||
* udevd: extend memory pressure logic: also kill any idle worker processes
|
||||
|
||||
* udevadm: to make symlink querying with udevadm nicer:
|
||||
- do not enable the pager for queries like 'udevadm info -q -r symlink'
|
||||
- do not enable the pager for queries like 'udevadm info -q symlink -r'
|
||||
- add mode with newlines instead of spaces (for grep)?
|
||||
|
||||
* SIGRTMIN+18 and memory pressure handling should still be added to: hostnamed,
|
||||
|
@ -10,7 +10,7 @@ sudo systemd-cryptsetup attach mytest /dev/sdXn - fido2-device=auto
|
||||
# If that worked, let's now add the same line persistently to /etc/crypttab,
|
||||
# for the future. We don't want to use the (unstable) /dev/sdX name, so let's
|
||||
# figure out a stable link:
|
||||
udevadm info -q -r symlink /dev/sdXn
|
||||
udevadm info -q symlink -r /dev/sdXn
|
||||
|
||||
# Now add the line using the by-uuid symlink to /etc/crypttab:
|
||||
sudo bash -c 'echo "mytest /dev/disk/by-uuid/... - fido2-device=auto" >>/etc/crypttab'
|
||||
|
@ -97,6 +97,18 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.break=</varname></term>
|
||||
<term><varname>rd.systemd.break=</varname></term>
|
||||
<listitem>
|
||||
<para>Parameters understood by
|
||||
<citerefentry><refentrytitle>systemd-debug-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
to pause the boot process at a certain point and spawn a debug shell.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.run=</varname></term>
|
||||
<term><varname>systemd.run_success_action=</varname></term>
|
||||
|
@ -205,6 +205,11 @@
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">smbios11</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">chid</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
@ -1084,6 +1089,37 @@ io.systemd.credential:vmm.notify_socket=vsock-stream:2:254570042
|
||||
<xi:include href="version-info.xml" xpointer="v257"/>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze chid</command></title>
|
||||
|
||||
<para>Shows a list of Computer Hardware IDs (CHIDs) of the local system. These IDs identify the
|
||||
system's computer hardware, based on SMBIOS data. See <ulink
|
||||
url="https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/using-chids">Using Computer
|
||||
Hardware IDs (CHIDs)</ulink> for details about CHIDs.</para>
|
||||
|
||||
<example>
|
||||
<title>Example output</title>
|
||||
<programlisting>$ systemd-analyze chid
|
||||
TYPE INPUT CHID
|
||||
3 MFPSmp 520537c0-3b59-504f-b062-9682ea236b21
|
||||
4 MFPS-- edf05dc8-a53d-5b2c-8023-630bca2a2463
|
||||
5 MFP--- ebc6a4d9-ec48-537a-916b-c69fa4fdd814
|
||||
6 M--Smp 5ebe4bba-f598-5e90-9ff2-9fd0d3211465
|
||||
7 M--S-- 1a3fb835-b42a-5f9c-a38c-eff5bfd5c41d
|
||||
8 M-P-mp 2a831dce-8163-5bad-8406-435b8c752dd8
|
||||
9 M-P--- 7c21c878-4a75-50f7-9816-21e811588da0
|
||||
10 MF--mp 9a003537-bcc5-500e-b10a-8d8892e4fc64
|
||||
11 MF---- bb9122bb-8a5c-50d2-a742-a85beb719909
|
||||
13 M---mp bfc36935-5032-5987-a0a3-6311f01de33a
|
||||
|
||||
LEGEND: M → sys_vendor (LENOVO) ┄ F → product_family (ThinkPad X1 Carbon Gen 9) ┄ P → product_name (20XW0055GE)
|
||||
S → product_sku (LENOVO_MT_20XW_BU_Think_FM_ThinkPad X1 Carbon Gen 9) ┄ m → board_vendor (LENOVO)
|
||||
p → board_name (20XW0055GE)</programlisting>
|
||||
</example>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -31,45 +31,131 @@
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><filename>systemd-debug-generator</filename> is a generator
|
||||
that reads the kernel command line and understands three
|
||||
options:</para>
|
||||
<para><command>systemd-debug-generator</command> is a generator that provides some debugging
|
||||
functionality.</para>
|
||||
|
||||
<para>If the <option>systemd.mask=</option> or <option>rd.systemd.mask=</option>
|
||||
option is specified and followed by a unit name, this unit is
|
||||
masked for the runtime (i.e. for this session — from boot to shutdown), similarly to the effect of
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>mask</command> command. This is useful to boot with
|
||||
certain units removed from the initial boot transaction for
|
||||
debugging system startup. May be specified more than once.
|
||||
<option>rd.systemd.mask=</option> is honored only by initial
|
||||
RAM disk (initrd) while <option>systemd.mask=</option> is
|
||||
honored only in the main system.</para>
|
||||
|
||||
<para>If the <option>systemd.wants=</option> or
|
||||
<option>rd.systemd.wants=</option> option is specified
|
||||
and followed by a unit name, a start job for this unit is added to
|
||||
the initial transaction. This is useful to start one or more
|
||||
additional units at boot. May be specified more than once.
|
||||
<option>rd.systemd.wants=</option> is honored only by initial
|
||||
RAM disk (initrd) while <option>systemd.wants=</option> is
|
||||
honored only in the main system.</para>
|
||||
|
||||
<para>If the <option>systemd.debug_shell</option> or <option>rd.systemd.debug_shell</option> option is
|
||||
specified, the debug shell service <literal>debug-shell.service</literal> is pulled into the boot
|
||||
transaction and a debug shell will be spawned during early boot. By default,
|
||||
<filename>&DEBUGTTY;</filename> is used, but a specific tty can also be specified, either with or without
|
||||
the <filename>/dev/</filename> prefix. To set the tty to use without enabling the debug shell, the
|
||||
<option>systemd.default_debug_tty=</option> option can be used which also takes a tty with or without the
|
||||
<filename>/dev/</filename> prefix. Note that the shell may also be turned on persistently by enabling it
|
||||
with <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>enable</command> command. <option>rd.systemd.debug_shell</option> is honored only by initial
|
||||
RAM disk (initrd) while <option>systemd.debug_shell</option> is honored only in the main system.</para>
|
||||
|
||||
<para><filename>systemd-debug-generator</filename> implements
|
||||
<para><command>systemd-debug-generator</command> implements
|
||||
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Kernel Command Line</title>
|
||||
|
||||
<para><command>systemd-debug-generator</command> understands the following kernel command line
|
||||
parameters:</para>
|
||||
|
||||
<variablelist class='kernel-commandline-options'>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.mask=</varname></term>
|
||||
<term><varname>rd.systemd.mask=</varname></term>
|
||||
|
||||
<listitem><para>These options take a unit name as argument. The unit specified is masked for the
|
||||
runtime (i.e. for this session — from boot to shutdown), similarly to the effect of
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>mask</command> command. This is useful to boot with certain units removed from the initial
|
||||
boot transaction for debugging system startup. May be specified more than once. The option prefixed
|
||||
with <literal>rd.</literal> is honored only in the initrd, while the one without prefix is only
|
||||
honored in the main system.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v215"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.wants=</varname></term>
|
||||
<term><varname>rd.systemd.wants=</varname></term>
|
||||
|
||||
<listitem><para>These options take a unit name as argument. A start job for this unit is added to the
|
||||
initial transaction. This is useful to start one or more additional units at boot. May be specified
|
||||
more than once. The option prefixed with <literal>rd.</literal> is honored only in the initrd, while
|
||||
the one that is not prefixed only in the main system.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v215"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.debug_shell</varname></term>
|
||||
<term><varname>rd.systemd.debug_shell</varname></term>
|
||||
<term><varname>systemd.default_debug_tty=</varname></term>
|
||||
<term><varname>rd.systemd.default_debug_tty=</varname></term>
|
||||
|
||||
<listitem><para>If the <option>systemd.debug_shell</option> or
|
||||
<option>rd.systemd.debug_shell</option> option is specified, the debug shell service
|
||||
<literal>debug-shell.service</literal> is pulled into the boot transaction and a debug shell will be
|
||||
spawned during early boot. By default, <filename>&DEBUGTTY;</filename> is used, but a specific tty
|
||||
can also be specified, either with or without the <filename>/dev/</filename> prefix. To set the tty
|
||||
to use without enabling the debug shell, the <option>systemd.default_debug_tty=</option> option can
|
||||
be used which also takes a tty with or without the <filename>/dev/</filename> prefix. Note that the
|
||||
shell may also be turned on persistently by enabling it with
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>enable</command> command. The options prefixed with <literal>rd.</literal> are honored only
|
||||
in the initrd, while the ones without prefix are only honored in the main system.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v215"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.break=</varname></term>
|
||||
<term><varname>rd.systemd.break=</varname></term>
|
||||
|
||||
<listitem><para>Takes one of <option>pre-udev</option>, <option>pre-basic</option>,
|
||||
<option>pre-mount</option>, or <option>pre-switch-root</option> (the default for the
|
||||
<literal>rd.</literal> option). It also accepts multiple values separated by comma
|
||||
(<literal>,</literal>). These options allow to pause the boot process at a certain point and spawn a
|
||||
debug shell. After exiting this shell, the system will resume booting. The option prefixed with
|
||||
<literal>rd.</literal> is honored only in the initrd, while the one without prefix is only honored in
|
||||
the main system.</para>
|
||||
|
||||
<table>
|
||||
<title>Available breakpoints</title>
|
||||
|
||||
<tgroup cols='4'>
|
||||
<colspec colname='breakpoint' />
|
||||
<colspec colname='description' />
|
||||
<colspec colname='initrd' />
|
||||
<colspec colname='main' />
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Breakpoints</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Can be used in the initrd</entry>
|
||||
<entry>Can be used in the main system</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><option>pre-udev</option></entry>
|
||||
<entry>Before starting to process kernel uevents, i.e., before <filename>systemd-udevd.service</filename> starts.</entry>
|
||||
<entry>✓</entry>
|
||||
<entry>✓</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>pre-basic</option></entry>
|
||||
<entry>Before leaving early boot and regular services start, i.e., before <filename>basic.target</filename> is reached.</entry>
|
||||
<entry>✓</entry>
|
||||
<entry>✓</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>pre-mount</option></entry>
|
||||
<entry>Before the root filesystem is mounted, i.e., before <filename>sysroot.mount</filename> starts.</entry>
|
||||
<entry>✓</entry>
|
||||
<entry>✗</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><option>pre-switch-root</option></entry>
|
||||
<entry>Before switching from the initrd to the real root.</entry>
|
||||
<entry>✓</entry>
|
||||
<entry>✗</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>System Credentials</title>
|
||||
|
||||
@ -108,6 +194,8 @@
|
||||
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd.system-credentials</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
||||
</simplelist></para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -672,7 +672,7 @@
|
||||
|
||||
<listitem><para>Specifies what anchor point <varname>Path=</varname> should be relative to. Takes one
|
||||
of <constant>root</constant>, <constant>esp</constant>, <constant>xbootldr</constant>,
|
||||
<constant>boot</constant> or <constant>directory</constant>. If unspecified, defaults to
|
||||
<constant>boot</constant> or <constant>explicit</constant>. If unspecified, defaults to
|
||||
<constant>root</constant>.</para>
|
||||
|
||||
<para>If set to <constant>root</constant>, <constant>esp</constant>, <constant>xbootldr</constant>,
|
||||
|
@ -93,7 +93,7 @@
|
||||
XML file.
|
||||
This may be used by software centers (such as GNOME Software or KDE Discover) to present rich
|
||||
metadata about this feature.
|
||||
This includes display names, chagnelogs, icons, and more.
|
||||
This includes display names, changelogs, icons, and more.
|
||||
This setting supports specifier expansion; see below for details on supported specifiers.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
@ -177,7 +177,7 @@ Enabled=false
|
||||
</programlisting></para>
|
||||
|
||||
<para>The above defines the <literal>devel</literal> feature, and disables it by default.
|
||||
Now let's a define a transfer that's associated with this feature:</para>
|
||||
Now let's define a transfer that's associated with this feature:</para>
|
||||
|
||||
<para><programlisting># /usr/lib/sysupdate.d/50-devel.transfer
|
||||
[Transfer]
|
||||
|
@ -10,7 +10,7 @@ sudo systemd-cryptsetup attach mytest /dev/sdXn - tpm2-device=auto
|
||||
# If that worked, let's now add the same line persistently to /etc/crypttab,
|
||||
# for the future. We don't want to use the (unstable) /dev/sdX name, so let's
|
||||
# figure out a stable link:
|
||||
udevadm info -q -r symlink /dev/sdXn
|
||||
udevadm info -q symlink -r /dev/sdXn
|
||||
|
||||
# Now add the line using the by-uuid symlink to /etc/crypttab:
|
||||
sudo bash -c 'echo "mytest /dev/disk/by-uuid/... - tpm2-device=auto" >>/etc/crypttab'
|
||||
|
@ -26,7 +26,7 @@ sudo systemd-cryptsetup attach mytest /dev/sdXn - pkcs11-uri=auto
|
||||
# If that worked, let's now add the same line persistently to /etc/crypttab,
|
||||
# for the future. We don't want to use the (unstable) /dev/sdX name, so let's
|
||||
# figure out a stable link:
|
||||
udevadm info -q -r symlink /dev/sdXn
|
||||
udevadm info -q symlink -r /dev/sdXn
|
||||
|
||||
# Now add the line using the by-uuid symlink to /etc/crypttab:
|
||||
sudo bash -c 'echo "mytest /dev/disk/by-uuid/... - pkcs11-uri=auto" >>/etc/crypttab'
|
||||
|
@ -67,7 +67,7 @@ _systemd_analyze() {
|
||||
)
|
||||
|
||||
local -A VERBS=(
|
||||
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk has-tpm2 smbios11'
|
||||
[STANDALONE]='time blame unit-files unit-paths exit-status compare-versions calendar timestamp timespan pcrs srk has-tpm2 smbios11 chid'
|
||||
[CRITICAL_CHAIN]='critical-chain'
|
||||
[DOT]='dot'
|
||||
[DUMP]='dump'
|
||||
|
224
src/analyze/analyze-chid.c
Normal file
224
src/analyze/analyze-chid.c
Normal file
@ -0,0 +1,224 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "analyze.h"
|
||||
#include "analyze-chid.h"
|
||||
#include "chid-fundamental.h"
|
||||
#include "efi-api.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "parse-util.h"
|
||||
#include "strv.h"
|
||||
#include "utf8.h"
|
||||
#include "virt.h"
|
||||
|
||||
static int parse_chid_type(const char *s, size_t *ret) {
|
||||
unsigned u;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
r = safe_atou(s, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (u >= CHID_TYPES_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (ret)
|
||||
*ret = u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char chid_smbios_fields_char[_CHID_SMBIOS_FIELDS_MAX] = {
|
||||
[CHID_SMBIOS_MANUFACTURER] = 'M',
|
||||
[CHID_SMBIOS_FAMILY] = 'F',
|
||||
[CHID_SMBIOS_PRODUCT_NAME] = 'P',
|
||||
[CHID_SMBIOS_PRODUCT_SKU] = 'S',
|
||||
[CHID_SMBIOS_BASEBOARD_MANUFACTURER] = 'm',
|
||||
[CHID_SMBIOS_BASEBOARD_PRODUCT] = 'p',
|
||||
};
|
||||
|
||||
static char *chid_smbios_fields_string(uint32_t combination) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
for (ChidSmbiosFields f = 0; f < _CHID_SMBIOS_FIELDS_MAX; f++) {
|
||||
char c;
|
||||
|
||||
c = (combination & (UINT32_C(1) << f)) ? chid_smbios_fields_char[f] : '-';
|
||||
|
||||
if (!strextend(&s, CHAR_TO_STR(c)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TAKE_PTR(s);
|
||||
}
|
||||
|
||||
static int add_chid(Table *table, const EFI_GUID guids[static CHID_TYPES_MAX], size_t t) {
|
||||
int r;
|
||||
|
||||
assert(table);
|
||||
assert(guids);
|
||||
assert(t < CHID_TYPES_MAX);
|
||||
|
||||
sd_id128_t id = efi_guid_to_id128(guids + t);
|
||||
|
||||
if (sd_id128_is_null(id))
|
||||
return 0;
|
||||
|
||||
_cleanup_free_ char *flags = chid_smbios_fields_string(chid_smbios_table[t]);
|
||||
if (!flags)
|
||||
return log_oom();
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_UINT, (unsigned) t,
|
||||
TABLE_STRING, flags,
|
||||
TABLE_UUID, id);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smbios_fields_free(char16_t *(*fields)[_CHID_SMBIOS_FIELDS_MAX]) {
|
||||
assert(fields);
|
||||
|
||||
FOREACH_ARRAY(i, *fields, _CHID_SMBIOS_FIELDS_MAX)
|
||||
free(*i);
|
||||
}
|
||||
|
||||
int verb_chid(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static const char *const smbios_files[_CHID_SMBIOS_FIELDS_MAX] = {
|
||||
[CHID_SMBIOS_MANUFACTURER] = "sys_vendor",
|
||||
[CHID_SMBIOS_FAMILY] = "product_family",
|
||||
[CHID_SMBIOS_PRODUCT_NAME] = "product_name",
|
||||
[CHID_SMBIOS_PRODUCT_SKU] = "product_sku",
|
||||
[CHID_SMBIOS_BASEBOARD_MANUFACTURER] = "board_vendor",
|
||||
[CHID_SMBIOS_BASEBOARD_PRODUCT] = "board_name",
|
||||
};
|
||||
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
int r;
|
||||
|
||||
if (detect_container() > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Container environments do not have SMBIOS.");
|
||||
|
||||
table = table_new("type", "input", "chid");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
(void) table_set_align_percent(table, table_get_cell(table, 0, 0), 100);
|
||||
(void) table_set_align_percent(table, table_get_cell(table, 0, 1), 50);
|
||||
|
||||
_cleanup_close_ int smbios_fd = open("/sys/class/dmi/id", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
if (smbios_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open SMBIOS sysfs object: %m");
|
||||
|
||||
_cleanup_(smbios_fields_free) char16_t* smbios_fields[_CHID_SMBIOS_FIELDS_MAX] = {};
|
||||
for (ChidSmbiosFields f = 0; f < _CHID_SMBIOS_FIELDS_MAX; f++) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t size;
|
||||
|
||||
r = read_virtual_file_at(smbios_fd, smbios_files[f], SIZE_MAX, &buf, &size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read SMBIOS field '%s': %m", smbios_files[f]);
|
||||
|
||||
if (size < 1 || buf[size-1] != '\n')
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected SMBIOS field '%s' to end in newline, but it doesn't, refusing.", smbios_files[f]);
|
||||
|
||||
size--;
|
||||
|
||||
smbios_fields[f] = utf8_to_utf16(buf, size);
|
||||
if (!smbios_fields[f])
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
EFI_GUID chids[CHID_TYPES_MAX] = {};
|
||||
chid_calculate((const char16_t* const*) smbios_fields, chids);
|
||||
|
||||
if (strv_isempty(strv_skip(argv, 1)))
|
||||
for (size_t t = 0; t < CHID_TYPES_MAX; t++) {
|
||||
r = add_chid(table, chids, t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
STRV_FOREACH(as, strv_skip(argv, 1)) {
|
||||
size_t t;
|
||||
r = parse_chid_type(*as, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to pare CHID type: %s", *as);
|
||||
|
||||
r = add_chid(table, chids, t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) table_set_sort(table, (size_t) 0);
|
||||
}
|
||||
|
||||
r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to output table: %m");
|
||||
|
||||
if (!sd_json_format_enabled(arg_json_format_flags)) {
|
||||
_cleanup_free_ char *legend = NULL;
|
||||
bool separator = false;
|
||||
size_t w = 0;
|
||||
|
||||
legend = strjoin(ansi_grey(), "LEGEND: ", ansi_normal());
|
||||
if (!legend)
|
||||
return log_oom();
|
||||
|
||||
for (ChidSmbiosFields f = 0; f < _CHID_SMBIOS_FIELDS_MAX; f++) {
|
||||
_cleanup_free_ char *c = utf16_to_utf8(smbios_fields[f], SIZE_MAX);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
if (!strextend(&legend,
|
||||
ansi_grey(),
|
||||
separator ? " " : "",
|
||||
separator ? special_glyph(SPECIAL_GLYPH_HORIZONTAL_DOTTED) : "",
|
||||
separator ? " " : "",
|
||||
ansi_normal(),
|
||||
CHAR_TO_STR(chid_smbios_fields_char[f]),
|
||||
ansi_grey(),
|
||||
" ",
|
||||
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT),
|
||||
" ",
|
||||
ansi_normal(),
|
||||
smbios_files[f],
|
||||
ansi_grey(),
|
||||
" (",
|
||||
ansi_highlight(),
|
||||
c,
|
||||
ansi_grey(),
|
||||
")",
|
||||
ansi_normal()))
|
||||
return log_oom();
|
||||
|
||||
w += separator * 3 +
|
||||
4 +
|
||||
utf8_console_width(smbios_files[f]) +
|
||||
2 +
|
||||
utf8_console_width(c) +
|
||||
1;
|
||||
|
||||
if (w > 79) {
|
||||
if (!strextend(&legend, "\n "))
|
||||
return log_oom();
|
||||
|
||||
separator = false;
|
||||
w = 8;
|
||||
} else
|
||||
separator = true;
|
||||
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
puts(legend);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
4
src/analyze/analyze-chid.h
Normal file
4
src/analyze/analyze-chid.h
Normal file
@ -0,0 +1,4 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
int verb_chid(int argc, char *argv[], void *userdata);
|
@ -18,6 +18,7 @@
|
||||
#include "analyze-calendar.h"
|
||||
#include "analyze-capability.h"
|
||||
#include "analyze-cat-config.h"
|
||||
#include "analyze-chid.h"
|
||||
#include "analyze-compare-versions.h"
|
||||
#include "analyze-condition.h"
|
||||
#include "analyze-critical-chain.h"
|
||||
@ -219,6 +220,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" filesystems [NAME...] List known filesystems\n"
|
||||
" architectures [NAME...] List known architectures\n"
|
||||
" smbios11 List strings passed via SMBIOS Type #11\n"
|
||||
" chid List local CHIDs\n"
|
||||
"\n%3$sExpression Evaluation:%4$s\n"
|
||||
" condition CONDITION... Evaluate conditions and asserts\n"
|
||||
" compare-versions VERSION1 [OP] VERSION2\n"
|
||||
@ -593,10 +595,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --offline= requires one or more units to perform a security review.");
|
||||
|
||||
if (sd_json_format_enabled(arg_json_format_flags) && !STRPTR_IN_SET(argv[optind], "security", "inspect-elf", "plot", "fdstore", "pcrs", "architectures", "capability", "exit-status"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --json= is only supported for security, inspect-elf, plot, fdstore, pcrs, architectures, capability, exit-status right now.");
|
||||
|
||||
if (arg_threshold != 100 && !streq_ptr(argv[optind], "security"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --threshold= is only supported for security right now.");
|
||||
@ -631,10 +629,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (streq_ptr(argv[optind], "condition") && arg_unit && optind < argc - 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No conditions can be passed if --unit= is used.");
|
||||
|
||||
if ((!arg_legend && !STRPTR_IN_SET(argv[optind], "plot", "architectures")) ||
|
||||
(streq_ptr(argv[optind], "plot") && !arg_legend && !arg_table && !sd_json_format_enabled(arg_json_format_flags)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --no-legend is only supported for plot with either --table or --json=.");
|
||||
|
||||
if (arg_table && !streq_ptr(argv[optind], "plot"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --table is only supported for plot right now.");
|
||||
|
||||
@ -691,6 +685,7 @@ static int run(int argc, char *argv[]) {
|
||||
{ "srk", VERB_ANY, 1, 0, verb_srk },
|
||||
{ "architectures", VERB_ANY, VERB_ANY, 0, verb_architectures },
|
||||
{ "smbios11", VERB_ANY, 1, 0, verb_smbios11 },
|
||||
{ "chid", VERB_ANY, VERB_ANY, 0, verb_chid },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@ systemd_analyze_sources = files(
|
||||
'analyze-calendar.c',
|
||||
'analyze-capability.c',
|
||||
'analyze-cat-config.c',
|
||||
'analyze-chid.c',
|
||||
'analyze-compare-versions.c',
|
||||
'analyze-condition.c',
|
||||
'analyze-critical-chain.c',
|
||||
|
@ -8,8 +8,9 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "capability-util.h"
|
||||
#include "cap-list.h"
|
||||
#include "capability-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "logarithm.h"
|
||||
@ -17,6 +18,8 @@
|
||||
#include "missing_prctl.h"
|
||||
#include "missing_threads.h"
|
||||
#include "parse-util.h"
|
||||
#include "pidref.h"
|
||||
#include "stat-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
int have_effective_cap(int value) {
|
||||
@ -607,3 +610,78 @@ int capability_get_ambient(uint64_t *ret) {
|
||||
*ret = a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pidref_get_capability(const PidRef *pidref, CapabilityQuintet *ret) {
|
||||
int r;
|
||||
|
||||
if (!pidref_is_set(pidref))
|
||||
return -ESRCH;
|
||||
if (pidref_is_remote(pidref))
|
||||
return -EREMOTE;
|
||||
|
||||
const char *path = procfs_file_alloca(pidref->pid, "status");
|
||||
_cleanup_fclose_ FILE *f = fopen(path, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT && proc_mounted() == 0)
|
||||
return -ENOSYS;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
CapabilityQuintet q = CAPABILITY_QUINTET_NULL;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
static const struct {
|
||||
const char *field;
|
||||
size_t offset;
|
||||
} fields[] = {
|
||||
{ "CapBnd:", offsetof(CapabilityQuintet, bounding) },
|
||||
{ "CapInh:", offsetof(CapabilityQuintet, inheritable) },
|
||||
{ "CapPrm:", offsetof(CapabilityQuintet, permitted) },
|
||||
{ "CapEff:", offsetof(CapabilityQuintet, effective) },
|
||||
{ "CapAmb:", offsetof(CapabilityQuintet, ambient) },
|
||||
};
|
||||
|
||||
FOREACH_ELEMENT(i, fields) {
|
||||
|
||||
const char *p = first_word(line, i->field);
|
||||
if (!p)
|
||||
continue;
|
||||
|
||||
uint64_t *v = (uint64_t*) ((uint8_t*) &q + i->offset);
|
||||
|
||||
if (*v != CAP_MASK_UNSET)
|
||||
return -EBADMSG;
|
||||
|
||||
r = safe_atoux64(p, v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*v == CAP_MASK_UNSET)
|
||||
return -EBADMSG;
|
||||
}
|
||||
}
|
||||
|
||||
if (q.effective == CAP_MASK_UNSET ||
|
||||
q.inheritable == CAP_MASK_UNSET ||
|
||||
q.permitted == CAP_MASK_UNSET ||
|
||||
q.effective == CAP_MASK_UNSET ||
|
||||
q.ambient == CAP_MASK_UNSET)
|
||||
return -EBADMSG;
|
||||
|
||||
r = pidref_verify(pidref);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = q;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "macro.h"
|
||||
#include "missing_capability.h"
|
||||
#include "pidref.h"
|
||||
|
||||
/* Special marker used when storing a capabilities mask as "unset" */
|
||||
#define CAP_MASK_UNSET UINT64_MAX
|
||||
@ -66,14 +67,18 @@ typedef struct CapabilityQuintet {
|
||||
|
||||
assert_cc(CAP_LAST_CAP < 64);
|
||||
|
||||
#define CAPABILITY_QUINTET_NULL { CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET }
|
||||
#define CAPABILITY_QUINTET_NULL (CapabilityQuintet) { CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET }
|
||||
|
||||
static inline bool capability_is_set(uint64_t v) {
|
||||
return v != CAP_MASK_UNSET;
|
||||
}
|
||||
|
||||
static inline bool capability_quintet_is_set(const CapabilityQuintet *q) {
|
||||
return q->effective != CAP_MASK_UNSET ||
|
||||
q->bounding != CAP_MASK_UNSET ||
|
||||
q->inheritable != CAP_MASK_UNSET ||
|
||||
q->permitted != CAP_MASK_UNSET ||
|
||||
q->ambient != CAP_MASK_UNSET;
|
||||
return capability_is_set(q->effective) ||
|
||||
capability_is_set(q->bounding) ||
|
||||
capability_is_set(q->inheritable) ||
|
||||
capability_is_set(q->permitted) ||
|
||||
capability_is_set(q->ambient);
|
||||
}
|
||||
|
||||
/* Mangles the specified caps quintet taking the current bounding set into account:
|
||||
@ -84,3 +89,5 @@ bool capability_quintet_mangle(CapabilityQuintet *q);
|
||||
int capability_quintet_enforce(const CapabilityQuintet *q);
|
||||
|
||||
int capability_get_ambient(uint64_t *ret);
|
||||
|
||||
int pidref_get_capability(const PidRef *pidref, CapabilityQuintet *ret);
|
||||
|
@ -500,22 +500,6 @@ int pidref_is_kernel_thread(const PidRef *pid) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_process_capeff(pid_t pid, char **ret) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(pid >= 0);
|
||||
assert(ret);
|
||||
|
||||
p = procfs_file_alloca(pid, "status");
|
||||
|
||||
r = get_proc_field(p, "CapEff", WHITESPACE, ret);
|
||||
if (r == -ENOENT)
|
||||
return -ESRCH;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int get_process_link_contents(pid_t pid, const char *proc_file, char **ret) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
@ -50,7 +50,6 @@ int get_process_exe(pid_t pid, char **ret);
|
||||
int pid_get_uid(pid_t pid, uid_t *ret);
|
||||
int pidref_get_uid(const PidRef *pid, uid_t *ret);
|
||||
int get_process_gid(pid_t pid, gid_t *ret);
|
||||
int get_process_capeff(pid_t pid, char **ret);
|
||||
int get_process_cwd(pid_t pid, char **ret);
|
||||
int get_process_root(pid_t pid, char **ret);
|
||||
int get_process_environ(pid_t pid, char **ret);
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bitfield.h"
|
||||
#include "creds-util.h"
|
||||
#include "dropin.h"
|
||||
#include "errno-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "generator.h"
|
||||
@ -27,6 +29,7 @@ static char **arg_wants = NULL;
|
||||
static bool arg_debug_shell = false;
|
||||
static char *arg_debug_tty = NULL;
|
||||
static char *arg_default_debug_tty = NULL;
|
||||
static uint32_t arg_breakpoints = 0;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_default_unit, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_mask, strv_freep);
|
||||
@ -34,6 +37,91 @@ STATIC_DESTRUCTOR_REGISTER(arg_wants, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_debug_tty, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_default_debug_tty, freep);
|
||||
|
||||
typedef enum BreakpointType {
|
||||
BREAKPOINT_PRE_UDEV,
|
||||
BREAKPOINT_PRE_BASIC,
|
||||
BREAKPOINT_PRE_SYSROOT_MOUNT,
|
||||
BREAKPOINT_PRE_SWITCH_ROOT,
|
||||
_BREAKPOINT_TYPE_MAX,
|
||||
_BREAKPOINT_TYPE_INVALID = -EINVAL,
|
||||
} BreakpointType;
|
||||
|
||||
typedef enum BreakpointValidity {
|
||||
BREAKPOINT_DEFAULT = 1 << 0,
|
||||
BREAKPOINT_IN_INITRD = 1 << 1,
|
||||
BREAKPOINT_ON_HOST = 1 << 2,
|
||||
} BreakpointValidity;
|
||||
|
||||
typedef struct BreakpointInfo {
|
||||
BreakpointType type;
|
||||
const char *name;
|
||||
const char *unit;
|
||||
BreakpointValidity validity;
|
||||
} BreakpointInfo;
|
||||
|
||||
static const struct BreakpointInfo breakpoint_info_table[_BREAKPOINT_TYPE_MAX] = {
|
||||
{ BREAKPOINT_PRE_UDEV, "pre-udev", "breakpoint-pre-udev.service", BREAKPOINT_IN_INITRD | BREAKPOINT_ON_HOST },
|
||||
{ BREAKPOINT_PRE_BASIC, "pre-basic", "breakpoint-pre-basic.service", BREAKPOINT_IN_INITRD | BREAKPOINT_ON_HOST },
|
||||
{ BREAKPOINT_PRE_SYSROOT_MOUNT, "pre-mount", "breakpoint-pre-mount.service", BREAKPOINT_IN_INITRD },
|
||||
{ BREAKPOINT_PRE_SWITCH_ROOT, "pre-switch-root", "breakpoint-pre-switch-root.service", BREAKPOINT_IN_INITRD | BREAKPOINT_DEFAULT },
|
||||
};
|
||||
|
||||
static BreakpointType parse_breakpoint_from_string_one(const char *s) {
|
||||
assert(s);
|
||||
|
||||
FOREACH_ARRAY(i, breakpoint_info_table, ELEMENTSOF(breakpoint_info_table))
|
||||
if (streq(i->name, s))
|
||||
return i->type;
|
||||
|
||||
return _BREAKPOINT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static int parse_breakpoint_from_string(const char *s, uint32_t *ret_breakpoints) {
|
||||
uint32_t breakpoints = 0;
|
||||
int r;
|
||||
|
||||
assert(ret_breakpoints);
|
||||
|
||||
/* Empty value? set default breakpoint */
|
||||
if (isempty(s)) {
|
||||
if (in_initrd()) {
|
||||
FOREACH_ARRAY(i, breakpoint_info_table, ELEMENTSOF(breakpoint_info_table))
|
||||
if (i->validity & BREAKPOINT_DEFAULT) {
|
||||
breakpoints |= 1 << i->type;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
log_warning("No default breakpoint defined on the host, ignoring breakpoint request from kernel command line.");
|
||||
} else
|
||||
for (;;) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
BreakpointType tt;
|
||||
|
||||
r = extract_first_word(&s, &t, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
tt = parse_breakpoint_from_string_one(t);
|
||||
if (tt < 0) {
|
||||
log_warning("Invalid breakpoint value '%s', ignoring.", t);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_initrd() && !FLAGS_SET(breakpoint_info_table[tt].validity, BREAKPOINT_IN_INITRD))
|
||||
log_warning("Breakpoint '%s' not valid in the initrd, ignoring.", t);
|
||||
else if (!in_initrd() && !FLAGS_SET(breakpoint_info_table[tt].validity, BREAKPOINT_ON_HOST))
|
||||
log_warning("Breakpoint '%s' not valid on the host, ignoring.", t);
|
||||
else
|
||||
breakpoints |= 1 << tt;
|
||||
}
|
||||
|
||||
*ret_breakpoints = breakpoints;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
int r;
|
||||
|
||||
@ -88,6 +176,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
|
||||
return free_and_strdup_warn(&arg_default_unit, value);
|
||||
|
||||
} else if (streq(key, "systemd.break")) {
|
||||
uint32_t breakpoints = 0;
|
||||
|
||||
r = parse_breakpoint_from_string(value, &breakpoints);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to parse breakpoint value '%s': %m", value);
|
||||
|
||||
arg_breakpoints |= breakpoints;
|
||||
|
||||
} else if (!value) {
|
||||
const char *target;
|
||||
|
||||
@ -269,6 +366,10 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
|
||||
RET_GATHER(r, install_debug_shell_dropin());
|
||||
}
|
||||
|
||||
BIT_FOREACH(i, arg_breakpoints)
|
||||
if (strv_extend(&arg_wants, breakpoint_info_table[i].unit) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (get_credentials_dir(&credentials_dir) >= 0)
|
||||
RET_GATHER(r, process_unit_credentials(credentials_dir));
|
||||
|
||||
|
@ -61,7 +61,7 @@ static void get_chid(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIE
|
||||
ret_chid->Data4[0] = (ret_chid->Data4[0] & UINT8_C(0x3f)) | UINT8_C(0x80);
|
||||
}
|
||||
|
||||
static const uint32_t chid_smbios_table[CHID_TYPES_MAX] = {
|
||||
const uint32_t chid_smbios_table[CHID_TYPES_MAX] = {
|
||||
[3] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
|
||||
(UINT32_C(1) << CHID_SMBIOS_FAMILY) |
|
||||
(UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) |
|
||||
|
@ -23,5 +23,7 @@ typedef enum ChidSmbiosFields {
|
||||
_CHID_SMBIOS_FIELDS_MAX,
|
||||
} ChidSmbiosFields;
|
||||
|
||||
extern const uint32_t chid_smbios_table[CHID_TYPES_MAX];
|
||||
|
||||
/* CHID (also called HWID by fwupd) is described at https://github.com/fwupd/fwupd/blob/main/docs/hwids.md */
|
||||
void chid_calculate(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], EFI_GUID ret_chids[static CHID_TYPES_MAX]);
|
||||
|
@ -132,6 +132,7 @@ static int client_context_new(Server *s, pid_t pid, ClientContext **ret) {
|
||||
.log_level_max = -1,
|
||||
.log_ratelimit_interval = s->ratelimit_interval,
|
||||
.log_ratelimit_burst = s->ratelimit_burst,
|
||||
.capability_quintet = CAPABILITY_QUINTET_NULL,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&s->client_contexts, NULL, PID_TO_PTR(pid), c);
|
||||
@ -154,7 +155,6 @@ static void client_context_reset(Server *s, ClientContext *c) {
|
||||
c->comm = mfree(c->comm);
|
||||
c->exe = mfree(c->exe);
|
||||
c->cmdline = mfree(c->cmdline);
|
||||
c->capeff = mfree(c->capeff);
|
||||
|
||||
c->auditid = AUDIT_SESSION_INVALID;
|
||||
c->loginuid = UID_INVALID;
|
||||
@ -184,6 +184,8 @@ static void client_context_reset(Server *s, ClientContext *c) {
|
||||
|
||||
c->log_filter_allowed_patterns = set_free_free(c->log_filter_allowed_patterns);
|
||||
c->log_filter_denied_patterns = set_free_free(c->log_filter_denied_patterns);
|
||||
|
||||
c->capability_quintet = CAPABILITY_QUINTET_NULL;
|
||||
}
|
||||
|
||||
static ClientContext* client_context_free(Server *s, ClientContext *c) {
|
||||
@ -233,8 +235,7 @@ static void client_context_read_basic(ClientContext *c) {
|
||||
if (pid_get_cmdline(c->pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &t) >= 0)
|
||||
free_and_replace(c->cmdline, t);
|
||||
|
||||
if (get_process_capeff(c->pid, &t) >= 0)
|
||||
free_and_replace(c->capeff, t);
|
||||
(void) pidref_get_capability(&PIDREF_MAKE_FROM_PID(c->pid), &c->capability_quintet);
|
||||
}
|
||||
|
||||
static int client_context_read_label(
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "set.h"
|
||||
#include "time-util.h"
|
||||
|
||||
@ -27,7 +28,7 @@ struct ClientContext {
|
||||
char *comm;
|
||||
char *exe;
|
||||
char *cmdline;
|
||||
char *capeff;
|
||||
CapabilityQuintet capability_quintet;
|
||||
|
||||
uint32_t auditid;
|
||||
uid_t loginuid;
|
||||
|
@ -1109,7 +1109,7 @@ static void server_dispatch_message_real(
|
||||
* Let's use a heap allocation for this one. */
|
||||
cmdline1 = set_iovec_string_field(iovec, &n, "_CMDLINE=", c->cmdline);
|
||||
|
||||
IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE"); /* Read from /proc/.../status */
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->capability_quintet.effective, uint64_t, capability_is_set, "%" PRIx64, "_CAP_EFFECTIVE");
|
||||
IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT");
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION");
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID");
|
||||
@ -1144,7 +1144,7 @@ static void server_dispatch_message_real(
|
||||
if (o->cmdline)
|
||||
cmdline2 = set_iovec_string_field(iovec, &n, "OBJECT_CMDLINE=", o->cmdline);
|
||||
|
||||
IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE");
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->capability_quintet.effective, uint64_t, capability_is_set, "%" PRIx64, "OBJECT_CAP_EFFECTIVE");
|
||||
IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT");
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION");
|
||||
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID");
|
||||
|
@ -475,7 +475,8 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings) {
|
||||
if (!full)
|
||||
return log_oom();
|
||||
|
||||
(void) mkdir(full, 0755);
|
||||
if (mkdir(full, 0755) < 0 && errno != EEXIST)
|
||||
return log_error_errno(errno, "Failed to create directory '%s': %m", full);
|
||||
|
||||
if (FLAGS_SET(mount_settings, MOUNT_APPLY_APIVFS_RO))
|
||||
extra_flags |= MS_RDONLY;
|
||||
@ -1405,9 +1406,11 @@ done:
|
||||
#define NSPAWN_PRIVATE_FULLY_VISIBLE_PROCFS "/run/host/proc"
|
||||
#define NSPAWN_PRIVATE_FULLY_VISIBLE_SYSFS "/run/host/sys"
|
||||
|
||||
int pin_fully_visible_fs(void) {
|
||||
int pin_fully_visible_api_fs(void) {
|
||||
int r;
|
||||
|
||||
log_debug("Pinning fully visible API FS");
|
||||
|
||||
(void) mkdir_p(NSPAWN_PRIVATE_FULLY_VISIBLE_PROCFS, 0755);
|
||||
(void) mkdir_p(NSPAWN_PRIVATE_FULLY_VISIBLE_SYSFS, 0755);
|
||||
|
||||
@ -1422,7 +1425,7 @@ int pin_fully_visible_fs(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_wipe_fully_visible_fs(void) {
|
||||
static int do_wipe_fully_visible_api_fs(void) {
|
||||
if (umount2(NSPAWN_PRIVATE_FULLY_VISIBLE_PROCFS, MNT_DETACH) < 0)
|
||||
return log_error_errno(errno, "Failed to unmount temporary proc: %m");
|
||||
|
||||
@ -1438,10 +1441,12 @@ static int do_wipe_fully_visible_fs(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wipe_fully_visible_fs(int mntns_fd) {
|
||||
int wipe_fully_visible_api_fs(int mntns_fd) {
|
||||
_cleanup_close_ int orig_mntns_fd = -EBADF;
|
||||
int r, rr;
|
||||
|
||||
log_debug("Wiping fully visible API FS");
|
||||
|
||||
r = namespace_open(0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
&orig_mntns_fd,
|
||||
@ -1459,7 +1464,7 @@ int wipe_fully_visible_fs(int mntns_fd) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enter mount namespace: %m");
|
||||
|
||||
rr = do_wipe_fully_visible_fs();
|
||||
rr = do_wipe_fully_visible_api_fs();
|
||||
|
||||
r = namespace_enter(/* pidns_fd = */ -EBADF,
|
||||
orig_mntns_fd,
|
||||
|
@ -73,5 +73,6 @@ int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s
|
||||
int setup_pivot_root(const char *directory, const char *pivot_root_new, const char *pivot_root_old);
|
||||
|
||||
int tmpfs_patch_options(const char *options,uid_t uid_shift, const char *selinux_apifs_context, char **ret);
|
||||
int pin_fully_visible_fs(void);
|
||||
int wipe_fully_visible_fs(int mntns_fd);
|
||||
|
||||
int pin_fully_visible_api_fs(void);
|
||||
int wipe_fully_visible_api_fs(int mntns_fd);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "copy.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "dev-setup.h"
|
||||
#include "devnum-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "dissect-image.h"
|
||||
#include "env-util.h"
|
||||
@ -1250,7 +1251,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_uid_range = UINT32_C(0x10000);
|
||||
|
||||
} else if (streq(optarg, "identity")) {
|
||||
/* identity: User namespaces on, UID range is map the 0…0xFFFF range to
|
||||
/* identity: User namespaces on, UID range is map of the 0…0xFFFF range to
|
||||
* itself, i.e. we don't actually map anything, but do take benefit of
|
||||
* isolation of capability sets. */
|
||||
arg_userns_mode = USER_NAMESPACE_FIXED;
|
||||
@ -2323,7 +2324,7 @@ static int copy_devnode_one(const char *dest, const char *node, bool ignore_mkno
|
||||
return log_error_errno(r, "Failed to create '%s': %m", dn);
|
||||
|
||||
_cleanup_free_ char *sl = NULL;
|
||||
if (asprintf(&sl, "%s/%u:%u", dn, major(st.st_rdev), minor(st.st_rdev)) < 0)
|
||||
if (asprintf(&sl, "%s/" DEVNUM_FORMAT_STR, dn, DEVNUM_FORMAT_VAL(st.st_rdev)) < 0)
|
||||
return log_oom();
|
||||
|
||||
_cleanup_free_ char *prefixed = path_join(dest, sl);
|
||||
@ -2847,7 +2848,7 @@ static int reset_audit_loginuid(void) {
|
||||
if (!arg_privileged)
|
||||
return 0;
|
||||
|
||||
r = read_one_line_file("/proc/self/loginuid", &p);
|
||||
r = read_virtual_file("/proc/self/loginuid", SIZE_MAX, &p, /* ret_size= */ NULL);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@ -3254,6 +3255,7 @@ static int chase_and_update(char **p, unsigned flags) {
|
||||
}
|
||||
|
||||
static int determine_uid_shift(const char *directory) {
|
||||
assert(directory);
|
||||
|
||||
if (arg_userns_mode == USER_NAMESPACE_NO) {
|
||||
arg_uid_shift = 0;
|
||||
@ -3932,7 +3934,7 @@ static int outer_child(
|
||||
|
||||
_cleanup_(bind_user_context_freep) BindUserContext *bind_user_context = NULL;
|
||||
_cleanup_strv_free_ char **os_release_pairs = NULL;
|
||||
_cleanup_close_ int fd = -EBADF, mntns_fd = -EBADF;
|
||||
_cleanup_close_ int mntns_fd = -EBADF;
|
||||
bool idmap = false, enable_fuse;
|
||||
const char *p;
|
||||
pid_t pid;
|
||||
@ -4325,6 +4327,7 @@ static int outer_child(
|
||||
* visible. Hence there we do it the other way round: we first allocate a new set of namespaces
|
||||
* (and fork for it) for which we then mount sysfs/procfs, and only then switch root. */
|
||||
|
||||
_cleanup_close_ int notify_fd = -EBADF;
|
||||
if (arg_privileged) {
|
||||
/* Mark everything as shared so our mounts get propagated down. This is required to make new
|
||||
* bind mounts available in systemd services inside the container that create a new mount
|
||||
@ -4355,16 +4358,16 @@ static int outer_child(
|
||||
* Note, the inner child wouldn't be able to unmount the instances on its own since
|
||||
* it doesn't own the originating mount namespace. IOW, the outer child needs to do
|
||||
* this. */
|
||||
r = pin_fully_visible_fs();
|
||||
r = pin_fully_visible_api_fs();
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
fd = setup_notify_child(NULL);
|
||||
notify_fd = setup_notify_child(NULL);
|
||||
} else
|
||||
fd = setup_notify_child(directory);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
notify_fd = setup_notify_child(directory);
|
||||
if (notify_fd < 0)
|
||||
return notify_fd;
|
||||
|
||||
pid = raw_clone(SIGCHLD|CLONE_NEWNS|
|
||||
arg_clone_ns_flags |
|
||||
@ -4429,7 +4432,7 @@ static int outer_child(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Short write while sending machine ID.");
|
||||
|
||||
l = send_one_fd(fd_outer_socket, fd, 0);
|
||||
l = send_one_fd(fd_outer_socket, notify_fd, 0);
|
||||
if (l < 0)
|
||||
return log_error_errno(l, "Failed to send notify fd: %m");
|
||||
|
||||
@ -5623,7 +5626,7 @@ static int run_container(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early.");
|
||||
|
||||
if (arg_userns_mode != USER_NAMESPACE_NO) {
|
||||
r = wipe_fully_visible_fs(mntns_fd);
|
||||
r = wipe_fully_visible_api_fs(mntns_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
mntns_fd = safe_close(mntns_fd);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "battery-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "cap-list.h"
|
||||
#include "capability-util.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "compare-operator.h"
|
||||
#include "condition.h"
|
||||
@ -701,45 +702,23 @@ static int condition_test_security(Condition *c, char **env) {
|
||||
}
|
||||
|
||||
static int condition_test_capability(Condition *c, char **env) {
|
||||
unsigned long long capabilities = (unsigned long long) -1;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int value, r;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_CAPABILITY);
|
||||
|
||||
/* If it's an invalid capability, we don't have it */
|
||||
value = capability_from_name(c->parameter);
|
||||
int value = capability_from_name(c->parameter);
|
||||
if (value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* If it's a valid capability we default to assume
|
||||
* that we have it */
|
||||
CapabilityQuintet q;
|
||||
r = pidref_get_capability(&PIDREF_MAKE_FROM_PID(getpid_cached()), &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
f = fopen("/proc/self/status", "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
const char *p = startswith(line, "CapBnd:");
|
||||
if (p) {
|
||||
if (sscanf(p, "%llx", &capabilities) != 1)
|
||||
return -EIO;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !!(capabilities & (1ULL << value));
|
||||
return !!(q.bounding & ((UINT64_C(1) << value)));
|
||||
}
|
||||
|
||||
static int condition_test_needs_update(Condition *c, char **env) {
|
||||
|
@ -536,6 +536,8 @@ int mount_switch_root_full(const char *path, unsigned long mount_propagation_fla
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Successfully switched root to '%s'.", path);
|
||||
|
||||
/* Finally, let's establish the requested propagation flags. */
|
||||
if (mount_propagation_flag == 0)
|
||||
return 0;
|
||||
@ -1319,7 +1321,7 @@ int make_userns(uid_t uid_shift, uid_t uid_range, uid_t source_owner, uid_t dest
|
||||
* process whose only purpose is to give us a new user namespace. It's killed when we got it. */
|
||||
|
||||
if (!userns_shift_range_valid(uid_shift, uid_range))
|
||||
return -EINVAL;
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid UID range for user namespace.");
|
||||
|
||||
if (IN_SET(idmapping, REMOUNT_IDMAPPING_NONE, REMOUNT_IDMAPPING_HOST_ROOT)) {
|
||||
if (asprintf(&line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0u, uid_shift, uid_range) < 0)
|
||||
|
@ -87,6 +87,8 @@ int nsresource_allocate_userns(const char *name, uint64_t size) {
|
||||
SD_JSON_BUILD_PAIR("userNamespaceFileDescriptor", SD_JSON_BUILD_UNSIGNED(userns_fd_idx)));
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to call AllocateUserRange() varlink call: %m");
|
||||
if (streq_ptr(error_id, "io.systemd.NamespaceResource.UserNamespaceInterfaceNotSupported"))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unprivileged user namespace delegation is not supported on this system.");
|
||||
if (error_id)
|
||||
return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to allocate user namespace with %" PRIu64 " users: %s", size, error_id);
|
||||
|
||||
|
@ -840,6 +840,13 @@ static int on_exit_event(sd_event_source *e, void *userdata) {
|
||||
if (drained(f))
|
||||
return pty_forward_done(f, 0);
|
||||
|
||||
if (!f->master_hangup)
|
||||
f->master_writable = f->master_readable = true;
|
||||
if (!f->stdin_hangup)
|
||||
f->stdin_readable = true;
|
||||
if (!f->stdout_hangup)
|
||||
f->stdout_writable = true;
|
||||
|
||||
r = shovel(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -596,7 +596,7 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H
|
||||
!IN_SET(t->target.type, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME)))
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Target type '%s' is incompatible with source type '%s', refusing.",
|
||||
resource_type_to_string(t->source.type), resource_type_to_string(t->target.type));
|
||||
resource_type_to_string(t->target.type), resource_type_to_string(t->source.type));
|
||||
|
||||
if (!t->source.path && !t->source.path_auto)
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
|
@ -305,6 +305,18 @@ static void test_capability_get_ambient(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_pidref_get_capability(void) {
|
||||
CapabilityQuintet q = CAPABILITY_QUINTET_NULL;
|
||||
|
||||
assert_se(pidref_get_capability(&PIDREF_MAKE_FROM_PID(getpid_cached()), &q) >= 0);
|
||||
|
||||
assert_se(q.effective != CAP_MASK_UNSET);
|
||||
assert_se(q.inheritable != CAP_MASK_UNSET);
|
||||
assert_se(q.permitted != CAP_MASK_UNSET);
|
||||
assert_se(q.effective != CAP_MASK_UNSET);
|
||||
assert_se(q.ambient != CAP_MASK_UNSET);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
bool run_ambient;
|
||||
|
||||
@ -336,5 +348,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
test_capability_get_ambient();
|
||||
|
||||
test_pidref_get_capability();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -363,24 +363,6 @@ TEST(status_field) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(capeff) {
|
||||
for (int pid = 0; pid < 2; pid++) {
|
||||
_cleanup_free_ char *capeff = NULL;
|
||||
int r, p;
|
||||
|
||||
r = get_process_capeff(0, &capeff);
|
||||
log_info("capeff: '%s' (r=%d)", capeff, r);
|
||||
|
||||
if (IN_SET(r, -ENOENT, -EPERM))
|
||||
return;
|
||||
|
||||
assert_se(r == 0);
|
||||
assert_se(*capeff);
|
||||
p = capeff[strspn(capeff, HEXDIGITS)];
|
||||
assert_se(!p || isspace(p));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(read_one_line_file) {
|
||||
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-fileio-1lf-XXXXXX";
|
||||
int fd;
|
||||
|
@ -42,11 +42,28 @@ void udev_builtin_exit(void) {
|
||||
(*b)->exit();
|
||||
}
|
||||
|
||||
bool udev_builtin_should_reload(void) {
|
||||
UdevReloadFlags udev_builtin_should_reload(void) {
|
||||
UdevReloadFlags flags = 0;
|
||||
|
||||
for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++)
|
||||
if (builtins[i] && builtins[i]->should_reload && builtins[i]->should_reload())
|
||||
return true;
|
||||
return false;
|
||||
flags |= 1u << i;
|
||||
|
||||
if (flags != 0)
|
||||
flags |= UDEV_RELOAD_KILL_WORKERS;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void udev_builtin_reload(UdevReloadFlags flags) {
|
||||
for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++) {
|
||||
if (!FLAGS_SET(flags, 1u << i) || !builtins[i])
|
||||
continue;
|
||||
if (builtins[i]->exit)
|
||||
builtins[i]->exit();
|
||||
if (builtins[i]->init)
|
||||
builtins[i]->init();
|
||||
}
|
||||
}
|
||||
|
||||
void udev_builtin_list(void) {
|
||||
|
@ -59,7 +59,8 @@ const char* udev_builtin_name(UdevBuiltinCommand cmd);
|
||||
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
|
||||
int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
|
||||
void udev_builtin_list(void);
|
||||
bool udev_builtin_should_reload(void);
|
||||
UdevReloadFlags udev_builtin_should_reload(void);
|
||||
void udev_builtin_reload(UdevReloadFlags flags);
|
||||
int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val);
|
||||
int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) _printf_(3, 4);
|
||||
int udev_builtin_import_property(UdevEvent *event, const char *key);
|
||||
|
@ -339,3 +339,27 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
|
||||
manager_adjust_config(&manager->config);
|
||||
return 1;
|
||||
}
|
||||
|
||||
UdevReloadFlags manager_reload_config(Manager *manager) {
|
||||
assert(manager);
|
||||
|
||||
UdevConfig old = manager->config;
|
||||
|
||||
manager->config_by_udev_conf = UDEV_CONFIG_INIT;
|
||||
manager_parse_udev_config(&manager->config_by_udev_conf);
|
||||
manager_merge_config(manager);
|
||||
log_set_max_level(manager->config.log_level);
|
||||
manager_adjust_config(&manager->config);
|
||||
|
||||
if (manager->config.resolve_name_timing != old.resolve_name_timing)
|
||||
return UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
|
||||
|
||||
if (manager->config.log_level != old.log_level ||
|
||||
manager->config.exec_delay_usec != old.exec_delay_usec ||
|
||||
manager->config.timeout_usec != old.timeout_usec ||
|
||||
manager->config.timeout_signal != old.timeout_signal ||
|
||||
manager->config.blockdev_read_only != old.blockdev_read_only)
|
||||
return UDEV_RELOAD_KILL_WORKERS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,4 +27,5 @@ typedef struct UdevConfig {
|
||||
}
|
||||
|
||||
int manager_load(Manager *manager, int argc, char *argv[]);
|
||||
UdevReloadFlags manager_reload_config(Manager *manager);
|
||||
void udev_config_set_default_children_max(UdevConfig *c);
|
||||
|
@ -55,3 +55,26 @@ typedef enum UdevBuiltinCommand {
|
||||
_UDEV_BUILTIN_MAX,
|
||||
_UDEV_BUILTIN_INVALID = -EINVAL,
|
||||
} UdevBuiltinCommand;
|
||||
|
||||
typedef enum UdevReloadFlags {
|
||||
#if HAVE_BLKID
|
||||
UDEV_RELOAD_BUILTIN_BLKID = 1u << UDEV_BUILTIN_BLKID,
|
||||
#endif
|
||||
UDEV_RELOAD_BUILTIN_BTRFS = 1u << UDEV_BUILTIN_BTRFS,
|
||||
UDEV_RELOAD_BUILTIN_HWDB = 1u << UDEV_BUILTIN_HWDB,
|
||||
UDEV_RELOAD_BUILTIN_INPUT_ID = 1u << UDEV_BUILTIN_INPUT_ID,
|
||||
UDEV_RELOAD_BUILTIN_KEYBOARD = 1u << UDEV_BUILTIN_KEYBOARD,
|
||||
#if HAVE_KMOD
|
||||
UDEV_RELOAD_BUILTIN_KMOD = 1u << UDEV_BUILTIN_KMOD,
|
||||
#endif
|
||||
UDEV_RELOAD_BUILTIN_DRIVER = 1u << UDEV_BUILTIN_NET_DRIVER,
|
||||
UDEV_RELOAD_BUILTIN_NET_ID = 1u << UDEV_BUILTIN_NET_ID,
|
||||
UDEV_RELOAD_BUILTIN_NET_LINK = 1u << UDEV_BUILTIN_NET_LINK,
|
||||
UDEV_RELOAD_BUILTIN_PATH_ID = 1u << UDEV_BUILTIN_PATH_ID,
|
||||
UDEV_RELOAD_BUILTIN_USB_ID = 1u << UDEV_BUILTIN_USB_ID,
|
||||
#if HAVE_ACL
|
||||
UDEV_RELOAD_BUILTIN_UACCESS = 1u << UDEV_BUILTIN_UACCESS,
|
||||
#endif
|
||||
UDEV_RELOAD_KILL_WORKERS = 1u << (_UDEV_BUILTIN_MAX + 0),
|
||||
UDEV_RELOAD_RULES = 1u << (_UDEV_BUILTIN_MAX + 1),
|
||||
} UdevReloadFlags;
|
||||
|
@ -262,22 +262,25 @@ static void manager_reload(Manager *manager, bool force) {
|
||||
/* Reload SELinux label database, to make the child inherit the up-to-date database. */
|
||||
mac_selinux_maybe_reload();
|
||||
|
||||
/* Nothing changed. It is not necessary to reload. */
|
||||
if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) {
|
||||
UdevReloadFlags flags = udev_builtin_should_reload();
|
||||
if (udev_rules_should_reload(manager->rules))
|
||||
flags |= UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
|
||||
if (flags == 0 && !force)
|
||||
/* Neither .rules files nor config files for builtins e.g. .link files changed. It is not
|
||||
* necessary to reload configs. Note, udev.conf is not checked in the above, hence reloaded
|
||||
* when explicitly requested or at least one .rules file or friend is updated. */
|
||||
return;
|
||||
|
||||
if (!force)
|
||||
return;
|
||||
(void) notify_reloading();
|
||||
|
||||
/* If we eat this up, then tell our service manager to just continue */
|
||||
(void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
|
||||
} else {
|
||||
(void) notify_reloading();
|
||||
flags |= manager_reload_config(manager);
|
||||
|
||||
if (FLAGS_SET(flags, UDEV_RELOAD_KILL_WORKERS))
|
||||
manager_kill_workers(manager, false);
|
||||
|
||||
udev_builtin_exit();
|
||||
udev_builtin_init();
|
||||
udev_builtin_reload(flags);
|
||||
|
||||
if (FLAGS_SET(flags, UDEV_RELOAD_RULES)) {
|
||||
r = udev_rules_load(&rules, manager->config.resolve_name_timing);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
|
||||
|
@ -42,6 +42,8 @@ create_dummy_container /var/lib/machines/long-running
|
||||
cat >/var/lib/machines/long-running/sbin/init <<\EOF
|
||||
#!/usr/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
PID=0
|
||||
|
||||
trap 'touch /terminate; kill 0' RTMIN+3
|
||||
@ -310,6 +312,10 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Unreg
|
||||
# test io.systemd.Machine.List with addresses, OSRelease, and UIDShift fields
|
||||
create_dummy_container "/var/lib/machines/container-without-os-release"
|
||||
cat >>/var/lib/machines/container-without-os-release/sbin/init <<\EOF
|
||||
#!/usr/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
ip link add hoge type dummy
|
||||
ip link set hoge up
|
||||
ip address add 192.0.2.1/24 dev hoge
|
||||
|
@ -27,7 +27,7 @@ event_timeout=10
|
||||
timeout_signal=SIGABRT
|
||||
EOF
|
||||
|
||||
systemctl restart systemd-udevd.service
|
||||
systemctl reload systemd-udevd.service
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
@ -40,7 +40,7 @@ teardown() {
|
||||
|
||||
rm -rf "$TMPDIR"
|
||||
rm -f "$TEST_RULE" "$TEST_CONF"
|
||||
systemctl restart systemd-udevd.service
|
||||
systemctl reload systemd-udevd.service
|
||||
}
|
||||
|
||||
run_test_timeout() {
|
||||
|
@ -18,7 +18,7 @@ at_exit() {
|
||||
# Forcibly kills sleep command invoked by the udev rule before restarting,
|
||||
# otherwise systemctl restart below will takes longer.
|
||||
killall -KILL sleep
|
||||
systemctl restart systemd-udevd.service
|
||||
udevadm control --reload
|
||||
ip link del "$IFNAME"
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ cat >/run/udev/rules.d/99-testsuite.rules <<EOF
|
||||
SUBSYSTEM=="net", ACTION=="change", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000"
|
||||
EOF
|
||||
|
||||
systemctl restart systemd-udevd.service
|
||||
udevadm control --reload
|
||||
|
||||
ip link add "$IFNAME" type dummy
|
||||
IFINDEX=$(ip -json link show "$IFNAME" | jq '.[].ifindex')
|
||||
|
@ -990,6 +990,11 @@ systemd-analyze architectures uname
|
||||
systemd-analyze smbios11
|
||||
systemd-analyze smbios11 -q
|
||||
|
||||
if test -f /sys/class/dmi/id/board_vendor && ! systemd-detect-virt --container ; then
|
||||
systemd-analyze chid
|
||||
systemd-analyze chid --json=pretty
|
||||
fi
|
||||
|
||||
systemd-analyze condition --instance=tmp --unit=systemd-growfs@.service
|
||||
systemd-analyze verify --instance=tmp --man=no systemd-growfs@.service
|
||||
systemd-analyze security --instance=tmp systemd-growfs@.service
|
||||
|
@ -69,6 +69,51 @@ SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/default.target.wants/debug-shell.service" /lib/systemd/system/debug-shell.service
|
||||
grep -F "/dev/tty666" "$OUT_DIR/early/debug-shell.service.d/50-tty.conf"
|
||||
|
||||
# systemd.break (default)
|
||||
: "debug-shell: regular + systemd.break"
|
||||
CMDLINE="$CMDLINE systemd.break"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
|
||||
|
||||
# systemd.break=pre-switch-root
|
||||
: "debug-shell: regular + systemd.break=pre-switch-root"
|
||||
CMDLINE="$CMDLINE systemd.break=pre-switch-root"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
|
||||
|
||||
# systemd.break=pre-mount
|
||||
: "debug-shell: regular + systemd.break=pre-mount"
|
||||
CMDLINE="$CMDLINE systemd.break=pre-mount"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
|
||||
test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
|
||||
|
||||
# systemd.break=pre-basic
|
||||
: "debug-shell: regular + systemd.break=pre-basic"
|
||||
CMDLINE="$CMDLINE systemd.break=pre-basic"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
|
||||
|
||||
# systemd.break=pre-udev
|
||||
: "debug-shell: regular + systemd.break=pre-udev"
|
||||
CMDLINE="$CMDLINE systemd.break=pre-udev"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
|
||||
|
||||
# systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root
|
||||
: "debug-shell: regular + systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
|
||||
rm -f "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
|
||||
rm -f "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service"
|
||||
CMDLINE="$CMDLINE systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
|
||||
SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
|
||||
link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
|
||||
|
||||
# Now override the default target via systemd.unit=
|
||||
: "debug-shell: regular + systemd.unit="
|
||||
CMDLINE="$CMDLINE systemd.unit=my-fancy.target"
|
||||
@ -103,6 +148,50 @@ CMDLINE="$CMDLINE rd.systemd.debug_shell"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/debug-shell.service" /lib/systemd/system/debug-shell.service
|
||||
|
||||
# rd.systemd.break (default)
|
||||
: "debug-shell: initrd + rd.systemd.break"
|
||||
CMDLINE="$CMDLINE rd.systemd.break"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
|
||||
|
||||
# rd.systemd.break=pre-udev
|
||||
: "debug-shell: initrd + rd.systemd.break=pre-udev"
|
||||
CMDLINE="$CMDLINE rd.systemd.break=pre-udev"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
|
||||
|
||||
# rd.systemd.break=pre-basic
|
||||
: "debug-shell: initrd + rd.systemd.break=pre-basic"
|
||||
CMDLINE="$CMDLINE rd.systemd.break=pre-basic"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
|
||||
|
||||
# rd.systemd.break=pre-mount
|
||||
: "debug-shell: initrd + rd.systemd.break=pre-mount"
|
||||
CMDLINE="$CMDLINE rd.systemd.break=pre-mount"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service" /lib/systemd/system/breakpoint-pre-mount.service
|
||||
|
||||
# rd.systemd.break=pre-switch-root
|
||||
: "debug-shell: initrd + rd.systemd.break=pre-switch-root"
|
||||
rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service"
|
||||
CMDLINE="$CMDLINE rd.systemd.break=pre-switch-root"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
|
||||
|
||||
# rd.systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root
|
||||
: "debug-shell: initrd + rd.systemd.break=pre-udev,pre-mount,pre-switch-root"
|
||||
rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service"
|
||||
rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service"
|
||||
rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service"
|
||||
rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service"
|
||||
CMDLINE="$CMDLINE rd.systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
|
||||
SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service" /lib/systemd/system/breakpoint-pre-mount.service
|
||||
link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
|
||||
|
||||
# Override the default target
|
||||
: "debug-shell: initrd + rd.systemd.unit"
|
||||
CMDLINE="$CMDLINE rd.systemd.unit=my-fancy-initrd.target"
|
||||
|
35
units/breakpoint-pre-basic.service.in
Normal file
35
units/breakpoint-pre-basic.service.in
Normal file
@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Breakpoint Before Basic System
|
||||
Documentation=man:systemd-debug-generator(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target emergency.target
|
||||
After=sysinit.target sockets.target paths.target slices.target tmp.mount systemd-vconsole-setup.service
|
||||
Before=basic.target
|
||||
|
||||
[Service]
|
||||
Environment=SHELL_PROMPT_PREFIX="pre-basic "
|
||||
Type=oneshot
|
||||
ExecStartPre=-plymouth --wait quit
|
||||
# Execute shell with "-" prefix to not consider the unit failed if it exits with
|
||||
# a non-zero value
|
||||
ExecStart=-{{SUSHELL}}
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
# bash ignores SIGTERM
|
||||
KillSignal=SIGHUP
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
|
36
units/breakpoint-pre-mount.service.in
Normal file
36
units/breakpoint-pre-mount.service.in
Normal file
@ -0,0 +1,36 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Breakpoint Before Mounting the Root Filesystem on /sysroot
|
||||
Documentation=man:systemd-debug-generator(8)
|
||||
AssertPathExists=/etc/initrd-release
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target emergency.target
|
||||
After=basic.target systemd-vconsole-setup.service
|
||||
Before=initrd-root-fs.target sysroot.mount systemd-fsck-root.service
|
||||
|
||||
[Service]
|
||||
Environment=SHELL_PROMPT_PREFIX="pre-mount "
|
||||
Type=oneshot
|
||||
ExecStartPre=-plymouth --wait quit
|
||||
# Execute shell with "-" prefix to not consider the unit failed if it exits with
|
||||
# a non-zero value
|
||||
ExecStart=-{{SUSHELL}}
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
# bash ignores SIGTERM
|
||||
KillSignal=SIGHUP
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
|
37
units/breakpoint-pre-switch-root.service.in
Normal file
37
units/breakpoint-pre-switch-root.service.in
Normal file
@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Breakpoint Before Switching Root
|
||||
Documentation=man:systemd-debug-generator(8)
|
||||
AssertPathExists=/etc/initrd-release
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target emergency.target
|
||||
Wants=remote-fs.target
|
||||
After=initrd.target initrd-parse-etc.service sysroot.mount remote-fs.target systemd-vconsole-setup.service
|
||||
Before=initrd-cleanup.service
|
||||
|
||||
[Service]
|
||||
Environment=SHELL_PROMPT_PREFIX="pre-switch-root "
|
||||
Type=oneshot
|
||||
ExecStartPre=-plymouth --wait quit
|
||||
# Execute shell with "-" prefix to not consider the unit failed if it exits with
|
||||
# a non-zero value
|
||||
ExecStart=-{{SUSHELL}}
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
# bash ignores SIGTERM
|
||||
KillSignal=SIGHUP
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
|
36
units/breakpoint-pre-udev.service.in
Normal file
36
units/breakpoint-pre-udev.service.in
Normal file
@ -0,0 +1,36 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Breakpoint Before Starting to Process Kernel uevents
|
||||
Documentation=man:systemd-debug-generator(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target emergency.target
|
||||
Wants=systemd-journald.socket
|
||||
After=systemd-journald.socket systemd-vconsole-setup.service
|
||||
Before=systemd-udevd.service systemd-udev-trigger.service
|
||||
|
||||
[Service]
|
||||
Environment=SHELL_PROMPT_PREFIX="pre-udev "
|
||||
Type=oneshot
|
||||
ExecStartPre=-plymouth --wait quit
|
||||
# Execute shell with "-" prefix to not consider the unit failed if it exits with
|
||||
# a non-zero value
|
||||
ExecStart=-{{SUSHELL}}
|
||||
StandardInput=tty-force
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
# bash ignores SIGTERM
|
||||
KillSignal=SIGHUP
|
||||
|
||||
# Unset locale for the console getty since the console has problems
|
||||
# displaying some internationalized messages.
|
||||
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
|
@ -7,6 +7,10 @@ units = [
|
||||
{ 'file' : 'blockdev@.target' },
|
||||
{ 'file' : 'bluetooth.target' },
|
||||
{ 'file' : 'boot-complete.target' },
|
||||
{ 'file' : 'breakpoint-pre-basic.service.in' },
|
||||
{ 'file' : 'breakpoint-pre-mount.service.in' },
|
||||
{ 'file' : 'breakpoint-pre-switch-root.service.in' },
|
||||
{ 'file' : 'breakpoint-pre-udev.service.in' },
|
||||
{ 'file' : 'capsule@.service.in' },
|
||||
{ 'file' : 'capsule.slice' },
|
||||
{ 'file' : 'console-getty.service.in' },
|
||||
|
Loading…
x
Reference in New Issue
Block a user