mirror of
https://github.com/systemd/systemd.git
synced 2025-03-10 16:58:28 +03:00
Compare commits
170 Commits
2fc6ae50fc
...
aac0db6cd9
Author | SHA1 | Date | |
---|---|---|---|
|
aac0db6cd9 | ||
|
06ffa66a5b | ||
|
33bfa69b2e | ||
|
f108996319 | ||
|
dec47e58a6 | ||
|
cdcb1eeeb8 | ||
|
77d4a263c1 | ||
|
5f29c86ace | ||
|
182ffb5819 | ||
|
e9f781a5a4 | ||
|
cb3801a4c9 | ||
|
8a135111ca | ||
|
5e837858e7 | ||
|
a3fecea5e2 | ||
|
f01132aacf | ||
|
ad920b4cb3 | ||
|
a7396f8364 | ||
|
71ec342d13 | ||
|
3b9010b170 | ||
|
cf89e48028 | ||
|
3cbf00a30c | ||
|
0f67cb3606 | ||
|
5ceb38cb1e | ||
|
312cf91005 | ||
|
b1b128d0e2 | ||
|
91cdc8ab0f | ||
|
009a02b263 | ||
|
b83358b87f | ||
|
bf1ef54d30 | ||
|
8f9ea89ce4 | ||
|
5229cd839a | ||
|
595ca10f37 | ||
|
6e3f32cc56 | ||
|
1462736c7e | ||
|
f441831c9e | ||
|
4bc06da775 | ||
|
ced0ef3b35 | ||
|
e95861d909 | ||
|
0f72af536f | ||
|
b5ea69f5ac | ||
|
04fa5c1580 | ||
|
394a678aec | ||
|
32c3e1379d | ||
|
0d1ebcf67d | ||
|
0e5a83f510 | ||
|
8f114904fc | ||
|
cffae6e113 | ||
|
a48803fd84 | ||
|
22583a002e | ||
|
be1bcb85ce | ||
|
85d040dabd | ||
|
67e5622bfe | ||
|
0da73fab56 | ||
|
1152826e8d | ||
|
d6d98a0c01 | ||
|
114453d795 | ||
|
e61032bf47 | ||
|
9aee971185 | ||
|
64b504bde3 | ||
|
12807b5a49 | ||
|
4a4e7ec0e9 | ||
|
d517427dff | ||
|
5e6a48bf99 | ||
|
781c8c3f72 | ||
|
4c9f242a54 | ||
|
7a8556b901 | ||
|
5830d34b40 | ||
|
80080f34f3 | ||
|
4f6086ceb4 | ||
|
be883be6d3 | ||
|
96c4d9d94d | ||
|
25b1a73f71 | ||
|
a5370d35d6 | ||
|
1184626a26 | ||
|
3ee8082947 | ||
|
6db5a6e799 | ||
|
4dac692094 | ||
|
65d9ef40f2 | ||
|
d54bbc4cdc | ||
|
5d1e57b820 | ||
|
4d98709cb2 | ||
|
9b1d97cccd | ||
|
caf1436ee8 | ||
|
ce66a2f2bb | ||
|
52cd287933 | ||
|
e1c52c9238 | ||
|
db5381c49c | ||
|
a87a9625f8 | ||
|
f07fe275d5 | ||
|
7f471bd3b2 | ||
|
32580792df | ||
|
166a678fea | ||
|
5e782e4de3 | ||
|
014d23c395 | ||
|
6082ccf792 | ||
|
8d08f18b52 | ||
|
00a415fc8f | ||
|
96ec3911f3 | ||
|
5aab7ad075 | ||
|
1fc1a32941 | ||
|
8351463f67 | ||
|
98e28335b7 | ||
|
476b7c3a68 | ||
|
abeedbde90 | ||
|
e837c257d0 | ||
|
7f8c27758b | ||
|
c195fdba12 | ||
|
47f58740aa | ||
|
b58b00e4c3 | ||
|
a4d1891475 | ||
|
0543b02cf8 | ||
|
930d65ccca | ||
|
640f8c3eb8 | ||
|
7c4e351861 | ||
|
f28cedfa31 | ||
|
48acd7fe90 | ||
|
56785120a0 | ||
|
e76fcd0e40 | ||
|
0d298a771a | ||
|
7fd45eec37 | ||
|
a0c314d6b0 | ||
|
9914b95a3f | ||
|
d0a63cf041 | ||
|
a763364cc9 | ||
|
9bc2acad8f | ||
|
106f64cbd6 | ||
|
78ef395947 | ||
|
93fc2adfa4 | ||
|
26f65dc0c7 | ||
|
ab70e42999 | ||
|
4a90166488 | ||
|
036c75ded3 | ||
|
e803e95760 | ||
|
498c20fad6 | ||
|
c5f95bc19b | ||
|
3f1d499964 | ||
|
301c159ce5 | ||
|
d68c8888c2 | ||
|
b8f49003d3 | ||
|
7f14902cc2 | ||
|
0bdcca5aee | ||
|
a2840b9599 | ||
|
7ab25935f3 | ||
|
61ecc410ea | ||
|
7edb1b42fc | ||
|
46d9f19465 | ||
|
9c6c4ad173 | ||
|
975115321f | ||
|
130698dc20 | ||
|
db09f8ad1b | ||
|
3fbc35bf9a | ||
|
beed1447b9 | ||
|
8746c17e15 | ||
|
764c91ed12 | ||
|
7406e0a3af | ||
|
1855064d4e | ||
|
b92be9b8e0 | ||
|
3e32e5a4d2 | ||
|
f393b2f99f | ||
|
a814fd7897 | ||
|
390bab5392 | ||
|
af44a16ec7 | ||
|
10a768443a | ||
|
dcd333168e | ||
|
9171384149 | ||
|
11ee1bab60 | ||
|
9311c28b34 | ||
|
19491cc90f | ||
|
d21b42b463 | ||
|
e813252378 |
4
.github/workflows/coverage.yml
vendored
4
.github/workflows/coverage.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@07ef37c4c0dad5dfc6cec86c967a7600df1cd88c
|
||||
- uses: systemd/mkosi@7d45366395f29fdb2b534a850c09d23d29b78fa9
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
@ -64,7 +64,7 @@ jobs:
|
||||
MESON_OPTIONS=--werror
|
||||
COVERAGE=1
|
||||
|
||||
[Host]
|
||||
[Runtime]
|
||||
QemuMem=4G
|
||||
EOF
|
||||
|
||||
|
8
.github/workflows/linter.yml
vendored
8
.github/workflows/linter.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
VALIDATE_GITHUB_ACTIONS: true
|
||||
|
||||
- name: Check that tabs are not used in Python code
|
||||
run: sh -c '! git grep -P "\\t" -- src/ukify/ukify.py test/integration-test-wrapper.py'
|
||||
run: sh -c '! git grep -P "\\t" -- src/boot/generate-hwids-section.py src/ukify/ukify.py test/integration-test-wrapper.py'
|
||||
|
||||
- name: Install ruff and mypy
|
||||
run: |
|
||||
@ -47,14 +47,14 @@ jobs:
|
||||
- name: Run mypy
|
||||
run: |
|
||||
python3 -m mypy --version
|
||||
python3 -m mypy src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
python3 -m mypy src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
|
||||
- name: Run ruff check
|
||||
run: |
|
||||
ruff --version
|
||||
ruff check src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
ruff check src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
|
||||
- name: Run ruff format
|
||||
run: |
|
||||
ruff --version
|
||||
ruff format --check src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
ruff format --check src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py
|
||||
|
4
.github/workflows/mkosi.yml
vendored
4
.github/workflows/mkosi.yml
vendored
@ -113,7 +113,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@c4bbf3b71a3e2cf947995caedf10f69da3c4957a
|
||||
- uses: systemd/mkosi@7d45366395f29fdb2b534a850c09d23d29b78fa9
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
@ -171,7 +171,7 @@ jobs:
|
||||
[Content]
|
||||
SELinuxRelabel=${{ matrix.relabel }}
|
||||
|
||||
[Host]
|
||||
[Runtime]
|
||||
QemuMem=4G
|
||||
EOF
|
||||
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@
|
||||
.config.args
|
||||
.gdb_history
|
||||
.deps/
|
||||
.venv/
|
||||
.mypy_cache/
|
||||
__pycache__/
|
||||
/*.gcda
|
||||
|
@ -109,9 +109,6 @@ EOF
|
||||
--env DPKG_DEB_COMPRESSOR_TYPE="none" \
|
||||
--env DEB_BUILD_PROFILES="pkg.systemd.upstream noudeb nodoc" \
|
||||
--env TEST_UPSTREAM=1 \
|
||||
--skip-test localed-locale \
|
||||
--skip-test localed-x11-keymap \
|
||||
--skip-test build-with-static-libsystemd \
|
||||
../systemd_*.dsc \
|
||||
-o "$ARTIFACTS_DIR" \
|
||||
-- lxc -s "$CONTAINER" \
|
||||
|
@ -15,7 +15,7 @@ auto_cancel:
|
||||
when: "true"
|
||||
|
||||
execution_time_limit:
|
||||
hours: 1
|
||||
hours: 2
|
||||
|
||||
blocks:
|
||||
- name: "Setup & test"
|
||||
|
5
NEWS
5
NEWS
@ -4,6 +4,11 @@ CHANGES WITH 258 in spe:
|
||||
|
||||
Incompatible changes:
|
||||
|
||||
* The default access mode of tty/pts device nodes has been changed to
|
||||
0600, which was 0620 in the older releases, due to general security
|
||||
concerns about terminals being written to by other users. To restore
|
||||
the old default access mode, use '-Dtty-mode=0620' meson build option.
|
||||
|
||||
* systemd-run's --expand-environment= switch, which was disabled
|
||||
by default when combined with --scope, has been changed to to be
|
||||
enabled by default. This brings cmdline expansion of transient
|
||||
|
7
README
7
README
@ -29,8 +29,7 @@ LICENSE:
|
||||
LGPL-2.1-or-later for all code, exceptions noted in LICENSES/README.md
|
||||
|
||||
REQUIREMENTS:
|
||||
Linux kernel ≥ 3.15
|
||||
≥ 4.3 for ambient capabilities
|
||||
Linux kernel ≥ 4.3
|
||||
≥ 4.5 for pids controller in cgroup v2
|
||||
≥ 4.6 for cgroup namespaces
|
||||
≥ 4.9 for RENAME_NOREPLACE support in vfat
|
||||
@ -42,9 +41,9 @@ REQUIREMENTS:
|
||||
≥ 5.4 for pidfd and signed Verity images
|
||||
≥ 5.7 for CLONE_INTO_CGROUP, BPF links and the BPF LSM hook
|
||||
|
||||
⛔ Kernel versions below 3.15 ("minimum baseline") are not supported at
|
||||
⛔ Kernel versions below 4.3 ("minimum baseline") are not supported at
|
||||
all, and are missing required functionality (e.g. CLOCK_BOOTTIME
|
||||
support for timerfd_create()).
|
||||
support for timerfd_create(), ambient capabilities, or memfd_create()).
|
||||
|
||||
⚠️ Kernel versions below 5.4 ("recommended baseline") have significant
|
||||
gaps in functionality and are not recommended for use with this version
|
||||
|
12
TODO
12
TODO
@ -101,13 +101,6 @@ Deprecations and removals:
|
||||
and then rework cgroupsv2 support around fds, i.e. keep one fd per active
|
||||
unit around, and always operate on that, instead of cgroup fs paths.
|
||||
|
||||
* drop support for kernels that lack ambient capabilities support (i.e. make
|
||||
4.3 new baseline). Then drop support for "!!" modifier for ExecStart= which
|
||||
is only supported for such old kernels.
|
||||
|
||||
* drop support for kernels lacking memfd_create() (i.e. make 3.17 new
|
||||
baseline), then drop all pipe() based fallbacks.
|
||||
|
||||
* drop support for getrandom()-less kernels. (GRND_INSECURE means once kernel
|
||||
5.6 becomes our baseline). See
|
||||
https://github.com/systemd/systemd/pull/24101#issuecomment-1193966468 for
|
||||
@ -129,8 +122,7 @@ Deprecations and removals:
|
||||
|
||||
Features:
|
||||
|
||||
* our logging tools should look for $DEBUG_INVOCATION and consider equivalent
|
||||
to $SYSTEMD_LOG_LEVEL=debug
|
||||
* resolved: make resolved process DNR DHCP info
|
||||
|
||||
* Teach systemd-ssh-generator to generated an /run/issue.d/ drop-in telling
|
||||
users how to connect to the system via the AF_VSOCK, as per:
|
||||
@ -803,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,
|
||||
|
@ -3,3 +3,7 @@
|
||||
# Dell iDRAC Virtual USB NIC
|
||||
usb:v413CpA102*
|
||||
ID_NET_NAME_FROM_DATABASE=idrac
|
||||
|
||||
# Disable inclusion of PCI domain in interface names on Azure MANA
|
||||
pci:v00001414d000000BA*
|
||||
ID_NET_NAME_INCLUDE_DOMAIN=0
|
||||
|
@ -739,6 +739,19 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:*
|
||||
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:*
|
||||
KEYBOARD_KEY_f8=wlan # Wireless HW switch button
|
||||
|
||||
# 2170p running coreboot
|
||||
evdev:atkbd:dmi:bvncoreboot:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook2170p:*
|
||||
evdev:atkbd:dmi:bvncoreboot:bvr*:bd*:svnHP*:pn*EliteBook2170p:*
|
||||
KEYBOARD_KEY_66=backspace
|
||||
KEYBOARD_KEY_be=battery # Fn+F2
|
||||
KEYBOARD_KEY_d7=switchvideomode # Fn+F4
|
||||
KEYBOARD_KEY_a3=mute # Fn+F5
|
||||
KEYBOARD_KEY_a1=volumedown # Fn+F6
|
||||
KEYBOARD_KEY_a2=volumeup # Fn+F7
|
||||
KEYBOARD_KEY_a4=brightnessdown # Fn+F9
|
||||
KEYBOARD_KEY_c3=brightnessup # Fn+F10
|
||||
KEYBOARD_KEY_e3=wlan # Fn+F12
|
||||
|
||||
# Elitebook 2760p
|
||||
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2760p*:*
|
||||
KEYBOARD_KEY_89=battery # Fn+F8
|
||||
@ -2210,6 +2223,11 @@ evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:bd*:svnPositivoBahia-VAIO:
|
||||
evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:bd*:svnPositivoBahia-VAIO:pnVJFE*:pvr*:*
|
||||
KEYBOARD_KEY_76=f21 # Fn+F1 toggle touchpad
|
||||
|
||||
# VAIO VJFH52
|
||||
evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:bd*:svnPositivoBahia-VAIO:pnVJFH52F11X*:pvr*:*
|
||||
KEYBOARD_KEY_f7=f23 # Fn+F1 toggle touchpad off
|
||||
KEYBOARD_KEY_f8=f22 # Fn+F1 toggle touchpad on
|
||||
|
||||
###########################################################
|
||||
# Positivo
|
||||
###########################################################
|
||||
|
24
hwdb.d/70-lights.hwdb
Normal file
24
hwdb.d/70-lights.hwdb
Normal file
@ -0,0 +1,24 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# Database for remote controllable lights that should be accessible to the seat owner,
|
||||
# such as Bluetooth or USB lights that are used in conjuction with the computer like
|
||||
# streaming lights.
|
||||
#
|
||||
# To add local entries, copy this file to
|
||||
# /etc/udev/hwdb.d/
|
||||
# and add your rules there. To load the new rules execute (as root):
|
||||
# systemd-hwdb update
|
||||
# udevadm trigger
|
||||
|
||||
################
|
||||
# Logitech
|
||||
################
|
||||
# Litra Beam
|
||||
bluetooth:v046dpc901*
|
||||
usb:v046dpc901*
|
||||
ID_AV_LIGHTS=1
|
||||
|
||||
# Litra Glow
|
||||
bluetooth:v046dpc900*
|
||||
usb:v046dpc900*
|
||||
ID_AV_LIGHTS=1
|
@ -159,6 +159,7 @@ def property_grammar():
|
||||
('ID_AUTOSUSPEND', Or((Literal('0'), Literal('1')))),
|
||||
('ID_AUTOSUSPEND_DELAY_MS', INTEGER),
|
||||
('ID_AV_PRODUCTION_CONTROLLER', Or((Literal('0'), Literal('1')))),
|
||||
('ID_AV_LIGHTS', Or((Literal('0'), Literal('1')))),
|
||||
('ID_PERSIST', Or((Literal('0'), Literal('1')))),
|
||||
('ID_PDA', Or((Literal('0'), Literal('1')))),
|
||||
('ID_INPUT', id_input_setting),
|
||||
|
@ -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>
|
||||
|
@ -409,6 +409,21 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>EnableWallMessages=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Controls whether
|
||||
<citerefentry><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
messages should be sent to the terminals of all currently logged in users upon shutdown or
|
||||
reboot. Defaults to <literal>yes</literal>, and can be changed at runtime via the DBus
|
||||
<literal>EnableWallMessages</literal> and <literal>WallMessagePrefix</literal> properties.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -3359,7 +3359,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
readonly (ss) ProtectHostnameEx = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
@ -4885,8 +4885,9 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
<para><varname>ProtectHostnameEx</varname> implement the destination parameter of the
|
||||
unit file setting <varname>ProtectHostname=</varname> listed in
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
Unlike boolean <varname>ProtectHostname</varname>, <varname>ProtectHostnameEx</varname>
|
||||
is a string type.</para>
|
||||
Unlike boolean <varname>ProtectHostname</varname>, <varname>ProtectHostnameEx</varname> is a pair of
|
||||
strings, the first one is a boolean string or special value <literal>private</literal>, and the second
|
||||
one is an optional private hostname that will be set in a new UTS namespace for the unit.</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
@ -5552,7 +5553,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
readonly (ss) ProtectHostnameEx = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
@ -7561,7 +7562,7 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
readonly (ss) ProtectHostnameEx = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
@ -9537,7 +9538,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ProtectHostname = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHostnameEx = '...';
|
||||
readonly (ss) ProtectHostnameEx = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b MemoryKSM = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
|
@ -1093,7 +1093,11 @@ manpages = [
|
||||
['systemd-sysctl.service', '8', ['systemd-sysctl'], ''],
|
||||
['systemd-sysext',
|
||||
'8',
|
||||
['systemd-confext', 'systemd-confext.service', 'systemd-sysext.service'],
|
||||
['systemd-confext',
|
||||
'systemd-confext-initrd.service',
|
||||
'systemd-confext.service',
|
||||
'systemd-sysext-initrd.service',
|
||||
'systemd-sysext.service'],
|
||||
'ENABLE_SYSEXT'],
|
||||
['systemd-system-update-generator', '8', [], ''],
|
||||
['systemd-system.conf',
|
||||
|
@ -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>
|
||||
|
||||
|
@ -19,8 +19,10 @@
|
||||
<refnamediv>
|
||||
<refname>systemd-sysext</refname>
|
||||
<refname>systemd-sysext.service</refname>
|
||||
<refname>systemd-sysext-initrd.service</refname>
|
||||
<refname>systemd-confext</refname>
|
||||
<refname>systemd-confext.service</refname>
|
||||
<refname>systemd-confext-initrd.service</refname>
|
||||
<refpurpose>Activates System Extension Images</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
|
@ -832,10 +832,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
assigned to this option, the ambient capability set is reset to the empty capability set, and all prior
|
||||
settings have no effect. If set to <literal>~</literal> (without any further argument), the ambient capability
|
||||
set is reset to the full set of available capabilities, also undoing any previous settings. Note that adding
|
||||
capabilities to the ambient capability set adds them to the process's inherited capability set. </para><para>
|
||||
Ambient capability sets are useful if you want to execute a process as a non-privileged user but still want to
|
||||
give it some capabilities. Note that in this case option <constant>keep-caps</constant> is automatically added
|
||||
to <varname>SecureBits=</varname> to retain the capabilities over the user
|
||||
capabilities to the ambient capability set adds them to the process's inherited capability set.</para>
|
||||
|
||||
<para>Ambient capability sets are useful if you want to execute a process as a non-privileged user but
|
||||
still want to give it some capabilities. Note that in this case option <constant>keep-caps</constant>
|
||||
is automatically added to <varname>SecureBits=</varname> to retain the capabilities over the user
|
||||
change. <varname>AmbientCapabilities=</varname> does not affect commands prefixed with
|
||||
<literal>+</literal>.</para>
|
||||
|
||||
@ -2062,11 +2063,13 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
|
||||
<varlistentry>
|
||||
<term><varname>ProtectHostname=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument or <literal>private</literal>. If enabled, sets up a new UTS namespace
|
||||
for the executed processes. If set to a true value, changing hostname or domainname via
|
||||
<function>sethostname()</function> and <function>setdomainname()</function> system calls is prevented. If set to
|
||||
<literal>private</literal>, changing hostname or domainname is allowed but only affects the unit's UTS namespace.
|
||||
Defaults to off.</para>
|
||||
<listitem><para>Takes a boolean argument or <literal>private</literal>. If enabled, sets up a new UTS
|
||||
namespace for the executed processes. If enabled, a hostname can be optionally specified following a
|
||||
colon (e.g. <literal>yes:foo</literal> or <literal>private:host.example.com</literal>), and the
|
||||
hostname is set in the new UTS namespace for the unit. If set to a true value, changing hostname or
|
||||
domainname via <function>sethostname()</function> and <function>setdomainname()</function> system
|
||||
calls is prevented. If set to <literal>private</literal>, changing hostname or domainname is allowed
|
||||
but only affects the unit's UTS namespace. Defaults to off.</para>
|
||||
|
||||
<para>Note that the implementation of this setting might be impossible (for example if UTS namespaces
|
||||
are not available), and the unit should be written in a way that does not solely rely on this setting
|
||||
|
@ -64,6 +64,10 @@
|
||||
override existing definitions. For tests, generators may be called with just one argument; the generator
|
||||
should assume that all three paths are the same in that case.</para>
|
||||
|
||||
<para>Generators executed by the system manager are invoked in a sandbox with a private writable
|
||||
<filename>/tmp/</filename> directory and where most of the file system is read-only except for the
|
||||
generator output directories.</para>
|
||||
|
||||
<para>Directory paths for generator output differ by priority: <filename>…/generator.early</filename> has
|
||||
priority higher than the admin configuration in <filename>/etc/</filename>, while
|
||||
<filename>…/generator</filename> has lower priority than <filename>/etc/</filename> but higher than
|
||||
|
@ -1148,6 +1148,24 @@ DuplicateAddressDetection=none</programlisting></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>MPLSRouting=</varname></term>
|
||||
<listitem>
|
||||
<para>Control whether Multi-protocol Label Switching (MPLS) routing is enabled on this interface.
|
||||
This configures <filename>/proc/sys/net/mpls/conf/<replaceable>INTERFACE</replaceable>/input</filename>.
|
||||
Takes a boolean. Defaults to unset, and the kernel's default will be used.</para>
|
||||
|
||||
<para>Note, <command>systemd-networkd</command> does <emphasis>not</emphasis> load any required
|
||||
kernel modules for MPLS. To enable the feature, <filename>mpls_router</filename> kernel module must
|
||||
be loaded before <filename>systemd-networkd.service</filename> is started. Consider adding the
|
||||
kernel module to
|
||||
<citerefentry><refentrytitle>modules-load.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>KeepMaster=</varname></term>
|
||||
<listitem>
|
||||
|
@ -1410,12 +1410,6 @@
|
||||
|
||||
<entry>Similar to the <literal>+</literal> character discussed above this permits invoking command lines with elevated privileges. However, unlike <literal>+</literal> the <literal>!</literal> character exclusively alters the effect of <varname>User=</varname>, <varname>Group=</varname> and <varname>SupplementaryGroups=</varname>, i.e. only the stanzas that affect user and group credentials. Note that this setting may be combined with <varname>DynamicUser=</varname>, in which case a dynamic user/group pair is allocated before the command is invoked, but credential changing is left to the executed process itself.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>!!</literal></entry>
|
||||
|
||||
<entry>This prefix is very similar to <literal>!</literal>, however it only has an effect on systems lacking support for ambient process capabilities, i.e. without support for <varname>AmbientCapabilities=</varname>. It's intended to be used for unit files that take benefit of ambient capabilities to run processes with minimal privileges wherever possible while remaining compatible with systems that lack ambient capabilities support. Note that when <literal>!!</literal> is used, and a system lacking ambient capability support is detected any configured <varname>SystemCallFilter=</varname> and <varname>CapabilityBoundingSet=</varname> stanzas are implicitly modified, in order to permit spawned processes to drop credentials and capabilities themselves, even if this is configured to not be allowed. Moreover, if this prefix is used and a system lacking ambient capability support is detected <varname>AmbientCapabilities=</varname> will be skipped and not be applied. On systems supporting ambient capabilities, <literal>!!</literal> has no effect and is redundant.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -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'
|
||||
|
@ -577,6 +577,17 @@
|
||||
<xi:include href="version-info.xml" xpointer="v251"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--include-parents</option></term>
|
||||
<listitem>
|
||||
<para>Trigger parent devices of found devices even if the parents
|
||||
won't match the filter condition.
|
||||
This is useful if we are interested to limit the coldplug activities to
|
||||
some devices or subsystems.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-w</option></term>
|
||||
<term><option>--settle</option></term>
|
||||
|
@ -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'
|
||||
|
10
meson.build
10
meson.build
@ -978,6 +978,16 @@ conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666')
|
||||
group_render_mode = get_option('group-render-mode')
|
||||
conf.set_quoted('GROUP_RENDER_MODE', group_render_mode)
|
||||
conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666')
|
||||
tty_mode = get_option('tty-mode')
|
||||
# The setting is used as both octal integer and string through STRINGIFY().
|
||||
# Here, only check if the value starts with '06', and further check will be done in terminal-util.h.
|
||||
if not tty_mode.startswith('06')
|
||||
error('Unexpected access mode "@0@" is specified for TTY/PTS device nodes, it must be "06xx".'.format(tty_mode))
|
||||
elif tty_mode != '0600' and tty_mode != '0620'
|
||||
warning('Unexpected access mode "@0@" is specified for TTY/PTS device nodes, typically it should be "0600" or "0620", proceeding anyway.'.format(tty_mode))
|
||||
endif
|
||||
# Do not use set_quoted() here, so that the value is available as an integer.
|
||||
conf.set('TTY_MODE', tty_mode)
|
||||
|
||||
kill_user_processes = get_option('default-kill-user-processes')
|
||||
conf.set10('KILL_USER_PROCESSES', kill_user_processes)
|
||||
|
@ -330,6 +330,8 @@ option('dev-kvm-mode', type : 'string', value : '0666',
|
||||
description : '/dev/kvm access mode')
|
||||
option('group-render-mode', type : 'string', value : '0666',
|
||||
description : 'Access mode for devices owned by render group (e.g. /dev/dri/renderD*, /dev/kfd).')
|
||||
option('tty-mode', type : 'string', value : '0600',
|
||||
description : 'Access mode for tty/pts device nodes.')
|
||||
option('default-kill-user-processes', type : 'boolean',
|
||||
description : 'the default value for KillUserProcesses= setting')
|
||||
option('gshadow', type : 'boolean',
|
||||
|
@ -74,7 +74,8 @@ KernelCommandLine=
|
||||
oops=panic
|
||||
panic=-1
|
||||
softlockup_panic=1
|
||||
panic_on_warn=1
|
||||
# Disabled due to BTRFS issue, waiting for the fix to become available
|
||||
panic_on_warn=0
|
||||
psi=1
|
||||
|
||||
KernelModulesInitrdExclude=.*
|
||||
@ -129,7 +130,7 @@ Packages=
|
||||
zsh
|
||||
zstd
|
||||
|
||||
[Host]
|
||||
[Runtime]
|
||||
Credentials=
|
||||
journal.storage=persistent
|
||||
tty.serial.hvc0.agetty.autologin=root
|
||||
|
@ -15,7 +15,7 @@ ToolsTreePackages=
|
||||
pkgconfig(libmicrohttpd)
|
||||
pkgconfig(mount)
|
||||
python3-ruff
|
||||
tss2-devel
|
||||
tpm2-0-tss-devel
|
||||
python3-jinja2
|
||||
python3-pytest
|
||||
ShellCheck
|
||||
|
@ -3,5 +3,5 @@
|
||||
[Match]
|
||||
Environment=NO_BUILD=1
|
||||
|
||||
[Content]
|
||||
[Build]
|
||||
WithNetwork=yes
|
||||
|
@ -78,7 +78,6 @@ wrap=(
|
||||
su
|
||||
tar
|
||||
tgtd
|
||||
unshare
|
||||
useradd
|
||||
userdel
|
||||
veritysetup
|
||||
|
9
po/fi.po
9
po/fi.po
@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-28 18:16+0900\n"
|
||||
"PO-Revision-Date: 2024-11-20 19:13+0000\n"
|
||||
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>\n"
|
||||
"PO-Revision-Date: 2024-12-20 15:38+0000\n"
|
||||
"Last-Translator: Ricky Tigg <ricky.tigg@gmail.com>\n"
|
||||
"Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/"
|
||||
"main/fi/>\n"
|
||||
"Language: fi\n"
|
||||
@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.8.2\n"
|
||||
"X-Generator: Weblate 5.9.1\n"
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:22
|
||||
msgid "Send passphrase back to system"
|
||||
@ -1176,9 +1176,8 @@ msgid "Manage optional features"
|
||||
msgstr "Hallitse valinnaisia ominaisuuksia"
|
||||
|
||||
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76
|
||||
#, fuzzy
|
||||
msgid "Authentication is required to manage optional features."
|
||||
msgstr "Todennus vaaditaan valinnaisten ominaisuuksien hallintaan"
|
||||
msgstr "Todennus vaaditaan valinnaisten ominaisuuksien hallintaan."
|
||||
|
||||
#: src/timedate/org.freedesktop.timedate1.policy:22
|
||||
msgid "Set system time"
|
||||
|
@ -37,7 +37,7 @@ ACTION!="add", GOTO="default_end"
|
||||
|
||||
SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
|
||||
SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
|
||||
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*|hvc[0-9]*|sclp_line[0-9]*|ttysclp[0-9]*|3270/tty[0-9]*", GROUP="tty", MODE="0620"
|
||||
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*|hvc[0-9]*|sclp_line[0-9]*|ttysclp[0-9]*|3270/tty[0-9]*", GROUP="tty", MODE="{{TTY_MODE}}"
|
||||
SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty"
|
||||
KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout"
|
||||
|
||||
|
@ -99,6 +99,10 @@ SUBSYSTEM=="hidraw", ENV{ID_AV_PRODUCTION_CONTROLLER}=="1", TAG+="uaccess"
|
||||
# This also allows accessing HID devices with the libusb backend of hidapi.
|
||||
SUBSYSTEM=="usb", ENV{ID_AV_PRODUCTION_CONTROLLER}=="1", TAG+="uaccess"
|
||||
|
||||
# USB and Bluetooth controllable lights
|
||||
SUBSYSTEM=="hidraw", ENV{ID_AV_LIGHTS}=="1", TAG+="uaccess"
|
||||
SUBSYSTEM=="usb", ENV{ID_AV_LIGHTS}=="1", TAG+="uaccess"
|
||||
|
||||
# Hardware wallets
|
||||
SUBSYSTEM=="usb", ENV{ID_HARDWARE_WALLET}=="1", TAG+="uaccess"
|
||||
SUBSYSTEM=="hidraw", ENV{ID_HARDWARE_WALLET}=="1", TAG+="uaccess"
|
||||
|
@ -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'
|
||||
|
@ -58,7 +58,7 @@ _udevadm() {
|
||||
--json --subsystem-match --subsystem-nomatch --attr-match --attr-nomatch --property-match
|
||||
--tag-match --sysname-match --name-match --parent-match'
|
||||
[TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid
|
||||
--initialized-match --initialized-nomatch'
|
||||
--initialized-match --initialized-nomatch --include-parents'
|
||||
[TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch
|
||||
-a --attr-match -A --attr-nomatch -p --property-match
|
||||
-g --tag-match -y --sysname-match --name-match -b --parent-match
|
||||
|
@ -38,6 +38,7 @@ _udevadm_trigger(){
|
||||
'--tag-match=[Trigger events for devices with a matching tag.]:TAG' \
|
||||
'--sysname-match=[Trigger events for devices with a matching sys device name.]:NAME' \
|
||||
'--parent-match=[Trigger events for all children of a given device.]:NAME' \
|
||||
'--include-parents[Also trigger parent devices of found devices.]' \
|
||||
'--initialized-match[Trigger events for devices that are already initialized.]' \
|
||||
'--initialized-nomatch[Trigger events for devices that are not initialized yet.]' \
|
||||
'--uuid[Print synthetic uevent UUID.]' \
|
||||
|
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',
|
||||
|
@ -9,8 +9,8 @@
|
||||
|
||||
#define AUDIT_SESSION_INVALID UINT32_MAX
|
||||
|
||||
int audit_session_from_pid(const PidRef *pid, uint32_t *id);
|
||||
int audit_loginuid_from_pid(const PidRef *pid, uid_t *uid);
|
||||
int audit_session_from_pid(const PidRef *pid, uint32_t *ret_id);
|
||||
int audit_loginuid_from_pid(const PidRef *pid, uid_t *ret_uid);
|
||||
|
||||
bool use_audit(void);
|
||||
|
||||
|
@ -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) {
|
||||
@ -123,12 +126,6 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
|
||||
|
||||
/* Add the capabilities to the ambient set (an possibly also the inheritable set) */
|
||||
|
||||
/* Check that we can use PR_CAP_AMBIENT or quit early. */
|
||||
if (!ambient_capabilities_supported())
|
||||
return (set & all_capabilities()) == 0 ?
|
||||
0 : -EOPNOTSUPP; /* if actually no ambient caps are to be set, be silent,
|
||||
* otherwise fail recognizably */
|
||||
|
||||
if (also_inherit) {
|
||||
caps = cap_get_proc();
|
||||
if (!caps)
|
||||
@ -395,32 +392,12 @@ int keep_capability(cap_value_t cv) {
|
||||
return change_capability(cv, CAP_SET);
|
||||
}
|
||||
|
||||
bool ambient_capabilities_supported(void) {
|
||||
static int cache = -1;
|
||||
|
||||
if (cache >= 0)
|
||||
return cache;
|
||||
|
||||
/* If PR_CAP_AMBIENT returns something valid, or an unexpected error code we assume that ambient caps are
|
||||
* available. */
|
||||
|
||||
cache = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_KILL, 0, 0) >= 0 ||
|
||||
!IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool capability_quintet_mangle(CapabilityQuintet *q) {
|
||||
uint64_t combined, drop = 0;
|
||||
bool ambient_supported;
|
||||
|
||||
assert(q);
|
||||
|
||||
combined = q->effective | q->bounding | q->inheritable | q->permitted;
|
||||
|
||||
ambient_supported = q->ambient != CAP_MASK_UNSET;
|
||||
if (ambient_supported)
|
||||
combined |= q->ambient;
|
||||
combined = q->effective | q->bounding | q->inheritable | q->permitted | q->ambient;
|
||||
|
||||
for (unsigned i = 0; i <= cap_last_cap(); i++) {
|
||||
unsigned long bit = UINT64_C(1) << i;
|
||||
@ -439,9 +416,7 @@ bool capability_quintet_mangle(CapabilityQuintet *q) {
|
||||
q->bounding &= ~drop;
|
||||
q->inheritable &= ~drop;
|
||||
q->permitted &= ~drop;
|
||||
|
||||
if (ambient_supported)
|
||||
q->ambient &= ~drop;
|
||||
q->ambient &= ~drop;
|
||||
|
||||
return drop != 0; /* Let the caller know we changed something */
|
||||
}
|
||||
@ -623,11 +598,6 @@ int capability_get_ambient(uint64_t *ret) {
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (!ambient_capabilities_supported()) {
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i <= cap_last_cap(); i++) {
|
||||
r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
|
||||
if (r < 0)
|
||||
@ -640,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
|
||||
@ -50,8 +51,6 @@ static inline bool cap_test_all(uint64_t caps) {
|
||||
return FLAGS_SET(caps, all_capabilities());
|
||||
}
|
||||
|
||||
bool ambient_capabilities_supported(void);
|
||||
|
||||
/* Identical to linux/capability.h's CAP_TO_MASK(), but uses an unsigned 1U instead of a signed 1 for shifting left, in
|
||||
* order to avoid complaints about shifting a signed int left by 31 bits, which would make it negative. */
|
||||
#define CAP_TO_MASK_CORRECTED(x) (1U << ((x) & 31U))
|
||||
@ -68,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:
|
||||
@ -86,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);
|
||||
|
@ -145,6 +145,11 @@ int read_attr_fd(int fd, unsigned *ret) {
|
||||
if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
|
||||
return -ENOTTY;
|
||||
|
||||
_cleanup_close_ int fd_close = -EBADF;
|
||||
fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_close); /* drop O_PATH if it is set */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
return RET_NERRNO(ioctl(fd, FS_IOC_GETFLAGS, ret));
|
||||
}
|
||||
|
||||
@ -155,11 +160,9 @@ int read_attr_at(int dir_fd, const char *path, unsigned *ret) {
|
||||
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
||||
assert(ret);
|
||||
|
||||
if (isempty(path)) {
|
||||
fd = fd_reopen_condition(dir_fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_close); /* drop O_PATH if it is set */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
} else {
|
||||
if (isempty(path) && dir_fd != AT_FDCWD)
|
||||
fd = dir_fd;
|
||||
else {
|
||||
fd_close = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
|
||||
if (fd_close < 0)
|
||||
return fd_close;
|
||||
|
@ -1406,14 +1406,29 @@ static bool should_parse_proc_cmdline(void) {
|
||||
|
||||
void log_parse_environment_variables(void) {
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
e = getenv("SYSTEMD_LOG_TARGET");
|
||||
if (e && log_set_target_from_string(e) < 0)
|
||||
log_warning("Failed to parse log target '%s', ignoring.", e);
|
||||
|
||||
e = getenv("SYSTEMD_LOG_LEVEL");
|
||||
if (e && log_set_max_level_from_string(e) < 0)
|
||||
log_warning("Failed to parse log level '%s', ignoring.", e);
|
||||
if (e) {
|
||||
r = log_set_max_level_from_string(e);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse log level '%s', ignoring: %m", e);
|
||||
} else {
|
||||
/* If no explicit log level is specified then let's see if this is a debug invocation, and if
|
||||
* so raise the log level to debug too. Note that this is not symmetric: just because
|
||||
* DEBUG_INVOCATION is explicitly set to 0 we won't lower the log level below debug. This
|
||||
* follows the logic that debug logging is an opt-in thing anyway, and if there's any reason
|
||||
* to enable it we should not disable it here automatically. */
|
||||
r = getenv_bool("DEBUG_INVOCATION");
|
||||
if (r < 0 && r != -ENXIO)
|
||||
log_warning_errno(r, "Failed to parse $DEBUG_INVOCATION value, ignoring: %m");
|
||||
else if (r > 0)
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
}
|
||||
|
||||
e = getenv("SYSTEMD_LOG_COLOR");
|
||||
if (e && log_show_color_from_string(e) < 0)
|
||||
|
@ -24,6 +24,11 @@ int memfd_create_wrapper(const char *name, unsigned mode) {
|
||||
unsigned mode_compat;
|
||||
int mfd;
|
||||
|
||||
assert(name);
|
||||
|
||||
/* Wrapper around memfd_create() which adds compat with older kernels where memfd_create() didn't
|
||||
* support MFD_EXEC/MFD_NOEXEC_SEAL. (kernel 6.3+) */
|
||||
|
||||
mfd = RET_NERRNO(memfd_create(name, mode));
|
||||
if (mfd != -EINVAL)
|
||||
return mfd;
|
||||
@ -36,11 +41,11 @@ int memfd_create_wrapper(const char *name, unsigned mode) {
|
||||
return RET_NERRNO(memfd_create(name, mode_compat));
|
||||
}
|
||||
|
||||
int memfd_new(const char *name) {
|
||||
int memfd_new_full(const char *name, unsigned extra_flags) {
|
||||
_cleanup_free_ char *g = NULL;
|
||||
|
||||
if (!name) {
|
||||
char pr[17] = {};
|
||||
char pr[TASK_COMM_LEN] = {};
|
||||
|
||||
/* If no name is specified we generate one. We include
|
||||
* a hint indicating our library implementation, and
|
||||
@ -65,16 +70,18 @@ int memfd_new(const char *name) {
|
||||
}
|
||||
}
|
||||
|
||||
return memfd_create_wrapper(name, MFD_ALLOW_SEALING | MFD_CLOEXEC | MFD_NOEXEC_SEAL);
|
||||
return memfd_create_wrapper(
|
||||
name,
|
||||
MFD_CLOEXEC | MFD_NOEXEC_SEAL | extra_flags);
|
||||
}
|
||||
|
||||
int memfd_add_seals(int fd, unsigned int seals) {
|
||||
int memfd_add_seals(int fd, unsigned seals) {
|
||||
assert(fd >= 0);
|
||||
|
||||
return RET_NERRNO(fcntl(fd, F_ADD_SEALS, seals));
|
||||
}
|
||||
|
||||
int memfd_get_seals(int fd, unsigned int *ret_seals) {
|
||||
int memfd_get_seals(int fd, unsigned *ret_seals) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
@ -88,30 +95,6 @@ int memfd_get_seals(int fd, unsigned int *ret_seals) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
|
||||
unsigned int seals;
|
||||
void *q;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(size > 0);
|
||||
assert(p);
|
||||
|
||||
r = memfd_get_seals(fd, &seals);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (seals & F_SEAL_WRITE)
|
||||
q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
|
||||
else
|
||||
q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (q == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
*p = q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memfd_set_sealed(int fd) {
|
||||
return memfd_add_seals(fd, F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
|
||||
}
|
||||
@ -128,16 +111,16 @@ int memfd_get_sealed(int fd) {
|
||||
return FLAGS_SET(seals, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
|
||||
}
|
||||
|
||||
int memfd_get_size(int fd, uint64_t *sz) {
|
||||
int memfd_get_size(int fd, uint64_t *ret) {
|
||||
struct stat stat;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(sz);
|
||||
assert(ret);
|
||||
|
||||
if (fstat(fd, &stat) < 0)
|
||||
return -errno;
|
||||
|
||||
*sz = stat.st_size;
|
||||
*ret = stat.st_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -147,50 +130,25 @@ int memfd_set_size(int fd, uint64_t sz) {
|
||||
return RET_NERRNO(ftruncate(fd, sz));
|
||||
}
|
||||
|
||||
int memfd_new_and_map(const char *name, size_t sz, void **p) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(sz > 0);
|
||||
assert(p);
|
||||
|
||||
fd = memfd_new(name);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
r = memfd_set_size(fd, sz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = memfd_map(fd, 0, sz, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return TAKE_FD(fd);
|
||||
}
|
||||
|
||||
int memfd_new_and_seal(const char *name, const void *data, size_t sz) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
ssize_t n;
|
||||
off_t f;
|
||||
int r;
|
||||
|
||||
assert(data || sz == 0);
|
||||
|
||||
fd = memfd_new(name);
|
||||
if (sz == SIZE_MAX)
|
||||
sz = strlen(data);
|
||||
|
||||
fd = memfd_new_full(name, MFD_ALLOW_SEALING);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (sz > 0) {
|
||||
n = write(fd, data, sz);
|
||||
ssize_t n = pwrite(fd, data, sz, 0);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
if ((size_t) n != sz)
|
||||
return -EIO;
|
||||
|
||||
f = lseek(fd, 0, SEEK_SET);
|
||||
if (f != 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = memfd_set_sealed(fd);
|
||||
|
@ -8,16 +8,21 @@
|
||||
|
||||
int memfd_create_wrapper(const char *name, unsigned mode);
|
||||
|
||||
int memfd_new(const char *name);
|
||||
int memfd_new_and_map(const char *name, size_t sz, void **p);
|
||||
int memfd_new_and_seal(const char *name, const void *data, size_t sz);
|
||||
int memfd_new_full(const char *name, unsigned extra_flags);
|
||||
static inline int memfd_new(const char *name) {
|
||||
return memfd_new_full(name, 0);
|
||||
}
|
||||
|
||||
int memfd_add_seals(int fd, unsigned int seals);
|
||||
int memfd_get_seals(int fd, unsigned int *ret_seals);
|
||||
int memfd_map(int fd, uint64_t offset, size_t size, void **p);
|
||||
int memfd_new_and_seal(const char *name, const void *data, size_t sz);
|
||||
static inline int memfd_new_and_seal_string(const char *name, const char *s) {
|
||||
return memfd_new_and_seal(name, s, SIZE_MAX);
|
||||
}
|
||||
|
||||
int memfd_add_seals(int fd, unsigned seals);
|
||||
int memfd_get_seals(int fd, unsigned *ret_seals);
|
||||
|
||||
int memfd_set_sealed(int fd);
|
||||
int memfd_get_sealed(int fd);
|
||||
|
||||
int memfd_get_size(int fd, uint64_t *sz);
|
||||
int memfd_get_size(int fd, uint64_t *ret);
|
||||
int memfd_set_size(int fd, uint64_t sz);
|
||||
|
@ -429,7 +429,7 @@ int pidref_wait(const PidRef *pidref, siginfo_t *ret, int options) {
|
||||
if (pidref_is_remote(pidref))
|
||||
return -EREMOTE;
|
||||
|
||||
if (pidref->pid == 1 || pidref->pid == getpid_cached())
|
||||
if (pidref->pid == 1 || pidref_is_self(pidref))
|
||||
return -ECHILD;
|
||||
|
||||
siginfo_t si = {};
|
||||
|
@ -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);
|
||||
|
@ -115,22 +115,29 @@ int sysctl_writef(const char *property, const char *format, ...) {
|
||||
return sysctl_write(property, v);
|
||||
}
|
||||
|
||||
static const char* af_to_sysctl_dir(int af) {
|
||||
if (af == AF_MPLS)
|
||||
return "mpls";
|
||||
|
||||
return af_to_ipv4_ipv6(af);
|
||||
}
|
||||
|
||||
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value, Hashmap **shadow) {
|
||||
const char *p;
|
||||
|
||||
assert(property);
|
||||
assert(value);
|
||||
|
||||
if (!IN_SET(af, AF_INET, AF_INET6))
|
||||
if (!IN_SET(af, AF_INET, AF_INET6, AF_MPLS))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (ifname) {
|
||||
if (!ifname_valid_full(ifname, IFNAME_VALID_SPECIAL))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/conf/", ifname, "/", property);
|
||||
p = strjoina("net/", af_to_sysctl_dir(af), "/conf/", ifname, "/", property);
|
||||
} else
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/", property);
|
||||
p = strjoina("net/", af_to_sysctl_dir(af), "/", property);
|
||||
|
||||
return sysctl_write_full(p, value, shadow);
|
||||
}
|
||||
@ -181,16 +188,16 @@ int sysctl_read_ip_property(int af, const char *ifname, const char *property, ch
|
||||
|
||||
assert(property);
|
||||
|
||||
if (!IN_SET(af, AF_INET, AF_INET6))
|
||||
if (!IN_SET(af, AF_INET, AF_INET6, AF_MPLS))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (ifname) {
|
||||
if (!ifname_valid_full(ifname, IFNAME_VALID_SPECIAL))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/conf/", ifname, "/", property);
|
||||
p = strjoina("net/", af_to_sysctl_dir(af), "/conf/", ifname, "/", property);
|
||||
} else
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/", property);
|
||||
p = strjoina("net/", af_to_sysctl_dir(af), "/", property);
|
||||
|
||||
return sysctl_read(p, ret);
|
||||
}
|
||||
|
@ -1900,6 +1900,7 @@ static int scan_background_color_response(
|
||||
}
|
||||
|
||||
int get_default_background_color(double *ret_red, double *ret_green, double *ret_blue) {
|
||||
_cleanup_close_ int nonblock_input_fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(ret_red);
|
||||
@ -1933,6 +1934,13 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
/* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() should someone
|
||||
* else process the POLLIN. */
|
||||
|
||||
nonblock_input_fd = fd_reopen(STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
|
||||
if (nonblock_input_fd < 0)
|
||||
return nonblock_input_fd;
|
||||
|
||||
usec_t end = usec_add(now(CLOCK_MONOTONIC), 333 * USEC_PER_MSEC);
|
||||
char buf[STRLEN(ANSI_OSC "11;rgb:0/0/0" ANSI_ST)]; /* shortest possible reply */
|
||||
size_t buf_full = 0;
|
||||
@ -1941,13 +1949,12 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
|
||||
for (bool first = true;; first = false) {
|
||||
if (buf_full == 0) {
|
||||
usec_t n = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (n >= end) {
|
||||
r = -EOPNOTSUPP;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = fd_wait_for_event(STDIN_FILENO, POLLIN, usec_sub_unsigned(end, n));
|
||||
r = fd_wait_for_event(nonblock_input_fd, POLLIN, usec_sub_unsigned(end, n));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (r == 0) {
|
||||
@ -1958,8 +1965,10 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
|
||||
/* On the first try, read multiple characters, i.e. the shortest valid
|
||||
* reply. Afterwards read byte-wise, since we don't want to read too much, and
|
||||
* unnecessarily drop too many characters from the input queue. */
|
||||
ssize_t l = read(STDIN_FILENO, buf, first ? sizeof(buf) : 1);
|
||||
ssize_t l = read(nonblock_input_fd, buf, first ? sizeof(buf) : 1);
|
||||
if (l < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
@ -2083,6 +2092,8 @@ int terminal_get_size_by_dsr(
|
||||
unsigned *ret_rows,
|
||||
unsigned *ret_columns) {
|
||||
|
||||
_cleanup_close_ int nonblock_input_fd = -EBADF;
|
||||
|
||||
assert(input_fd >= 0);
|
||||
assert(output_fd >= 0);
|
||||
|
||||
@ -2130,6 +2141,13 @@ int terminal_get_size_by_dsr(
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
/* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() should someone
|
||||
* else process the POLLIN. */
|
||||
|
||||
nonblock_input_fd = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
|
||||
if (nonblock_input_fd < 0)
|
||||
return nonblock_input_fd;
|
||||
|
||||
usec_t end = usec_add(now(CLOCK_MONOTONIC), 333 * USEC_PER_MSEC);
|
||||
char buf[STRLEN("\x1B[1;1R")]; /* The shortest valid reply possible */
|
||||
size_t buf_full = 0;
|
||||
@ -2138,13 +2156,12 @@ int terminal_get_size_by_dsr(
|
||||
for (bool first = true;; first = false) {
|
||||
if (buf_full == 0) {
|
||||
usec_t n = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (n >= end) {
|
||||
r = -EOPNOTSUPP;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = fd_wait_for_event(input_fd, POLLIN, usec_sub_unsigned(end, n));
|
||||
r = fd_wait_for_event(nonblock_input_fd, POLLIN, usec_sub_unsigned(end, n));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (r == 0) {
|
||||
@ -2155,8 +2172,11 @@ int terminal_get_size_by_dsr(
|
||||
/* On the first try, read multiple characters, i.e. the shortest valid
|
||||
* reply. Afterwards read byte-wise, since we don't want to read too much, and
|
||||
* unnecessarily drop too many characters from the input queue. */
|
||||
ssize_t l = read(input_fd, buf, first ? sizeof(buf) : 1);
|
||||
ssize_t l = read(nonblock_input_fd, buf, first ? sizeof(buf) : 1);
|
||||
if (l < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -143,8 +143,9 @@ int vt_release(int fd, bool restore_vt);
|
||||
|
||||
void get_log_colors(int priority, const char **on, const char **off, const char **highlight);
|
||||
|
||||
/* This assumes there is a 'tty' group */
|
||||
#define TTY_MODE 0620
|
||||
/* Assume TTY_MODE is defined in config.h. Also, this assumes there is a 'tty' group. */
|
||||
assert_cc((TTY_MODE & ~0666) == 0);
|
||||
assert_cc((TTY_MODE & 0711) == 0600);
|
||||
|
||||
void termios_disable_echo(struct termios *termios);
|
||||
|
||||
|
@ -58,13 +58,10 @@ typedef struct SmbiosInfo {
|
||||
} SmbiosInfo;
|
||||
|
||||
static void smbios_info_populate(SmbiosInfo *ret_info) {
|
||||
static RawSmbiosInfo raw = {};
|
||||
static bool raw_info_populated = false;
|
||||
assert(ret_info);
|
||||
|
||||
if (!raw_info_populated) {
|
||||
smbios_raw_info_populate(&raw);
|
||||
raw_info_populated = true;
|
||||
}
|
||||
RawSmbiosInfo raw;
|
||||
smbios_raw_info_get_cached(&raw);
|
||||
|
||||
ret_info->smbios_fields[CHID_SMBIOS_MANUFACTURER] = smbios_to_hashable_string(raw.manufacturer);
|
||||
ret_info->smbios_fields[CHID_SMBIOS_PRODUCT_NAME] = smbios_to_hashable_string(raw.product_name);
|
||||
@ -104,7 +101,11 @@ EFI_STATUS chid_match(const void *hwid_buffer, size_t hwid_length, const Device
|
||||
|
||||
status = populate_board_chids(chids);
|
||||
if (EFI_STATUS_IS_ERROR(status))
|
||||
#if SD_BOOT
|
||||
return log_error_status(status, "Failed to populate board CHIDs: %m");
|
||||
#else
|
||||
return status;
|
||||
#endif
|
||||
|
||||
size_t n_devices = 0;
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "efi-fundamental.h"
|
||||
#include "macro-fundamental.h"
|
||||
|
||||
#if SD_BOOT
|
||||
@ -118,30 +119,11 @@ typedef uint64_t EFI_PHYSICAL_ADDRESS;
|
||||
#define EFI_IP_ADDRESS_CONFLICT EFIERR(34)
|
||||
#define EFI_HTTP_ERROR EFIERR(35)
|
||||
|
||||
typedef struct {
|
||||
uint32_t Data1;
|
||||
uint16_t Data2;
|
||||
uint16_t Data3;
|
||||
uint8_t Data4[8];
|
||||
} EFI_GUID;
|
||||
|
||||
#define GUID_DEF(d1, d2, d3, d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8) \
|
||||
{ d1, d2, d3, { d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8 } }
|
||||
|
||||
/* Creates a EFI_GUID pointer suitable for EFI APIs. Use of const allows the compiler to merge multiple
|
||||
* uses (although, currently compilers do that regardless). Most EFI APIs declare their EFI_GUID input
|
||||
* as non-const, but almost all of them are in fact const. */
|
||||
#define MAKE_GUID_PTR(name) ((EFI_GUID *) &(const EFI_GUID) name##_GUID)
|
||||
|
||||
/* These allow MAKE_GUID_PTR() to work without requiring an extra _GUID in the passed name. We want to
|
||||
* keep the GUID definitions in line with the UEFI spec. */
|
||||
#define EFI_GLOBAL_VARIABLE_GUID EFI_GLOBAL_VARIABLE
|
||||
#define EFI_FILE_INFO_GUID EFI_FILE_INFO_ID
|
||||
|
||||
#define EFI_GLOBAL_VARIABLE \
|
||||
GUID_DEF(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
|
||||
#define EFI_IMAGE_SECURITY_DATABASE_GUID \
|
||||
GUID_DEF(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
|
||||
#define EFI_CUSTOM_MODE_ENABLE_GUID \
|
||||
GUID_DEF(0xc076ec0c, 0x7028, 0x4399, 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f)
|
||||
|
||||
@ -238,20 +220,6 @@ typedef enum {
|
||||
EfiResetPlatformSpecific,
|
||||
} EFI_RESET_TYPE;
|
||||
|
||||
typedef struct {
|
||||
uint16_t Year;
|
||||
uint8_t Month;
|
||||
uint8_t Day;
|
||||
uint8_t Hour;
|
||||
uint8_t Minute;
|
||||
uint8_t Second;
|
||||
uint8_t Pad1;
|
||||
uint32_t Nanosecond;
|
||||
int16_t TimeZone;
|
||||
uint8_t Daylight;
|
||||
uint8_t Pad2;
|
||||
} EFI_TIME;
|
||||
|
||||
typedef struct {
|
||||
uint32_t Resolution;
|
||||
uint32_t Accuracy;
|
||||
|
39
src/boot/generate-hwids-section.py
Normal file
39
src/boot/generate-hwids-section.py
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# We import ukify.py, which is a template file. But only __version__ is
|
||||
# substituted, which we don't care about here. Having the .py suffix makes it
|
||||
# easier to import the file.
|
||||
sys.path.append(os.path.dirname(__file__) + '/../ukify')
|
||||
import ukify
|
||||
|
||||
BYTES_PER_LINE = 16
|
||||
|
||||
hwids = ukify.parse_hwid_dir(Path(sys.argv[1]))
|
||||
|
||||
print(
|
||||
"""/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
const uint8_t hwids_section_data[] = {
|
||||
""",
|
||||
end='',
|
||||
)
|
||||
|
||||
for i, b in enumerate(hwids):
|
||||
print(f'0x{b:02X}, ', end='')
|
||||
if i % BYTES_PER_LINE == BYTES_PER_LINE - 1:
|
||||
print('\n ', end='')
|
||||
elif i == len(hwids) - 1:
|
||||
print('')
|
||||
|
||||
print(
|
||||
"""};
|
||||
const size_t hwids_section_len =""",
|
||||
f'{len(hwids)};',
|
||||
)
|
8
src/boot/hwids/device1.json
Normal file
8
src/boot/hwids/device1.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Device 1",
|
||||
"compatible": "test,device-1",
|
||||
"hwids": [
|
||||
"2bdcafa9-727c-5e8b-b13b-236f1391c25a",
|
||||
"c87886da-8026-5149-8c95-6d2504c1b7f9"
|
||||
]
|
||||
}
|
8
src/boot/hwids/device2.json
Normal file
8
src/boot/hwids/device2.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Device 2",
|
||||
"compatible": "test,device-2",
|
||||
"hwids": [
|
||||
"6ff16153-a32f-548a-9cd7-3574a5d0caa4",
|
||||
"0afb4762-c5bb-5fba-887b-d56ce73ee793"
|
||||
]
|
||||
}
|
8
src/boot/hwids/device3.json
Normal file
8
src/boot/hwids/device3.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Device 3",
|
||||
"compatible": "test,device-3",
|
||||
"hwids": [
|
||||
"06b74502-e5d8-5ecd-a67a-e77654cf3b17",
|
||||
"a8d84e4e-23d9-5629-86da-a49d859b5cde"
|
||||
]
|
||||
}
|
@ -7,6 +7,7 @@ libefitest = static_library(
|
||||
'efitest',
|
||||
files(
|
||||
'bcd.c',
|
||||
'chid.c',
|
||||
'efi-string.c',
|
||||
),
|
||||
build_by_default : false,
|
||||
@ -25,6 +26,20 @@ efitest_base = {
|
||||
efi_test_template = test_template + efitest_base
|
||||
efi_fuzz_template = fuzz_template + efitest_base
|
||||
|
||||
generate_hwids_section_py = find_program('generate-hwids-section.py')
|
||||
|
||||
if conf.get('ENABLE_UKIFY') == 1
|
||||
test_hwids_section_c = custom_target(
|
||||
'test-hwids-section.c',
|
||||
input : ['hwids/device1.json', 'hwids/device2.json', 'hwids/device2.json'],
|
||||
output : 'test-hwids-section.c',
|
||||
command : [generate_hwids_section_py, meson.current_source_dir()/'hwids'],
|
||||
capture : true,
|
||||
build_by_default : want_tests != 'false')
|
||||
else
|
||||
test_hwids_section_c = ''
|
||||
endif
|
||||
|
||||
executables += [
|
||||
efi_test_template + {
|
||||
'sources' : files('test-bcd.c'),
|
||||
@ -35,6 +50,11 @@ executables += [
|
||||
'sources' : files('test-efi-string.c'),
|
||||
'conditions' : ['ENABLE_BOOTLOADER'],
|
||||
},
|
||||
efi_test_template + {
|
||||
'sources' : files('test-chid-match.c') +
|
||||
test_hwids_section_c,
|
||||
'conditions' : ['ENABLE_BOOTLOADER', 'ENABLE_UKIFY'],
|
||||
},
|
||||
efi_fuzz_template + {
|
||||
'sources' : files('fuzz-bcd.c'),
|
||||
},
|
||||
|
@ -259,3 +259,17 @@ void smbios_raw_info_populate(RawSmbiosInfo *ret_info) {
|
||||
ret_info->baseboard_product = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void smbios_raw_info_get_cached(RawSmbiosInfo *ret_info) {
|
||||
static RawSmbiosInfo info = {};
|
||||
static bool cached = false;
|
||||
|
||||
assert(ret_info);
|
||||
|
||||
if (!cached) {
|
||||
smbios_raw_info_populate(&info);
|
||||
cached = true;
|
||||
}
|
||||
|
||||
*ret_info = info;
|
||||
}
|
||||
|
@ -17,3 +17,4 @@ typedef struct RawSmbiosInfo {
|
||||
} RawSmbiosInfo;
|
||||
|
||||
void smbios_raw_info_populate(RawSmbiosInfo *ret_info);
|
||||
void smbios_raw_info_get_cached(RawSmbiosInfo *ret_info);
|
||||
|
@ -232,6 +232,17 @@ nothing:
|
||||
return false;
|
||||
}
|
||||
|
||||
static char16_t * strip_stub_cmdline(char16_t *cmdline, const char16_t *file_path) {
|
||||
if (file_path == NULL || strlen16(file_path) == 0) return cmdline;
|
||||
int ret = strcmp16(cmdline, file_path);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
} else if (ret > 0) {
|
||||
return cmdline + strlen16(file_path) + 1;
|
||||
}
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
static void process_arguments(
|
||||
EFI_HANDLE stub_image,
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
|
||||
@ -253,11 +264,19 @@ static void process_arguments(
|
||||
if (loaded_image->LoadOptionsSize < sizeof(char16_t) || ((const char16_t *) loaded_image->LoadOptions)[0] <= 0x1F)
|
||||
goto nothing;
|
||||
|
||||
/* Not running from EFI shell, use entire LoadOptions. Note that LoadOptions is a void*, so
|
||||
/* Not running from EFI shell. Note that LoadOptions is a void*, so
|
||||
* it could actually be anything! */
|
||||
char16_t *c = xstrndup16(loaded_image->LoadOptions, loaded_image->LoadOptionsSize / sizeof(char16_t));
|
||||
parse_profile_from_cmdline(&c, ret_profile);
|
||||
*ret_cmdline = mangle_stub_cmdline(c);
|
||||
|
||||
/* When LoadOptions starts with the stub path ignore it */
|
||||
_cleanup_free_ char16_t *p = NULL;
|
||||
if (loaded_image->FilePath && device_path_to_str(loaded_image->FilePath, &p) == EFI_SUCCESS) {
|
||||
*ret_cmdline = strip_stub_cmdline(*ret_cmdline, p);
|
||||
if (*ret_cmdline == NULL) *ret_cmdline = mfree(*ret_cmdline);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
77
src/boot/test-chid-match.c
Normal file
77
src/boot/test-chid-match.c
Normal file
@ -0,0 +1,77 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "chid.h"
|
||||
#include "smbios.h"
|
||||
#include "tests.h"
|
||||
|
||||
extern uint8_t hwids_section_data[];
|
||||
extern size_t hwids_section_len;
|
||||
|
||||
static const RawSmbiosInfo smbios_info[] = {
|
||||
{
|
||||
.manufacturer = "First Vendor",
|
||||
.product_name = "Device 1",
|
||||
.product_sku = "KD01",
|
||||
.family = "Laptop X",
|
||||
.baseboard_product = "FODM1",
|
||||
.baseboard_manufacturer = "First ODM",
|
||||
},
|
||||
{
|
||||
.manufacturer = "Second Vendor",
|
||||
.product_name = "Device 2",
|
||||
.product_sku = "KD02",
|
||||
.family = "Laptop 2",
|
||||
.baseboard_product = "SODM2",
|
||||
.baseboard_manufacturer = "Second ODM",
|
||||
},
|
||||
{
|
||||
.manufacturer = "First Vendor",
|
||||
.product_name = "Device 3",
|
||||
.product_sku = "KD03",
|
||||
.family = "Tablet Y",
|
||||
.baseboard_product = "FODM2",
|
||||
.baseboard_manufacturer = "First ODM",
|
||||
},
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *compatible;
|
||||
} results[] = {
|
||||
{ "Device 1", "test,device-1" },
|
||||
{ "Device 2", "test,device-2" },
|
||||
{ "Device 3", "test,device-3" },
|
||||
};
|
||||
|
||||
static RawSmbiosInfo current_info = {};
|
||||
|
||||
/* This is a dummy implementation for testing purposes */
|
||||
void smbios_raw_info_get_cached(RawSmbiosInfo *ret_info) {
|
||||
assert(ret_info);
|
||||
*ret_info = current_info;
|
||||
}
|
||||
|
||||
TEST(chid_match) {
|
||||
for (size_t i = 0; i < ELEMENTSOF(smbios_info); i++) {
|
||||
current_info = smbios_info[i];
|
||||
const Device *dev = NULL;
|
||||
/* Match and check */
|
||||
ASSERT_EQ(chid_match(hwids_section_data, hwids_section_len, &dev), EFI_SUCCESS);
|
||||
ASSERT_NOT_NULL(dev);
|
||||
ASSERT_STREQ(device_get_name(hwids_section_data, dev), results[i].name);
|
||||
ASSERT_STREQ(device_get_compatible(hwids_section_data, dev), results[i].compatible);
|
||||
}
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return EXIT_SUCCESS;
|
||||
#else
|
||||
return log_tests_skipped("cannot run CHID calculation on big-endian machine");
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
|
@ -3,11 +3,14 @@
|
||||
|
||||
#include "efi.h"
|
||||
#include "efi-string.h"
|
||||
#include "log.h"
|
||||
#include "memory-util-fundamental.h"
|
||||
#include "proto/file-io.h"
|
||||
#include "string-util-fundamental.h"
|
||||
|
||||
#if SD_BOOT
|
||||
|
||||
#include "log.h"
|
||||
#include "proto/file-io.h"
|
||||
|
||||
/* This is provided by the linker. */
|
||||
extern uint8_t __executable_start[];
|
||||
|
||||
@ -236,3 +239,11 @@ char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path);
|
||||
|
||||
#define bswap_16(x) __builtin_bswap16(x)
|
||||
#define bswap_32(x) __builtin_bswap32(x)
|
||||
|
||||
#else
|
||||
|
||||
#include "alloc-util.h"
|
||||
|
||||
#define xnew0(type, n) ASSERT_PTR(new0(type, n))
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "journal-file.h"
|
||||
@ -64,7 +65,6 @@ static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_tmp_ex, "s", PrivateTmp,
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_users_ex, "s", PrivateUsers, private_users_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_protect_control_groups_ex, "s", ProtectControlGroups, protect_control_groups_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_private_pids, "s", PrivatePIDs, private_pids_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_protect_hostname_ex, "s", ProtectHostname, protect_hostname_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
|
||||
@ -1084,6 +1084,20 @@ static int property_get_protect_hostname(
|
||||
return sd_bus_message_append_basic(reply, 'b', &b);
|
||||
}
|
||||
|
||||
static int property_get_protect_hostname_ex(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(userdata);
|
||||
|
||||
return sd_bus_message_append(reply, "(ss)", protect_hostname_to_string(c->protect_hostname), c->private_hostname);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -1259,7 +1273,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostname", "b", property_get_protect_hostname, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostnameEx", "s", property_get_protect_hostname_ex, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostnameEx", "(ss)", property_get_protect_hostname_ex, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MemoryKSM", "b", bus_property_get_tristate, offsetof(ExecContext, memory_ksm), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -1443,8 +1457,7 @@ static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
|
||||
return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : "");
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "");
|
||||
}
|
||||
|
||||
int bus_set_transient_exec_command(
|
||||
@ -2027,21 +2040,29 @@ int bus_exec_context_set_transient_property(
|
||||
}
|
||||
|
||||
if (streq(name, "ProtectHostnameEx")) {
|
||||
const char *s;
|
||||
ProtectHostname t;
|
||||
const char *s, *h = NULL;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
r = sd_bus_message_read(message, "(ss)", &s, &h);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
t = protect_hostname_from_string(s);
|
||||
if (t < 0)
|
||||
if (!isempty(h) && !hostname_is_valid(h, /* flags = */ 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname in %s setting: %s", name, h);
|
||||
|
||||
ProtectHostname t = protect_hostname_from_string(s);
|
||||
if (t < 0 || (t == PROTECT_HOSTNAME_NO && !isempty(h)))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s setting: %s", name, s);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->protect_hostname = t;
|
||||
(void) unit_write_settingf(u, flags, name, "ProtectHostname=%s",
|
||||
protect_hostname_to_string(c->protect_hostname));
|
||||
r = free_and_strdup(&c->private_hostname, empty_to_null(h));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) unit_write_settingf(u, flags, name, "ProtectHostname=%s%s%s",
|
||||
protect_hostname_to_string(c->protect_hostname),
|
||||
c->private_hostname ? ":" : "",
|
||||
strempty(c->private_hostname));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "bus-util.h"
|
||||
#include "chase.h"
|
||||
#include "confidential-virt.h"
|
||||
#include "data-fd-util.h"
|
||||
#include "dbus-cgroup.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-job.h"
|
||||
@ -33,6 +32,7 @@
|
||||
#include "locale-util.h"
|
||||
#include "log.h"
|
||||
#include "manager-dump.h"
|
||||
#include "memfd-util.h"
|
||||
#include "os-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@ -48,10 +48,6 @@
|
||||
#include "virt.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
/* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state
|
||||
* there, and if we can't we'll fail badly. */
|
||||
#define RELOAD_DISK_SPACE_MIN (UINT64_C(16) * UINT64_C(1024) * UINT64_C(1024))
|
||||
|
||||
static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
|
||||
return (runtime ? UNIT_FILE_RUNTIME : 0) |
|
||||
(force ? UNIT_FILE_FORCE : 0);
|
||||
@ -1447,7 +1443,7 @@ static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *er
|
||||
static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
fd = acquire_data_fd(dump);
|
||||
fd = memfd_new_and_seal_string("dump", dump);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -1485,73 +1481,6 @@ static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bu
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
|
||||
}
|
||||
|
||||
static int get_run_space(uint64_t *ret, sd_bus_error *error) {
|
||||
struct statvfs svfs;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (statvfs("/run/systemd", &svfs) < 0)
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
|
||||
|
||||
*ret = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_run_space(const char *message, sd_bus_error *error) {
|
||||
uint64_t available = 0; /* unnecessary, but used to trick out gcc's incorrect maybe-uninitialized warning */
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
r = get_run_space(&available, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (available < RELOAD_DISK_SPACE_MIN)
|
||||
return sd_bus_error_setf(error,
|
||||
BUS_ERROR_DISK_FULL,
|
||||
"%s, not enough space available on /run/systemd/. "
|
||||
"Currently, %s are free, but a safety buffer of %s is enforced.",
|
||||
message,
|
||||
FORMAT_BYTES(available),
|
||||
FORMAT_BYTES(RELOAD_DISK_SPACE_MIN));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int verify_run_space_and_log(const char *message) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
r = verify_run_space(message, &error);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "%s", bus_error_message(&error, r));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_run_space_permissive(const char *message, sd_bus_error *error) {
|
||||
uint64_t available = 0; /* unnecessary, but used to trick out gcc's incorrect maybe-uninitialized warning */
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
r = get_run_space(&available, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (available < RELOAD_DISK_SPACE_MIN)
|
||||
log_warning("Dangerously low amount of free space on /run/systemd/, %s.\n"
|
||||
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
|
||||
message,
|
||||
FORMAT_BYTES(available),
|
||||
FORMAT_BYTES(RELOAD_DISK_SPACE_MIN));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void log_caller(sd_bus_message *message, Manager *manager, const char *method) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
@ -1585,10 +1514,6 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
|
||||
|
||||
assert(message);
|
||||
|
||||
r = verify_run_space("Refusing to reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mac_selinux_access_check(message, "reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1631,10 +1556,6 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
|
||||
assert(message);
|
||||
|
||||
r = verify_run_space("Refusing to reexecute", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mac_selinux_access_check(message, "reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1718,10 +1639,6 @@ static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
|
||||
"Soft reboot is only supported by system manager.");
|
||||
|
||||
r = verify_run_space_permissive("soft reboot may fail", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mac_selinux_access_check(message, "reboot", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1826,10 +1743,6 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
|
||||
"Root switching is only supported by system manager.");
|
||||
|
||||
r = verify_run_space_permissive("root switching may fail", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mac_selinux_access_check(message, "reboot", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -131,10 +131,16 @@ static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_e
|
||||
assert(message);
|
||||
assert_se(bus = sd_bus_message_get_bus(message));
|
||||
|
||||
if (bus == m->api_bus)
|
||||
if (bus == m->api_bus) {
|
||||
log_notice("Got disconnect on API bus.");
|
||||
bus_done_api(m);
|
||||
if (bus == m->system_bus)
|
||||
}
|
||||
if (bus == m->system_bus) {
|
||||
/* If we are the system manager, this is already logged by the API bus. */
|
||||
if (!MANAGER_IS_SYSTEM(m))
|
||||
log_notice("Got disconnect on system bus.");
|
||||
bus_done_system(m);
|
||||
}
|
||||
|
||||
if (set_remove(m->private_buses, bus)) {
|
||||
log_debug("Got disconnect on private connection.");
|
||||
|
@ -85,7 +85,9 @@ static int device_set_sysfs(Device *d, const char *sysfs) {
|
||||
Unit *u = UNIT(ASSERT_PTR(d));
|
||||
int r;
|
||||
|
||||
if (streq_ptr(d->sysfs, sysfs))
|
||||
assert(sysfs);
|
||||
|
||||
if (path_equal(d->sysfs, sysfs))
|
||||
return 0;
|
||||
|
||||
Hashmap **devices = &u->manager->devices_by_sysfs;
|
||||
@ -332,6 +334,20 @@ static void device_catchup(Unit *u) {
|
||||
Device *d = ASSERT_PTR(DEVICE(u));
|
||||
|
||||
/* Second, let's update the state with the enumerated state */
|
||||
|
||||
/* If Device.found (set from Device.deserialized_found) does not have DEVICE_FOUND_UDEV, and the
|
||||
* device has not been processed by udevd while enumeration, it indicates the unit was never active
|
||||
* before reexecution, hence we can safely drop the flag from Device.enumerated_found. The device
|
||||
* will be set up later when udev finishes processing (see also comment in
|
||||
* device_setup_devlink_unit_one()).
|
||||
*
|
||||
* NB: 💣💣💣 If Device.found already contains udev, i.e. the unit was fully ready before
|
||||
* reexecution, do not unset the flag. Otherwise, e.g. if systemd-udev-trigger.service is started
|
||||
* just before reexec, reload, and so on, devices being reprocessed (carrying ID_PROCESSING=1
|
||||
* property) on enumeration and will enter dead state. See issue #35329. */
|
||||
if (!FLAGS_SET(d->found, DEVICE_FOUND_UDEV) && !d->processed)
|
||||
d->enumerated_found &= ~DEVICE_FOUND_UDEV;
|
||||
|
||||
device_update_found_one(d, d->enumerated_found, _DEVICE_FOUND_MASK);
|
||||
}
|
||||
|
||||
@ -777,8 +793,16 @@ static int device_setup_devlink_unit_one(Manager *m, const char *devlink, Set **
|
||||
assert(ready_units);
|
||||
assert(not_ready_units);
|
||||
|
||||
if (sd_device_new_from_devname(&dev, devlink) >= 0 && device_is_ready(dev))
|
||||
if (sd_device_new_from_devname(&dev, devlink) >= 0 && device_is_ready(dev)) {
|
||||
if (MANAGER_IS_RUNNING(m) && device_is_processed(dev) <= 0)
|
||||
/* The device is being processed by udevd. We will receive relevant uevent for the
|
||||
* device later when completed. Let's ignore the device now. */
|
||||
return 0;
|
||||
|
||||
/* Note, even if the device is being processed by udevd, setup the unit on enumerate.
|
||||
* See also the comments in device_catchup(). */
|
||||
return device_setup_unit(m, dev, devlink, /* main = */ false, ready_units);
|
||||
}
|
||||
|
||||
/* the devlink is already removed or not ready */
|
||||
if (device_by_path(m, devlink, &u) < 0)
|
||||
@ -874,14 +898,15 @@ static int device_setup_extra_units(Manager *m, sd_device *dev, Set **ready_unit
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set **not_ready_units) {
|
||||
static int device_setup_units(Manager *m, sd_device *dev, Set **ret_ready_units, Set **ret_not_ready_units) {
|
||||
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
|
||||
const char *syspath, *devname = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(dev);
|
||||
assert(ready_units);
|
||||
assert(not_ready_units);
|
||||
assert(ret_ready_units);
|
||||
assert(ret_not_ready_units);
|
||||
|
||||
r = sd_device_get_syspath(dev, &syspath);
|
||||
if (r < 0)
|
||||
@ -901,13 +926,13 @@ static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set
|
||||
/* Add the main unit named after the syspath. If this one fails, don't bother with the rest,
|
||||
* as this one shall be the main device unit the others just follow. (Compare with how
|
||||
* device_following() is implemented, see below, which looks for the sysfs device.) */
|
||||
r = device_setup_unit(m, dev, syspath, /* main = */ true, ready_units);
|
||||
r = device_setup_unit(m, dev, syspath, /* main = */ true, &ready_units);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Add an additional unit for the device node */
|
||||
if (sd_device_get_devname(dev, &devname) >= 0)
|
||||
(void) device_setup_unit(m, dev, devname, /* main = */ false, ready_units);
|
||||
(void) device_setup_unit(m, dev, devname, /* main = */ false, &ready_units);
|
||||
|
||||
} else {
|
||||
Unit *u;
|
||||
@ -915,28 +940,30 @@ static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set
|
||||
/* If the device exists but not ready, then save the units and unset udev bits later. */
|
||||
|
||||
if (device_by_path(m, syspath, &u) >= 0) {
|
||||
r = set_ensure_put(not_ready_units, NULL, DEVICE(u));
|
||||
r = set_ensure_put(¬_ready_units, NULL, DEVICE(u));
|
||||
if (r < 0)
|
||||
log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m");
|
||||
}
|
||||
|
||||
if (sd_device_get_devname(dev, &devname) >= 0 &&
|
||||
device_by_path(m, devname, &u) >= 0) {
|
||||
r = set_ensure_put(not_ready_units, NULL, DEVICE(u));
|
||||
r = set_ensure_put(¬_ready_units, NULL, DEVICE(u));
|
||||
if (r < 0)
|
||||
log_unit_debug_errno(u, r, "Failed to store unit, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
/* Next, add/update additional .device units point to aliases and symlinks. */
|
||||
(void) device_setup_extra_units(m, dev, ready_units, not_ready_units);
|
||||
(void) device_setup_extra_units(m, dev, &ready_units, ¬_ready_units);
|
||||
|
||||
/* Safety check: no unit should be in ready_units and not_ready_units simultaneously. */
|
||||
Unit *u;
|
||||
SET_FOREACH(u, *not_ready_units)
|
||||
if (set_remove(*ready_units, u))
|
||||
SET_FOREACH(u, not_ready_units)
|
||||
if (set_remove(ready_units, u))
|
||||
log_unit_error(u, "Cannot activate and deactivate the unit simultaneously. Deactivating.");
|
||||
|
||||
*ret_ready_units = TAKE_PTR(ready_units);
|
||||
*ret_not_ready_units = TAKE_PTR(not_ready_units);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1046,13 +1073,32 @@ static void device_enumerate(Manager *m) {
|
||||
|
||||
FOREACH_DEVICE(e, dev) {
|
||||
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
|
||||
const char *syspath;
|
||||
bool processed;
|
||||
Device *d;
|
||||
|
||||
r = sd_device_get_syspath(dev, &syspath);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to get syspath of enumerated device, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
r = device_is_processed(dev);
|
||||
if (r < 0)
|
||||
log_device_debug_errno(dev, r, "Failed to check if device is processed by udevd, assuming not: %m");
|
||||
processed = r > 0;
|
||||
|
||||
if (device_setup_units(m, dev, &ready_units, ¬_ready_units) < 0)
|
||||
continue;
|
||||
|
||||
SET_FOREACH(d, ready_units)
|
||||
SET_FOREACH(d, ready_units) {
|
||||
device_update_found_one(d, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
|
||||
|
||||
/* Why we need to check the syspath here? Because the device unit may be generated by
|
||||
* a devlink, and the syspath may be different from the one of the original device. */
|
||||
if (path_equal(d->sysfs, syspath))
|
||||
d->processed = processed;
|
||||
}
|
||||
SET_FOREACH(d, not_ready_units)
|
||||
device_update_found_one(d, DEVICE_NOT_FOUND, DEVICE_FOUND_UDEV);
|
||||
}
|
||||
@ -1097,7 +1143,6 @@ static void device_remove_old_on_move(Manager *m, sd_device *dev) {
|
||||
}
|
||||
|
||||
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
|
||||
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
sd_device_action_t action;
|
||||
const char *sysfs;
|
||||
@ -1150,6 +1195,7 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
|
||||
* change events */
|
||||
ready = device_is_ready(dev);
|
||||
|
||||
_cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL;
|
||||
(void) device_setup_units(m, dev, &ready_units, ¬_ready_units);
|
||||
|
||||
if (action == SD_DEVICE_REMOVE) {
|
||||
|
@ -29,7 +29,9 @@ struct Device {
|
||||
|
||||
DeviceState state, deserialized_state;
|
||||
DeviceFound found, deserialized_found, enumerated_found;
|
||||
|
||||
bool processed; /* Whether udevd has done processing the device, i.e. the device has database and
|
||||
* ID_PROCESSING=1 udev property is not set. This is used only by enumeration and
|
||||
* subsequent catchup process. */
|
||||
bool bind_mounts;
|
||||
|
||||
/* The SYSTEMD_WANTS udev property for this device the last time we saw it */
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "chattr-util.h"
|
||||
#include "chown-recursive.h"
|
||||
#include "copy.h"
|
||||
#include "data-fd-util.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "exec-credential.h"
|
||||
@ -40,9 +39,11 @@
|
||||
#include "exit-status.h"
|
||||
#include "fd-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "io-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "journal-send.h"
|
||||
#include "memfd-util.h"
|
||||
#include "missing_ioprio.h"
|
||||
#include "missing_prctl.h"
|
||||
#include "missing_sched.h"
|
||||
@ -405,7 +406,7 @@ static int setup_input(
|
||||
case EXEC_INPUT_DATA: {
|
||||
int fd;
|
||||
|
||||
fd = acquire_data_fd_full(context->stdin_data, context->stdin_data_size, /* flags = */ 0);
|
||||
fd = memfd_new_and_seal("exec-input", context->stdin_data, context->stdin_data_size);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -1406,7 +1407,7 @@ static bool skip_seccomp_unavailable(const ExecContext *c, const ExecParameters
|
||||
return true;
|
||||
}
|
||||
|
||||
static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, bool needs_ambient_hack) {
|
||||
static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p) {
|
||||
uint32_t negative_action, default_action, action;
|
||||
int r;
|
||||
|
||||
@ -1429,12 +1430,6 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, b
|
||||
action = negative_action;
|
||||
}
|
||||
|
||||
if (needs_ambient_hack) {
|
||||
r = seccomp_filter_set_add(c->syscall_filter, c->syscall_allow_list, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Sending over exec_fd or handoff_timestamp_fd requires write() syscall. */
|
||||
if (p->exec_fd >= 0 || p->handoff_timestamp_fd >= 0) {
|
||||
r = seccomp_filter_set_add_by_name(c->syscall_filter, c->syscall_allow_list, "write");
|
||||
@ -1698,6 +1693,8 @@ static int apply_restrict_filesystems(const ExecContext *c, const ExecParameters
|
||||
#endif
|
||||
|
||||
static int apply_protect_hostname(const ExecContext *c, const ExecParameters *p, int *ret_exit_status) {
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(p);
|
||||
|
||||
@ -1708,27 +1705,27 @@ static int apply_protect_hostname(const ExecContext *c, const ExecParameters *p,
|
||||
if (unshare(CLONE_NEWUTS) < 0) {
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) {
|
||||
*ret_exit_status = EXIT_NAMESPACE;
|
||||
return log_exec_error_errno(c,
|
||||
p,
|
||||
errno,
|
||||
"Failed to set up UTS namespacing: %m");
|
||||
return log_exec_error_errno(c, p, errno, "Failed to set up UTS namespacing: %m");
|
||||
}
|
||||
|
||||
log_exec_warning(c,
|
||||
p,
|
||||
"ProtectHostname=yes is configured, but UTS namespace setup is "
|
||||
"prohibited (container manager?), ignoring namespace setup.");
|
||||
log_exec_warning(c, p,
|
||||
"ProtectHostname=%s is configured, but UTS namespace setup is prohibited (container manager?), ignoring namespace setup.",
|
||||
protect_hostname_to_string(c->protect_hostname));
|
||||
|
||||
} else if (c->private_hostname) {
|
||||
r = sethostname_idempotent(c->private_hostname);
|
||||
if (r < 0) {
|
||||
*ret_exit_status = EXIT_NAMESPACE;
|
||||
return log_exec_error_errno(c, p, r, "Failed to set private hostname '%s': %m", c->private_hostname);
|
||||
}
|
||||
}
|
||||
} else
|
||||
log_exec_warning(c,
|
||||
p,
|
||||
"ProtectHostname=yes is configured, but the kernel does not "
|
||||
"support UTS namespaces, ignoring namespace setup.");
|
||||
log_exec_warning(c, p,
|
||||
"ProtectHostname=%s is configured, but the kernel does not support UTS namespaces, ignoring namespace setup.",
|
||||
protect_hostname_to_string(c->protect_hostname));
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
if (c->protect_hostname == PROTECT_HOSTNAME_YES) {
|
||||
int r;
|
||||
|
||||
if (skip_seccomp_unavailable(c, p, "ProtectHostname="))
|
||||
return 0;
|
||||
|
||||
@ -4294,8 +4291,7 @@ int exec_invoke(
|
||||
bool userns_set_up = false;
|
||||
bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */
|
||||
needs_setuid, /* Do we need to do the actual setresuid()/setresgid() calls? */
|
||||
needs_mount_namespace, /* Do we need to set up a mount namespace for this kernel? */
|
||||
needs_ambient_hack; /* Do we need to apply the ambient capabilities hack? */
|
||||
needs_mount_namespace; /* Do we need to set up a mount namespace for this kernel? */
|
||||
bool keep_seccomp_privileges = false;
|
||||
bool has_cap_sys_admin = false;
|
||||
#if HAVE_SELINUX
|
||||
@ -4936,17 +4932,9 @@ int exec_invoke(
|
||||
return log_exec_error_errno(context, params, r, "Failed to set up kernel keyring: %m");
|
||||
}
|
||||
|
||||
/* We need the ambient capability hack, if the caller asked us to apply it and the command is marked
|
||||
* for it, and the kernel doesn't actually support ambient caps. */
|
||||
needs_ambient_hack = (params->flags & EXEC_APPLY_SANDBOXING) && (command->flags & EXEC_COMMAND_AMBIENT_MAGIC) && !ambient_capabilities_supported();
|
||||
|
||||
/* We need setresuid() if the caller asked us to apply sandboxing and the command isn't explicitly
|
||||
* excepted from either whole sandboxing or just setresuid() itself, and the ambient hack is not
|
||||
* desired. */
|
||||
if (needs_ambient_hack)
|
||||
needs_setuid = false;
|
||||
else
|
||||
needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
|
||||
* excepted from either whole sandboxing or just setresuid() itself. */
|
||||
needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
|
||||
|
||||
uint64_t capability_ambient_set = context->capability_ambient_set;
|
||||
|
||||
@ -4993,20 +4981,17 @@ int exec_invoke(
|
||||
return log_exec_error_errno(context, params, r, "Failed to set up PAM session: %m");
|
||||
}
|
||||
|
||||
if (ambient_capabilities_supported()) {
|
||||
uint64_t ambient_after_pam;
|
||||
|
||||
/* PAM modules might have set some ambient caps. Query them here and merge them into
|
||||
* the caps we want to set in the end, so that we don't end up unsetting them. */
|
||||
r = capability_get_ambient(&ambient_after_pam);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
return log_exec_error_errno(context, params, r, "Failed to query ambient caps: %m");
|
||||
}
|
||||
|
||||
capability_ambient_set |= ambient_after_pam;
|
||||
/* PAM modules might have set some ambient caps. Query them here and merge them into
|
||||
* the caps we want to set in the end, so that we don't end up unsetting them. */
|
||||
uint64_t ambient_after_pam;
|
||||
r = capability_get_ambient(&ambient_after_pam);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
return log_exec_error_errno(context, params, r, "Failed to query ambient caps: %m");
|
||||
}
|
||||
|
||||
capability_ambient_set |= ambient_after_pam;
|
||||
|
||||
ngids_after_pam = getgroups_alloc(&gids_after_pam);
|
||||
if (ngids_after_pam < 0) {
|
||||
*exit_status = EXIT_GROUP;
|
||||
@ -5309,13 +5294,6 @@ int exec_invoke(
|
||||
#endif
|
||||
|
||||
bset = context->capability_bounding_set;
|
||||
/* If the ambient caps hack is enabled (which means the kernel can't do them, and the user asked for
|
||||
* our magic fallback), then let's add some extra caps, so that the service can drop privs of its own,
|
||||
* instead of us doing that */
|
||||
if (needs_ambient_hack)
|
||||
bset |= (UINT64_C(1) << CAP_SETPCAP) |
|
||||
(UINT64_C(1) << CAP_SETUID) |
|
||||
(UINT64_C(1) << CAP_SETGID);
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
/* If the service has any form of a seccomp filter and it allows dropping privileges, we'll
|
||||
@ -5358,7 +5336,7 @@ int exec_invoke(
|
||||
*
|
||||
* The requested ambient capabilities are raised in the inheritable set if the second
|
||||
* argument is true. */
|
||||
if (!needs_ambient_hack && capability_ambient_set != 0) {
|
||||
if (capability_ambient_set != 0) {
|
||||
r = capability_ambient_set_apply(capability_ambient_set, /* also_inherit= */ true);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
@ -5402,7 +5380,7 @@ int exec_invoke(
|
||||
}
|
||||
}
|
||||
|
||||
if (!needs_ambient_hack && capability_ambient_set != 0) {
|
||||
if (capability_ambient_set != 0) {
|
||||
|
||||
/* Raise the ambient capabilities after user change. */
|
||||
r = capability_ambient_set_apply(capability_ambient_set, /* also_inherit= */ false);
|
||||
@ -5588,7 +5566,7 @@ int exec_invoke(
|
||||
#if HAVE_SECCOMP
|
||||
/* This really should remain as close to the execve() as possible, to make sure our own code is affected
|
||||
* by the filter as little as possible. */
|
||||
r = apply_syscall_filter(context, params, needs_ambient_hack);
|
||||
r = apply_syscall_filter(context, params);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_SECCOMP;
|
||||
return log_exec_error_errno(context, params, r, "Failed to apply system call filters: %m");
|
||||
|
@ -1982,6 +1982,10 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_item(f, "exec-context-private-hostname", c->private_hostname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_item(f, "exec-context-protect-proc", protect_proc_to_string(c->protect_proc));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2884,6 +2888,10 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
c->protect_hostname = protect_hostname_from_string(val);
|
||||
if (c->protect_hostname < 0)
|
||||
return -EINVAL;
|
||||
} else if ((val = startswith(l, "exec-context-private-hostname="))) {
|
||||
r = free_and_strdup(&c->private_hostname, val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-context-protect-proc="))) {
|
||||
c->protect_proc = protect_proc_from_string(val);
|
||||
if (c->protect_proc < 0)
|
||||
|
@ -516,8 +516,9 @@ int exec_spawn(
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(unit, r, "Failed to serialize parameters: %m");
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_unit_error_errno(unit, errno, "Failed to reseek on serialization stream: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(unit, r, "Failed to finish serialization stream: %m");
|
||||
|
||||
r = fd_cloexec(fileno(f), false);
|
||||
if (r < 0)
|
||||
@ -723,6 +724,8 @@ void exec_context_done(ExecContext *c) {
|
||||
c->root_image_policy = image_policy_free(c->root_image_policy);
|
||||
c->mount_image_policy = image_policy_free(c->mount_image_policy);
|
||||
c->extension_image_policy = image_policy_free(c->extension_image_policy);
|
||||
|
||||
c->private_hostname = mfree(c->private_hostname);
|
||||
}
|
||||
|
||||
int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) {
|
||||
@ -1066,7 +1069,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
"%sRestrictRealtime: %s\n"
|
||||
"%sRestrictSUIDSGID: %s\n"
|
||||
"%sKeyringMode: %s\n"
|
||||
"%sProtectHostname: %s\n"
|
||||
"%sProtectHostname: %s%s%s\n"
|
||||
"%sProtectProc: %s\n"
|
||||
"%sProcSubset: %s\n",
|
||||
prefix, c->umask,
|
||||
@ -1093,7 +1096,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
prefix, yes_no(c->restrict_realtime),
|
||||
prefix, yes_no(c->restrict_suid_sgid),
|
||||
prefix, exec_keyring_mode_to_string(c->keyring_mode),
|
||||
prefix, protect_hostname_to_string(c->protect_hostname),
|
||||
prefix, protect_hostname_to_string(c->protect_hostname), c->private_hostname ? ":" : "", strempty(c->private_hostname),
|
||||
prefix, protect_proc_to_string(c->protect_proc),
|
||||
prefix, proc_subset_to_string(c->proc_subset));
|
||||
|
||||
|
@ -337,6 +337,7 @@ struct ExecContext {
|
||||
ProtectHome protect_home;
|
||||
PrivatePIDs private_pids;
|
||||
ProtectHostname protect_hostname;
|
||||
char *private_hostname;
|
||||
|
||||
bool dynamic_user;
|
||||
bool remove_ipc;
|
||||
|
@ -180,7 +180,7 @@
|
||||
{% else %}
|
||||
{{type}}.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
{% endif %}
|
||||
{{type}}.ProtectHostname, config_parse_protect_hostname, 0, offsetof({{type}}, exec_context.protect_hostname)
|
||||
{{type}}.ProtectHostname, config_parse_protect_hostname, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.MemoryKSM, config_parse_tristate, 0, offsetof({{type}}, exec_context.memory_ksm)
|
||||
{%- endmacro -%}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "fstab-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "ioprio-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
@ -141,7 +142,6 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMo
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_hostname, protect_hostname, ProtectHostname);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType);
|
||||
@ -933,7 +933,7 @@ int config_parse_exec(
|
||||
}
|
||||
|
||||
const char *f = firstword;
|
||||
bool ignore, separate_argv0 = false;
|
||||
bool ignore, separate_argv0 = false, ambient_hack = false;
|
||||
ExecCommandFlags flags = 0;
|
||||
|
||||
for (;; f++) {
|
||||
@ -944,28 +944,29 @@ int config_parse_exec(
|
||||
* ":": Disable environment variable substitution
|
||||
* "+": Run with full privileges and no sandboxing
|
||||
* "!": Apply sandboxing except for user/group credentials
|
||||
* "!!": Apply user/group credentials if the kernel supports ambient capabilities -
|
||||
* if it doesn't we don't apply the credentials themselves, but do apply
|
||||
* most other sandboxing, with some special exceptions for changing UID.
|
||||
*
|
||||
* The idea is that '!!' may be used to write services that can take benefit of
|
||||
* systemd's UID/GID dropping if the kernel supports ambient creds, but provide
|
||||
* an automatic fallback to privilege dropping within the daemon if the kernel
|
||||
* does not offer that. */
|
||||
*/
|
||||
|
||||
if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE))
|
||||
if (*f == '-' && !FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE))
|
||||
flags |= EXEC_COMMAND_IGNORE_FAILURE;
|
||||
else if (*f == '@' && !separate_argv0)
|
||||
separate_argv0 = true;
|
||||
else if (*f == ':' && !(flags & EXEC_COMMAND_NO_ENV_EXPAND))
|
||||
else if (*f == ':' && !FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND))
|
||||
flags |= EXEC_COMMAND_NO_ENV_EXPAND;
|
||||
else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
|
||||
else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
|
||||
flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
|
||||
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
|
||||
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
|
||||
flags |= EXEC_COMMAND_NO_SETUID;
|
||||
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))) {
|
||||
else if (*f == '!' && !FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) && !ambient_hack) {
|
||||
/* Compatibility with the old !! ambient caps hack (removed in v258). Since
|
||||
* we don't support that anymore and !! was a noop on non-supporting systems,
|
||||
* we'll just turn off the EXEC_COMMAND_NO_SETUID flag again and be done with
|
||||
* it. */
|
||||
flags &= ~EXEC_COMMAND_NO_SETUID;
|
||||
flags |= EXEC_COMMAND_AMBIENT_MAGIC;
|
||||
ambient_hack = true;
|
||||
|
||||
log_syntax(unit, LOG_NOTICE, filename, line, 0,
|
||||
"The !! modifier for %s= lines is no longer supported and is now ignored. "
|
||||
"Please update your unit files and remove the modifier.", lvalue);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@ -6743,3 +6744,53 @@ int config_parse_cgroup_nft_set(
|
||||
|
||||
return config_parse_nft_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &c->nft_set_context, u);
|
||||
}
|
||||
|
||||
int config_parse_protect_hostname(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *h = NULL, *p = NULL;
|
||||
int r;
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
c->protect_hostname = PROTECT_HOSTNAME_NO;
|
||||
c->private_hostname = mfree(c->private_hostname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *colon = strchr(rvalue, ':');
|
||||
if (colon) {
|
||||
r = unit_full_printf_full(u, colon + 1, HOST_NAME_MAX, &h);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to resolve unit specifiers in '%s', ignoring: %m", colon + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hostname_is_valid(h, /* flags = */ 0))
|
||||
return log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Invalid hostname is specified to %s=, ignoring: %s", lvalue, h);
|
||||
|
||||
p = strndup(rvalue, colon - rvalue);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
ProtectHostname t = protect_hostname_from_string(p ?: rvalue);
|
||||
if (t < 0 || (t == PROTECT_HOSTNAME_NO && h))
|
||||
return log_syntax_parse_error(unit, filename, line, 0, lvalue, rvalue);
|
||||
|
||||
c->protect_hostname = t;
|
||||
free_and_replace(c->private_hostname, h);
|
||||
return 1;
|
||||
}
|
||||
|
@ -34,12 +34,12 @@
|
||||
#include "clock-warp.h"
|
||||
#include "conf-parser.h"
|
||||
#include "confidential-virt.h"
|
||||
#include "constants.h"
|
||||
#include "copy.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "crash-handler.h"
|
||||
#include "dbus-manager.h"
|
||||
#include "dbus.h"
|
||||
#include "constants.h"
|
||||
#include "dev-setup.h"
|
||||
#include "efi-random.h"
|
||||
#include "efivars.h"
|
||||
@ -87,6 +87,7 @@
|
||||
#include "seccomp-util.h"
|
||||
#include "selinux-setup.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "signal-util.h"
|
||||
#include "smack-setup.h"
|
||||
#include "special.h"
|
||||
@ -1233,14 +1234,14 @@ static int prepare_reexecute(
|
||||
assert(ret_f);
|
||||
assert(ret_fds);
|
||||
|
||||
r = manager_open_serialization(m, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create serialization file: %m");
|
||||
|
||||
/* Make sure nothing is really destructed when we shut down */
|
||||
m->n_reloading++;
|
||||
bus_manager_send_reloading(m, true);
|
||||
|
||||
r = manager_open_serialization(m, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create serialization file: %m");
|
||||
|
||||
fds = fdset_new();
|
||||
if (!fds)
|
||||
return log_oom();
|
||||
@ -1249,8 +1250,9 @@ static int prepare_reexecute(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to rewind serialization fd: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization file: %m");
|
||||
|
||||
r = fd_cloexec(fileno(f), false);
|
||||
if (r < 0)
|
||||
|
@ -77,6 +77,9 @@ static void manager_dump_header(Manager *m, FILE *f, const char *prefix) {
|
||||
timestamp_is_set(t->realtime) ? FORMAT_TIMESTAMP(t->realtime) :
|
||||
FORMAT_TIMESPAN(t->monotonic, 1));
|
||||
}
|
||||
|
||||
for (const char *n = sd_bus_track_first(m->subscribed); n; n = sd_bus_track_next(m->subscribed))
|
||||
fprintf(f, "%sSubscribed: %s\n", strempty(prefix), n);
|
||||
}
|
||||
|
||||
void manager_dump(Manager *m, FILE *f, char **patterns, const char *prefix) {
|
||||
|
@ -186,10 +186,6 @@ int manager_serialize(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to flush serialization: %m");
|
||||
|
||||
r = bus_fdset_add_all(m, fds);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "rlimit-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "special.h"
|
||||
@ -3123,9 +3124,6 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
|
||||
case SIGTERM:
|
||||
if (MANAGER_IS_SYSTEM(m)) {
|
||||
/* This is for compatibility with the original sysvinit */
|
||||
if (verify_run_space_and_log("Refusing to reexecute") < 0)
|
||||
break;
|
||||
|
||||
m->objective = MANAGER_REEXECUTE;
|
||||
break;
|
||||
}
|
||||
@ -3179,9 +3177,6 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
|
||||
}
|
||||
|
||||
case SIGHUP:
|
||||
if (verify_run_space_and_log("Refusing to reload") < 0)
|
||||
break;
|
||||
|
||||
m->objective = MANAGER_RELOAD;
|
||||
break;
|
||||
|
||||
@ -3762,8 +3757,9 @@ int manager_reload(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to seek to beginning of serialization: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization: %m");
|
||||
|
||||
/* 💀 This is the point of no return, from here on there is no way back. 💀 */
|
||||
reloading = NULL;
|
||||
|
@ -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]);
|
||||
|
@ -1,10 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#if !SD_BOOT
|
||||
# include <stdbool.h>
|
||||
# include <stdint.h>
|
||||
# include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Matches EFI API definition of the same structure for userspace */
|
||||
typedef struct {
|
||||
@ -14,9 +11,13 @@ typedef struct {
|
||||
uint8_t Data4[8];
|
||||
} EFI_GUID;
|
||||
|
||||
#if !SD_BOOT
|
||||
# include <stdbool.h>
|
||||
# include <string.h>
|
||||
static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
|
||||
return memcmp(a, b, sizeof(EFI_GUID)) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID SignatureOwner;
|
||||
@ -66,6 +67,9 @@ typedef struct {
|
||||
#define GUID_DEF(d1, d2, d3, d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8) \
|
||||
{ d1, d2, d3, { d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7, d4_8 } }
|
||||
|
||||
/* Creates a EFI_GUID pointer suitable for EFI APIs. Use of const allows the compiler to merge multiple
|
||||
* uses (although, currently compilers do that regardless). Most EFI APIs declare their EFI_GUID input
|
||||
* as non-const, but almost all of them are in fact const. */
|
||||
#define MAKE_GUID_PTR(name) ((EFI_GUID *) &(const EFI_GUID) name##_GUID)
|
||||
|
||||
#define EFI_GLOBAL_VARIABLE \
|
||||
@ -77,5 +81,3 @@ typedef struct {
|
||||
GUID_DEF(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
|
||||
#define EFI_CERT_TYPE_PKCS7_GUID \
|
||||
GUID_DEF(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
|
||||
|
||||
#endif
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "build-path.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-locator.h"
|
||||
#include "data-fd-util.h"
|
||||
#include "env-util.h"
|
||||
#include "errno-list.h"
|
||||
#include "errno-util.h"
|
||||
@ -1266,13 +1265,13 @@ static int home_start_work(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
stdin_fd = acquire_data_fd(formatted);
|
||||
stdin_fd = memfd_new_and_seal_string("request", formatted);
|
||||
if (stdin_fd < 0)
|
||||
return stdin_fd;
|
||||
|
||||
log_debug("Sending to worker: %s", formatted);
|
||||
|
||||
stdout_fd = memfd_create_wrapper("homework-stdout", MFD_CLOEXEC | MFD_NOEXEC_SEAL);
|
||||
stdout_fd = memfd_new("homework-stdout");
|
||||
if (stdout_fd < 0)
|
||||
return stdout_fd;
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <linux/fs.h>
|
||||
#endif
|
||||
|
||||
#include "data-fd-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -13,6 +12,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "homework-cifs.h"
|
||||
#include "homework-mount.h"
|
||||
#include "memfd-util.h"
|
||||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
#include "process-util.h"
|
||||
@ -76,7 +76,7 @@ int home_setup_cifs(
|
||||
pid_t mount_pid;
|
||||
int exit_status;
|
||||
|
||||
passwd_fd = acquire_data_fd(*pw);
|
||||
passwd_fd = memfd_new_and_seal_string("cifspw", *pw);
|
||||
if (passwd_fd < 0)
|
||||
return log_error_errno(passwd_fd, "Failed to create data FD for password: %m");
|
||||
|
||||
|
@ -24,7 +24,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
_cleanup_(unlink_and_freep) char *name = NULL;
|
||||
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||
_cleanup_(journal_remote_server_destroy) RemoteServer s = {};
|
||||
void *mem;
|
||||
int fdin, r;
|
||||
|
||||
if (outside_size_range(size, 3, 65536))
|
||||
@ -35,13 +34,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
assert_se(mkdtemp_malloc("/tmp/fuzz-journal-remote-XXXXXX", &tmp) >= 0);
|
||||
assert_se(name = path_join(tmp, "fuzz-journal-remote.XXXXXX.journal"));
|
||||
|
||||
fdin = fdin_close = memfd_new_and_map("fuzz-journal-remote", size, &mem);
|
||||
fdin = fdin_close = memfd_new_and_seal("fuzz-journal-remote", data, size);
|
||||
if (fdin < 0)
|
||||
return log_error_errno(fdin, "memfd_new_and_map() failed: %m");
|
||||
|
||||
memcpy(mem, data, size);
|
||||
assert_se(munmap(mem, size) == 0);
|
||||
|
||||
fdout = mkostemps(name, STRLEN(".journal"), O_CLOEXEC);
|
||||
if (fdout < 0)
|
||||
return log_error_errno(errno, "mkostemps() failed: %m");
|
||||
|
@ -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");
|
||||
|
@ -1065,4 +1065,5 @@ global:
|
||||
sd_json_variant_type_from_string;
|
||||
sd_json_variant_type_to_string;
|
||||
sd_varlink_reset_fds;
|
||||
sd_device_enumerator_add_all_parents;
|
||||
} LIBSYSTEMD_257;
|
||||
|
@ -32,7 +32,6 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_DISK_FULL, ENOSPC),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED,
|
||||
EHOSTDOWN),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_FROZEN_BY_PARENT, EDEADLK),
|
||||
|
@ -28,7 +28,6 @@
|
||||
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
|
||||
#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
|
||||
#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
|
||||
#define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull"
|
||||
#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean"
|
||||
#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy"
|
||||
#define BUS_ERROR_UNIT_INACTIVE "org.freedesktop.systemd1.UnitInactive"
|
||||
|
@ -81,7 +81,7 @@ static void *server(void *p) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
|
||||
assert_se(pidref_set_pidfd_take(&pidref, pidfd) >= 0);
|
||||
assert_se(pidref.pid == getpid_cached());
|
||||
assert_se(pidref_is_self(&pidref));
|
||||
}
|
||||
|
||||
const gid_t *gl = NULL;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user