1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-10 16:58:28 +03:00

Compare commits

...

31 Commits

Author SHA1 Message Date
Antonio Alvarez Feijoo
e9f781a5a4
debug-generator: add a kernel cmdline option to pause the boot process
Introduce the `systemd.break=` kernel command line option to allow stopping the
boot process at a certain point and spawn a debug shell. After exiting this
shell, the system will resume booting.

It accepts the following values:
- `pre-udev`: before starting to process kernel uevents (initrd and host).
- `pre-basic`: before leaving early boot and regular services start (initrd and
host).
- `pre-mount`: before the root filesystem is mounted (initrd).
- `pre-switch-root`: before switching root (initrd).
2024-12-20 08:51:23 +01:00
Antonio Alvarez Feijoo
cb3801a4c9
man/debug-generator: add a section for kernel command line options 2024-12-20 08:48:23 +01:00
Yu Watanabe
8a135111ca
capability-util: generalize helper to acquire local caps (#35403)
This generalizes and modernizes the code to acquire set of local caps,
based on the code for this in the condition logic. Uses PidRef, and
acquires the full quintuplet of caps.

This can be considered preparation to one day maybe build without
libcap.
2024-12-20 11:52:24 +09:00
Yu Watanabe
5e837858e7
analyze: add "chid" verb to display CHIDs of the local system (#35175)
We already have the code for it, expose it in systemd-analyze, because
it's useful.
2024-12-20 11:47:03 +09:00
Yu Watanabe
a3fecea5e2
Small fixes to nspawn and other stuff (#35686)
Split out ouf #35685.
2024-12-20 11:03:59 +09:00
Yu Watanabe
3b9010b170
udev: support reloading udev.conf (#35458)
This makes systemd-udevd reload udev.conf when explicitly requested by
e.g. `udevadm control --reload`.
2024-12-20 09:00:48 +09:00
Yu Watanabe
cf89e48028 ptyfwd: reset writable/readable flag before shovel() on exit
Follow-up for 12807b5a49d1fe60434d473afe11ff81a4c92306.

Otherwise, if a call of shovel() disabled the flags, the subsequent
calls do nothing even if there is something we need to read or write.

Fixes the following error:
```
Dec 19 02:19:39 run0[5618]: Error on PTY forwarding logic: Too many levels of symbolic links
```
2024-12-20 08:59:41 +09:00
Ivan Kruglov
3cbf00a30c machine: make TEST-13-NSPAWN wqlong-running code more verbose
Need this to debug https://github.com/systemd/systemd/issues/35115
2024-12-19 17:09:04 +00:00
Luca Boccassi
0f67cb3606
Minor fixes in man pages, example scripts, error log (#35683)
No functional changes.
2024-12-19 17:08:13 +00:00
Lennart Poettering
5ceb38cb1e nspawn: switch to read_virtual_file() for reading audit loginuid 2024-12-19 15:37:00 +01:00
Lennart Poettering
312cf91005 nsresource: print nicer error message when trying to acquire an unpriv user ns range where this isn't possible 2024-12-19 15:35:23 +01:00
Lennart Poettering
b1b128d0e2 mount-util: add debug message to make_userns() failure 2024-12-19 15:33:52 +01:00
Lennart Poettering
91cdc8ab0f mount-util: add debug output when we switched root 2024-12-19 15:33:44 +01:00
Lennart Poettering
009a02b263 nspawn: trivial improvements 2024-12-19 15:33:34 +01:00
Lennart Poettering
b83358b87f nspawn: rename pin_fully_visible_fs() → pin_fully_visible_api_fs()
This function pins the *API* FS, i.e. /proc/ + /sys/, not just any fs.
Hence clarify this in the name.

(At least we call these two fs "API (V)FS" in our codebase, hence
continue to do so here)
2024-12-19 15:33:24 +01:00
Lennart Poettering
bf1ef54d30 nspawn: add some additional useful debug logging 2024-12-19 15:33:10 +01:00
Lennart Poettering
8f9ea89ce4 nspawn: make unexpected mkdir() failures fatal
THis is just to make things easier to debug.
2024-12-19 15:33:06 +01:00
Lennart Poettering
5229cd839a nspawn: rename 'fd' variable to something more descriptive 2024-12-19 15:32:50 +01:00
Lennart Poettering
595ca10f37 nspawn: use DEVNUM_FORMAT_STR/DEVNUM_FORMAT_VAL more 2024-12-19 15:32:05 +01:00
Matthias Lisin
6e3f32cc56
man/sysupdate.features: fix typos 2024-12-19 12:39:32 +01:00
Matthias Lisin
1462736c7e
sysupdate: fix args order of formatted error 2024-12-19 12:39:31 +01:00
Matthias Lisin
f441831c9e
man/sysupdate.d: fix wrong PathRelativeTo value 2024-12-19 12:39:31 +01:00
Matthias Lisin
4bc06da775
man: fix args order for udevadm info cmd 2024-12-19 12:39:31 +01:00
Yu Watanabe
ced0ef3b35 TEST-17: use 'udevadm control --reload' or 'systemctl reload systemd-udevd.service' for reloading udev.conf
These should be equivalent. For coverage, one subtest uses systemctl and
another uses udevadm.
2024-12-19 19:00:38 +09:00
Yu Watanabe
e95861d909 udev: also reload udev.conf when explicitly requested
When reloading is explicitly requested, e.g. by 'udevadm control --reload',
then also reload udev.conf.
2024-12-19 18:57:32 +09:00
Yu Watanabe
0f72af536f udev: reload .rules files and builtins only when necessary
Previously, even if e.g. .rules files are unchanged, all .rules files
are reloaded when other kind of config files like .link files or
.hwdb.bin are changed, vice versa.
2024-12-19 18:55:18 +09:00
Lennart Poettering
0e5a83f510 analyze: drop conditioning of --no-legend and --json= on specific verbs
First of all, the list of verbs was badly out of date, in particular for
--no-legend. But second if it, I think such minor switches that alter
some detail of the output should not result in failure when the specific
tweak does not apply on some command. It should be fine for scripts and
suchlike to dumbly always pass --no-legend to all invocations of our
tools without having to consider if a specific subtool of ours actually
supports it or not.
2024-12-18 17:39:22 +01:00
Lennart Poettering
8f114904fc analyze: add verb for showing system's CHIDs
We have the code already, expose it in systemd-analyze too.

This should make it easier to debug the CHID use in the UKIs with
onboard tooling.
2024-12-18 17:38:42 +01:00
Lennart Poettering
25b1a73f71 journald: get rid of get_process_capeff(), use pidref_get_capability() instead
This does pretty much the same, but is nicer, since it parses things
properly.
2024-12-17 19:06:54 +01:00
Lennart Poettering
a5370d35d6 capability-util: introduce capability_is_set() helper 2024-12-17 19:06:54 +01:00
Lennart Poettering
1184626a26 capability-util: generalize helper to acquire local caps
This generalizes and modernizes the code to acquire set of local caps,
based on the code for this in the condition logic. Uses PidRef, and
acquires the full quintuplet of caps.

This can be considered preparation to one day maybe build without
libcap.
2024-12-17 19:06:54 +01:00
50 changed files with 1012 additions and 167 deletions

2
TODO
View File

@ -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,

View File

@ -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'

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>,

View File

@ -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]

View File

@ -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'

View File

@ -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'

View File

@ -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
View 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;
}

View File

@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int verb_chid(int argc, char *argv[], void *userdata);

View File

@ -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 },
{}
};

View File

@ -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',

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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) |

View File

@ -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]);

View File

@ -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(

View File

@ -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;

View File

@ -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");

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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),

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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() {

View File

@ -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')

View File

@ -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

View File

@ -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"

View 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

View 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

View 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

View 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

View File

@ -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' },