Compare commits

...

51 Commits

Author SHA1 Message Date
Adrian Vovk 3c87698a62
Merge 3e2b6fd389 into b7eefa1996 2024-11-21 14:29:21 +01:00
Luca Boccassi b7eefa1996 cgroup-util: fix memory leak on error
CID#1565824

Follow-up for f6793bbcf0
2024-11-21 14:02:34 +09:00
Luca Boccassi 2e5b0412f9
network: update state files before replying bus method (#35255)
Follow-up for 2b07a3211b.

Fixes the failure found in
https://autopkgtest.ubuntu.com/results/autopkgtest-noble-upstream-systemd-ci-systemd-ci/noble/amd64/s/systemd-upstream/20241115_182040_92382@/log.gz
. Relevant logs:
```
Nov 16 02:48:36 systemd-networkd[2706]: veth99: Reconfiguring with /run/systemd/network/25-dhcp-client-ipv6-only.network.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Started IPv6 Router Solicitation client
Nov 16 02:48:36 systemd-networkd[2706]: veth99: IPv6 Router Discovery is configured and started.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Sent Router Solicitation, next solicitation in 3s
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Received Router Advertisement from fe80::1034:56ff:fe78:9abd: flags=0xc0(managed, other), preference=medium, lifetime=30min
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Invoking callback for 'router' event.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: link_check_ready(): dynamic addressing protocols are enabled but none of them finished yet.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Starting in Solicit mode
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: State changed: stopped -> solicitation
Nov 16 02:48:36 systemd-networkd[2706]: veth99: Acquiring DHCPv6 lease on NDisc request
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Sent Solicit
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Next retransmission in 1s
Nov 16 02:48:37 systemd-networkd[2706]: veth99: DHCPv6 client: Sent Solicit
Nov 16 02:48:37 systemd-networkd[2706]: veth99: DHCPv6 client: Next retransmission in 1s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: NDISC: Received Neighbor Advertisement from fe80::1034:56ff:fe78:9abd: Router=yes, Solicited=yes, Override=no
Nov 16 02:48:39 systemd-networkd[2706]: veth99: NDISC: Invoking callback for 'neighbor' event.
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: Processed Reply message
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: T1 expires in 50s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: T2 expires in 55s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: Valid lifetime expires in 2min
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: State changed: solicitation -> bound
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 address 2600::15/128 (valid for 1min 59s, preferred for 1min 59s)
Nov 16 02:48:41 systemd-networkd[2706]: veth99: Received updated DHCPv6 address (configured): 2600::15/128 (valid for 1min 58s, preferred for 1min 58s), flags: no-prefixroute, scope: global
Nov 16 02:48:41 systemd-networkd[2706]: veth99: DHCPv6 addresses and routes set.
Nov 16 02:48:41 systemd-networkd[2706]: veth99: link_check_ready(): IPv4LL:no DHCPv4:no DHCPv6:yes DHCP-PD:no NDisc:no
Nov 16 02:48:41 systemd-networkd[2706]: veth99: State changed: configuring -> configured
```
The interface veth99 entered the configured state after 5 seconds, but
at the same time, the `wait_online()` in the test script considered the
test failed.
The function `wait_online()` first invokes
`systemd-networkd-wait-online` with `--timeout=20`, then check setup
states of interfaces with 5 seconds timeout. So, the failure suggests
that `systemd-networkd-wait-online` finishes immediately, as the state
file was not updated when it is invoked, and thus it handles the
interface veth99 already in the configured state.
2024-11-20 23:36:35 +00:00
Martin Srebotnjak 69af4849aa po: Translated using Weblate (Slovenian)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Martin Srebotnjak <miles@filmsi.net>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/sl/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Jiri Grönroos 18d4e0be89 po: Translated using Weblate (Finnish)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fi/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Dmytro Markevych 7d7b89a015 po: Translated using Weblate (Ukrainian)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Dmytro Markevych <hotr1pak@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/uk/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Léane GRASSER 8a92365f79 po: Translated using Weblate (French)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Léane GRASSER <leane.grasser@proton.me>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fr/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Yu Watanabe 2b397d43ab test-network: actually check metric and preference
Otherwise, nexthop ID may contain e.g. 300, then
===
AssertionError: '300' unexpectedly found in
'default nhid 3860882700 via fe80::1034:56ff:fe78:9a99 proto ra metric 512 expires 1798sec pref high\n
 default nhid 2639230080 via fe80::1034:56ff:fe78:9a98 proto ra metric 2048 expires 1798sec pref low'
===
2024-11-21 03:43:35 +09:00
Yu Watanabe 9ad294efd0 network: update state files before replying bus method
Follow-up for 2b07a3211b.
2024-11-21 03:42:06 +09:00
Lennart Poettering f6793bbcf0 killall: gracefully handle processes inserted into containers via nsenter -a
"nsenter -a" doesn't migrate the specified process into the target
cgroup (it really should). Thus the cgroup will remain in a cgroup
that is (due to cgroup ns) outside our visibility. The kernel will
report the cgroup path of such cgroups as starting with "/../". Detect
that and print a reasonably error message instead of trying to resolve
that.
2024-11-20 18:11:38 +00:00
Mike Yuan f87863a8ff process-util: refuse to operate on remote PidRef
Follow-up for 7e3e540b88
2024-11-20 18:10:26 +00:00
Antonio Alvarez Feijoo 58c3c2886d cryptenroll: fix typo 2024-11-20 18:03:44 +00:00
Daan De Meyer dbbe895807 test-audit-util: Migrate to new assertion macros 2024-11-20 16:48:55 +00:00
Yu Watanabe 52b0351a15
core/exec-invoke: suppress placeholder home only in build_environment() (#35219)
Alternative to https://github.com/systemd/systemd/pull/34789
Closes #34789
2024-11-20 17:34:25 +09:00
Luca Boccassi fe077a1a58 units: add initrd directory to list of conditions for systemd-confext
systemd-sysext has the same check, but it was forgotten for confexts.
Needed to activate confexts from the ESP in the initrd.
2024-11-20 09:12:24 +01:00
Xuanjun Wen a526b9ddfc hwdb: add new Cube Mix Plus (i18D) rotation info
Added rotation information for the new version of Cube Mix Plus (i18D).
2024-11-20 05:23:34 +09:00
Mike Yuan 804dd670d1
sd-varlink: mark sd_varlink_server_{ref,unref} as _public_ (#35241)
Co-authored-by: Thorsten Kukuk <kukuk@suse.com>
2024-11-20 05:21:15 +09:00
Lennart Poettering d5bb359429
user-record: don't synthesize default list of self-modfiable fields for non-regular users. (#35133)
A follow-up for a192250eda

/cc @AdrianVovk
2024-11-19 14:32:21 +01:00
Antonio Alvarez Feijoo a04d42821b man/kernel-command-line: fix typo 2024-11-19 13:59:11 +01:00
Luca Boccassi 987156769b
network/ndisc: process zero lifetime options at first (#35212)
Fixes two issues reported at #33468.
2024-11-19 12:42:03 +00:00
Antonio Alvarez Feijoo 2b251491de cryptenroll: show better log message if slot to wipe does not exist
```
$ systemd-cryptenroll /dev/vda3
SLOT TYPE
   0 password
$ systemd-cryptenroll --wipe-slot 1 /dev/vda3
Failed to wipe slot 1, continuing: No such file or directory
```
2024-11-19 12:00:50 +01:00
Lennart Poettering 12b06fef7a update TODO 2024-11-19 11:03:16 +01:00
Yaron Shahrabani dd7bc02ee6 po: Translated using Weblate (Hebrew)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/he/
Translation: systemd/main
2024-11-19 19:01:31 +09:00
Mantas Mikulėnas 2424a67c02 ssh-generator: silence "Binding to socket" messages 2024-11-19 11:00:20 +01:00
Lennart Poettering ebe37f771c user-record: distinguish explicit and implicit empty modifiable lists case
We now distinguish two cases: where the list of self modifiable fields
is explicitly set to empty, and where the default is empty.

Let's display them differently in the output. When set explicitly to
empty let's mention the admin, otherwise just say "none".
2024-11-19 10:15:42 +01:00
Lennart Poettering ac8e381e26 user-record: only synthesize default list of self-modifiable fields for *regular* users
For system users we should lock things down, hence generate an empty
list.

This is mostly a safety precaution, but also hides really confusing
output of "userdbctl user" for an system user.

Follow-up for: a192250eda
2024-11-19 10:15:40 +01:00
Zbigniew Jędrzejewski-Szmek 574a04f62a
test: fix generate-sym-test using the wrong array (#35185)
For my understanding bsearch is searching in the wrong array. Or, if
it's the right one, then the size is wrong. In another commit I made the
arrays different by mistake and that triggered a SIGSEV during tests.
2024-11-19 10:15:18 +01:00
Lennart Poettering ec97125a7e vmspawn: enable memory pressure logic for vmspawn 2024-11-19 10:12:03 +01:00
Lennart Poettering 54646b1ca9 systemctl: grey out tasks limit the same way we grey out the fd store limit in the output
"systemctl status systemd-logind" otherwise looks a bit weird, since the
tasks and the fdstore lines are so close to each other but formatted
quite differently when it comes to coloring.
2024-11-19 10:11:49 +01:00
Federico Giovanardi 0c851a58f7 style: Fix formatting 2024-11-19 09:55:07 +01:00
Mike Yuan b718b86e1b
core/exec-invoke: suppress placeholder home only in build_environment()
Currently, get_fixed_user() employs USER_CREDS_SUPPRESS_PLACEHOLDER,
meaning home path is set to NULL if it's empty or root. However,
the path is also used for applying WorkingDirectory=~, and we'd
spuriously use the invoking user's home as fallback even if
User= is changed in that case.

Let's instead delegate such suppression to build_environment(),
so that home is proper initialized for usage at other steps.
shell doesn't actually suffer from such problem, but it's changed
too for consistency.

Alternative to #34789
2024-11-19 00:38:18 +01:00
Mike Yuan d911778877
core/exec-invoke: minor cleanup for apply_working_directory() error handling
Assign exit_status at the same site where error log is emitted,
for readability.
2024-11-19 00:38:18 +01:00
Mike Yuan eea9d3eb10
basic/user-util: split out placeholder suppression from USER_CREDS_CLEAN into its own flag
No functional change, preparation for later commits.
2024-11-19 00:38:18 +01:00
Mike Yuan 579ce77ead
basic/user-util: introduce shell_is_placeholder() helper 2024-11-19 00:38:18 +01:00
Daan De Meyer 70bb29db62 mkosi: Enable clangd execution for all distributions 2024-11-18 23:21:24 +00:00
Lennart Poettering cc74edd861 update TODO 2024-11-18 23:50:04 +01:00
Yu Watanabe c295b558bf test-network: add test case for IPv6 Core Conformance test v6LC.2.2.23 2024-11-19 04:48:39 +09:00
Yu Watanabe 16ccdc3748 test-network: split out check_router_preference() from test_router_preference()
This also drop high2.network and low2.network, and edit high.network and
low.network during the test.
2024-11-19 04:44:59 +09:00
Yu Watanabe 25688f8d5a network/ndisc: first process options with zero lifetime
Fixes IPv6 Core Conformance test failures reported at #33468.
https://www.ipv6ready.org/docs/Core_Conformance.pdf
Test v6LC.2.2.23 h and j: Processing Router Advertisement with Route
Information Option (Host Only)

When a RA contains route option with ::/0 prefix, then previously that
may contradict with the default route requested with the RA header.
If the route option has zero lifetime, the existing default route should
be removed, and a new route based on the RA header should be configured.
If the route option has non-zero lifetime, the RA header should be
ignored.

So, we first need to process options with zero lifetime (not only
route option, as the similar reasons), then configure the default route
based on the RA, finally process options with non-zero lifetime.
2024-11-19 04:04:14 +09:00
Yu Watanabe cb3243460b network/ndisc: sd_ndisc_router_route_get_preference() does not return -EOPNOTSUPP anymore 2024-11-19 04:04:14 +09:00
Yu Watanabe c8ddd5ff72 ndisc-option: use memcpy_safe() at one more place
As 'len' may be 8.

Follow-up for a163404cc8.
2024-11-19 04:04:14 +09:00
Zbigniew Jędrzejewski-Szmek 5e7e4e4d49 ukify: fix parsing of SignTool configuration option
This partially reverts 02eabaffe9.
As noted in https://github.com/systemd/systemd/pull/35211:
> The configuration parsing simply stores the string as-is, rather than
> creating the appropriate object

One way to fix the issue would be to store the "appropriate object", i.e.
actually the class. But that makes the code very verbose, with the conversion
being done in two places. And that still doesn't fix the issue, because we need
to map the class objects back to the original name in error messages.

So instead, store the setting as a string and only map it to the class much
later. This makes the code simpler and fixes the error messages too.

Resolves https://github.com/systemd/systemd/pull/35193
2024-11-18 14:58:41 +00:00
Yu Watanabe 4d9cac56db man: fix copy-and-paste error
Follow-up for 85a1360ecf.
2024-11-18 15:18:26 +09:00
Yu Watanabe 85a1360ecf man: add several future version info tags 2024-11-18 15:04:17 +09:00
Yu Watanabe ec0847f8fb po: update Japanese translations 2024-11-18 13:01:34 +09:00
Yu Watanabe efb158a11b network/netdev: fix typo
Follow-up for 09db410606.
2024-11-18 12:53:21 +09:00
Michał Górny 7fd70a5326 nspawn: Include arm_fadvise64_64 in syscall allow_list
Add the `arm_fadvise64_64` syscall to the allow_list, in addition
to the existing `fadvise64` and `fadvise64_64` syscalls, as this is
the syscall actually defined for `arm` architecture.  Adding it fixes
the syscall being rejected in arm32 containers.

Fixes #35194
2024-11-18 11:43:35 +09:00
Federico Giovanardi 55980446c3 test: fix generate-sym-test using the wrong array
The second check was searching the symbols into the same array, but
using the size of the other. This generated a SIGSEV when they
occassionally mismatched.
2024-11-15 17:12:42 +01:00
Adrian Vovk 3e2b6fd389
sysupdate: Add --stream flag for major version bumps
Basically, distros that maintain more than one release stream (i.e.
multiple stable versions, a beta channel, etc) can put the others'
transfer definitions into /usr/lib/sysupdate@$STREAM.d/, and the admin
can pass --stream= on the CLI to switch to this new stream.

Part of https://github.com/systemd/systemd/issues/33345

SQUASHME: s/--next/--streams=<stream>/
2024-10-30 22:00:30 -04:00
Adrian Vovk 6f6d29290e
Warn admins about danger of overriding sysupdate.d
Overriding settings of systemd-sysupdate is quite dangerous - OS vendor
might make a change that is incompatible with the settings in /etc, and
unlike most other config incompatibilities this has the potential to
accidentally wipe the wrong partition during an update. Not good. So
let's warn admins.
2024-10-30 21:54:49 -04:00
Adrian Vovk 19bac76b1a
sysupdate: Document components more visibly
Right now components aren't particularly well documented. Let's make
the feature a bit more visible.
2024-10-30 21:54:48 -04:00
47 changed files with 656 additions and 340 deletions

14
TODO
View File

@ -129,6 +129,20 @@ Deprecations and removals:
Features: Features:
* 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:
https://github.com/systemd/systemd/issues/35071#issuecomment-2462803142
* maybe introduce an OSC sequence that signals when we ask for a password, so
that terminal emulators can maybe connect a password manager or so, and
highlight things specially.
* Port pidref_namespace_open() to use PIDFD_GET_MNT_NAMESPACE and related
ioctls to get nsfds directly from pidfds.
* start using STATX_SUBVOL in btrfs_is_subvol(). Also, make use of it
generically, so that image discovery recognizes bcachefs subvols too.
* format-table: introduce new cell type for strings with ansi sequences in * format-table: introduce new cell type for strings with ansi sequences in
them. display them in regular output mode (via strip_tab_ansi()), but them. display them in regular output mode (via strip_tab_ansi()), but
suppress them in json mode. suppress them in json mode.

View File

@ -376,11 +376,12 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svncube:pni1-TF:*
sensor:modalias:acpi:SMO8500*:dmi:*:svncube:pni7:* sensor:modalias:acpi:SMO8500*:dmi:*:svncube:pni7:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
# Cube i7 Stylus, i7 Stylus I8L Model, i7 Book (i16) and Mix Plus (i18B) # Cube i7 Stylus, i7 Stylus I8L Model, i7 Book (i16) and Mix Plus (i18B/i18D)
sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni7Stylus:* sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni7Stylus:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni8-L:* sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni8-L:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni16:* sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni16:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni18B:* sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni18B:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnALLDOCUBE:pni18D:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
# Cube iWork 10 Flagship # Cube iWork 10 Flagship

View File

@ -421,7 +421,7 @@
<term><varname>rd.systemd.verity=</varname></term> <term><varname>rd.systemd.verity=</varname></term>
<term><varname>systemd.verity_root_data=</varname></term> <term><varname>systemd.verity_root_data=</varname></term>
<term><varname>systemd.verity_root_hash=</varname></term> <term><varname>systemd.verity_root_hash=</varname></term>
<term><varname>systemd.verity.root_options=</varname></term> <term><varname>systemd.verity_root_options=</varname></term>
<term><varname>usrhash=</varname></term> <term><varname>usrhash=</varname></term>
<term><varname>systemd.verity_usr_data=</varname></term> <term><varname>systemd.verity_usr_data=</varname></term>
<term><varname>systemd.verity_usr_hash=</varname></term> <term><varname>systemd.verity_usr_hash=</varname></term>

View File

@ -190,6 +190,17 @@
<xi:include href="version-info.xml" xpointer="v251"/></listitem> <xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>streams</option></term>
<listitem><para>Lists streams that can be updated. This enumerates the
<filename>/var/cache/systemd/sysupdate@*.d/</filename> and <filename>/usr/lib/sysupdate@*.d/</filename>
directories that contain transfer definitions. This command is useful to list possible parameters
for <option>--stream=</option> (see below).</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" /> <xi:include href="standard-options.xml" xpointer="version" />
</variablelist> </variablelist>
@ -225,7 +236,8 @@
updated together in a synchronous fashion. Simply define multiple transfer files within the same updated together in a synchronous fashion. Simply define multiple transfer files within the same
<filename>sysupdate.d/</filename> directory for these cases.</para> <filename>sysupdate.d/</filename> directory for these cases.</para>
<para>This option may not be combined with <option>--definitions=</option>.</para> <para>This option may not be combined with <option>--definitions=</option> or
<option>--stream=</option>.</para>
<xi:include href="version-info.xml" xpointer="v251"/></listitem> <xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry> </varlistentry>
@ -237,11 +249,29 @@
are read from this directory instead of <filename>/usr/lib/sysupdate.d/*.conf</filename>, are read from this directory instead of <filename>/usr/lib/sysupdate.d/*.conf</filename>,
<filename>/etc/sysupdate.d/*.conf</filename>, and <filename>/run/sysupdate.d/*.conf</filename>.</para> <filename>/etc/sysupdate.d/*.conf</filename>, and <filename>/run/sysupdate.d/*.conf</filename>.</para>
<para>This option may not be combined with <option>--component=</option>.</para> <para>This option may not be combined with <option>--component=</option> or
<option>--stream=</option>.</para>
<xi:include href="version-info.xml" xpointer="v251"/></listitem> <xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--stream=</option></term>
<listitem><para>Selects the update stream to use. Takes a stream name as argument. This alters
the search logic for transfer definitions to look in
<filename>/usr/lib/sysupdate@<replaceable>stream</replaceable>.d/</filename> and
<filename>/var/cache/systemd/sysupdate@<replaceable>stream</replaceable>.d/</filename> instead of
<filename>/usr/lib/sysupdate.d</filename>.
Note that administrator-controlled directories (i.e. <filename>/etc/sysupdate.d/</filename>, etc) are
still loaded as usual.</para>
<para>This option may not be combined with <option>--definitions=</option> or
<option>--component=</option>.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--root=</option></term> <term><option>--root=</option></term>

View File

@ -65,6 +65,52 @@
<citerefentry><refentrytitle>sysupdate.features</refentrytitle><manvolnum>5</manvolnum></citerefentry>. <citerefentry><refentrytitle>sysupdate.features</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para> </para>
<para>Sometimes, distributions need to update certain parts of themselves independently from the normal
update cycle.
For example, the <ulink url="https://github.com/rhboot/shim">UEFI Shim loader</ulink> (necessary for
UEFI Secure Boot support in many cases) has its own release cycle, requires code signatures from a
third-party, and in general is not tied to a distribution's update cycle.
Support for this scenario is provided by "components", which allow distributions to define transfer
definitions that receive updates independently from the base OS.
Components are defined in <filename>/usr/lib/sysupdate.<replaceable>component</replaceable>.d/</filename>,
and have corresponding override directories for administrators (i.e.
<filename>/etc/sysupdate.<replaceable>component</replaceable>.d/</filename>, etc).</para>
<para>Some distributions may wish to maintain multiple update "streams" at a time, for example to offer
a beta/nightly update channel, or to distribute security updates to multiple major versions at a time.
Users of such distributions may wish to remain on their current stream, and switch streams at some future
point in time.
A distribution with multiple update streams should ship the transfer definitions for each stream in the
<filename>/usr/lib/sysupdate@<replaceable>stream</replaceable>.d/</filename> or
<filename>/var/cache/systemd/sysupdate@<replaceable>stream</replaceable>.d/</filename> directories.
For example, a distribution with multiple stable branches can ship the next major release's transfer
definitions in the current release's
<filename>/usr/lib/sysupdate@foobarOS-<replaceable>next</replaceable>.d/</filename> directory, and users
can switch to it by updating the <literal>foobarOS-<replaceable>next</replaceable></literal> stream.
How exactly these stream definition directories are delivered is up to distributions: they can stabilize
transfer definitions a version in advance and ship the stream definitions from day one, or they can ship
these files as part of a regular security patch that users will install anyway, or they can use a
component as described above to update the stream definitions under <filename>/var/cache/</filename>
independently from the host system.
Note that the presence of a stream definition directory does not imply the availability of an upgrade on
that stream; it just defines where to look and if an update is found on the remote how to install it.
Also note that the normal administrator override files (i.e. transfer definitions, feature definitions,
or drop-ins found in <filname>/etc/sysupdate.d/</filname>, <filename>/run/sysupdate.d/</filename>, etc)
are applied over top of the definitions found in the stream definition directory.
This is done because a the stream definition directory turns into the normal definition directory
(<filename>/usr/lib/sysupdate.d/</filename>) when that stream is switched to.</para>
<para>System Administrators must take <emphasis>extreme</emphasis> care when overriding any transfer or
optional feature definitions, other than to turn on or off features!
As with any configuration defined in <filename>/usr</filename> and overridden in
<filename>/etc</filename>, an update to the host system can break the administrator overrides.
However, <command>systemd-sysupdate</command> is uniquely destructive: a broken configuration could
prevent the system from updating (best case), or completely destroy an installation by wiping the wrong
partition.
Distributions must take care to avoid breaking systems where overrides exist only to turn on or off
optional features; supporting (or choosing not to) everything else is up to distribution policy.
<emphasis>You have been warned.</emphasis></para>
<para>Each <filename>*.transfer</filename> file contains three sections: [Transfer], [Source] and [Target].</para> <para>Each <filename>*.transfer</filename> file contains three sections: [Transfer], [Source] and [Target].</para>
</refsect1> </refsect1>

View File

@ -81,4 +81,7 @@
<para id="v255">Added in version 255.</para> <para id="v255">Added in version 255.</para>
<para id="v256">Added in version 256.</para> <para id="v256">Added in version 256.</para>
<para id="v257">Added in version 257.</para> <para id="v257">Added in version 257.</para>
<para id="v258">Added in version 258.</para>
<para id="v259">Added in version 259.</para>
<para id="v260">Added in version 260.</para>
</refsect1> </refsect1>

View File

@ -0,0 +1,7 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
if [[ "$1" == "clangd" ]]; then
exec "$@"
fi

View File

@ -2,10 +2,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
set -e set -e
if [[ "$1" == "clangd" ]]; then
exec "$@"
fi
if [[ ! -f "pkg/$PKG_SUBDIR/PKGBUILD" ]]; then if [[ ! -f "pkg/$PKG_SUBDIR/PKGBUILD" ]]; then
echo "PKGBUILD not found at pkg/$PKG_SUBDIR/PKGBUILD, run mkosi once with -ff to make sure the PKGBUILD is cloned" >&2 echo "PKGBUILD not found at pkg/$PKG_SUBDIR/PKGBUILD, run mkosi once with -ff to make sure the PKGBUILD is cloned" >&2
exit 1 exit 1

View File

@ -3,12 +3,13 @@
# Finnish translation of systemd. # Finnish translation of systemd.
# Jan Kuparinen <copper_fin@hotmail.com>, 2021, 2022, 2023. # Jan Kuparinen <copper_fin@hotmail.com>, 2021, 2022, 2023.
# Ricky Tigg <ricky.tigg@gmail.com>, 2022, 2024. # Ricky Tigg <ricky.tigg@gmail.com>, 2022, 2024.
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2024.
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-09-12 13:43+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Ricky Tigg <ricky.tigg@gmail.com>\n" "Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>\n"
"Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/"
"main/fi/>\n" "main/fi/>\n"
"Language: fi\n" "Language: fi\n"
@ -16,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.7.2\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -112,14 +113,12 @@ msgid "Authentication is required to update a user's home area."
msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi." msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Päivitä kotialue" msgstr "Päivitä kotialue"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi." msgstr "Todennus vaaditaan kotialueen päivittämiseksi."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1174,14 +1173,11 @@ msgstr "Todennus vaaditaan vanhojen järjestelmäpäivitysten puhdistamiseen."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Hallitse valinnaisia ominaisuuksia"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr "Todennus vaaditaan valinnaisten ominaisuuksien hallintaan"
"Todennus vaaditaan aktiivisten istuntojen, käyttäjien ja paikkojen "
"hallintaan."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -12,7 +12,7 @@ msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-11-07 09:30+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n" "Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n"
"Language-Team: French <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: French <https://translate.fedoraproject.org/projects/systemd/"
"main/fr/>\n" "main/fr/>\n"
@ -360,8 +360,8 @@ msgid ""
"Authentication is required to set the statically configured local hostname, " "Authentication is required to set the statically configured local hostname, "
"as well as the pretty hostname." "as well as the pretty hostname."
msgstr "" msgstr ""
"Une authentification est requise pour définir le nom d'hôte local de manière " "Une authentification est requise pour définir le nom d'hôte local configuré "
"statique, ainsi que le nom d'hôte familier." "de manière statique, ainsi que le nom d'hôte convivial."
#: src/hostname/org.freedesktop.hostname1.policy:41 #: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information" msgid "Set machine information"

View File

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: systemd\n" "Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-11-17 15:48+0000\n" "PO-Revision-Date: 2024-11-19 07:38+0000\n"
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n" "Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
"Language-Team: Hebrew <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: Hebrew <https://translate.fedoraproject.org/projects/systemd/"
"main/he/>\n" "main/he/>\n"
@ -375,10 +375,9 @@ msgid "Cancel transfer of a disk image"
msgstr "ביטול העברה של דמות כונן" msgstr "ביטול העברה של דמות כונן"
#: src/import/org.freedesktop.import1.policy:53 #: src/import/org.freedesktop.import1.policy:53
#, fuzzy
msgid "" msgid ""
"Authentication is required to cancel the ongoing transfer of a disk image." "Authentication is required to cancel the ongoing transfer of a disk image."
msgstr "נדרש אימות כדי להחליף סיסמה של אזור בית למשתמש." msgstr "נדרש אימות כדי לבטל העברה של דמות כונן שמתבצעת בזמן אמת."
#: src/locale/org.freedesktop.locale1.policy:22 #: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale" msgid "Set system locale"
@ -720,9 +719,8 @@ msgid "Set a wall message"
msgstr "הגדרת הודעת קיר" msgstr "הגדרת הודעת קיר"
#: src/login/org.freedesktop.login1.policy:397 #: src/login/org.freedesktop.login1.policy:397
#, fuzzy
msgid "Authentication is required to set a wall message." msgid "Authentication is required to set a wall message."
msgstr "נדרש אימות כדי להגדיר הודעת קיר" msgstr "נדרש אימות כדי להגדיר הודעת קיר."
#: src/login/org.freedesktop.login1.policy:406 #: src/login/org.freedesktop.login1.policy:406
msgid "Change Session" msgid "Change Session"
@ -792,16 +790,14 @@ msgstr ""
"נדרש אימות כדי לנהל מכונות וירטואליות (VM) ומכולות (container) מקומיות." "נדרש אימות כדי לנהל מכונות וירטואליות (VM) ומכולות (container) מקומיות."
#: src/machine/org.freedesktop.machine1.policy:95 #: src/machine/org.freedesktop.machine1.policy:95
#, fuzzy
msgid "Create a local virtual machine or container" msgid "Create a local virtual machine or container"
msgstr "ניהול מכונות וירטואליות ומכולות מקומיות" msgstr "יצירת מכונה וירטואלית או מכולה מקומיות"
#: src/machine/org.freedesktop.machine1.policy:96 #: src/machine/org.freedesktop.machine1.policy:96
#, fuzzy
msgid "" msgid ""
"Authentication is required to create a local virtual machine or container." "Authentication is required to create a local virtual machine or container."
msgstr "" msgstr ""
"נדרש אימות כדי לנהל מכונות וירטואליות (VM) ומכולות (container) מקומיות." "נדרש אימות כדי ליצור מכונות וירטואליות (VM) או מכולות (container) מקומיות."
#: src/machine/org.freedesktop.machine1.policy:106 #: src/machine/org.freedesktop.machine1.policy:106
msgid "Manage local virtual machine and container images" msgid "Manage local virtual machine and container images"
@ -953,13 +949,13 @@ msgstr "נדרש אימות כדי להגדיר כרטיס רשת מחדש."
#: src/network/org.freedesktop.network1.policy:187 #: src/network/org.freedesktop.network1.policy:187
msgid "Specify whether persistent storage for systemd-networkd is available" msgid "Specify whether persistent storage for systemd-networkd is available"
msgstr "" msgstr "נא לציין האם יש אחסון קבוע זמין ל־systemd-networkd"
#: src/network/org.freedesktop.network1.policy:188 #: src/network/org.freedesktop.network1.policy:188
msgid "" msgid ""
"Authentication is required to specify whether persistent storage for systemd-" "Authentication is required to specify whether persistent storage for systemd-"
"networkd is available." "networkd is available."
msgstr "" msgstr "נדרש אימות כדי לציין האם אחסון קבוע זמין ל־systemd-networkd."
#: src/portable/org.freedesktop.portable1.policy:13 #: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image" msgid "Inspect a portable service image"
@ -992,18 +988,16 @@ msgid "Register a DNS-SD service"
msgstr "רישום שירות DNS-SD" msgstr "רישום שירות DNS-SD"
#: src/resolve/org.freedesktop.resolve1.policy:23 #: src/resolve/org.freedesktop.resolve1.policy:23
#, fuzzy
msgid "Authentication is required to register a DNS-SD service." msgid "Authentication is required to register a DNS-SD service."
msgstr "נדרש אימות כדי לרשום שירות DNS-SD" msgstr "נדרש אימות כדי לרשום שירות DNS-SD."
#: src/resolve/org.freedesktop.resolve1.policy:33 #: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service" msgid "Unregister a DNS-SD service"
msgstr "ביטול רישום שירות DNS-SD" msgstr "ביטול רישום שירות DNS-SD"
#: src/resolve/org.freedesktop.resolve1.policy:34 #: src/resolve/org.freedesktop.resolve1.policy:34
#, fuzzy
msgid "Authentication is required to unregister a DNS-SD service." msgid "Authentication is required to unregister a DNS-SD service."
msgstr "נדרש אימות כדי לבטל רישום של שירות DNS-SD" msgstr "נדרש אימות כדי לבטל רישום של שירות DNS-SD."
#: src/resolve/org.freedesktop.resolve1.policy:132 #: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings" msgid "Revert name resolution settings"
@ -1015,95 +1009,85 @@ msgstr "נדרש אימות כדי לאפס את הגדרות פתרון השמ
#: src/resolve/org.freedesktop.resolve1.policy:143 #: src/resolve/org.freedesktop.resolve1.policy:143
msgid "Subscribe query results" msgid "Subscribe query results"
msgstr "" msgstr "רישום לתוצאות שאילתה"
#: src/resolve/org.freedesktop.resolve1.policy:144 #: src/resolve/org.freedesktop.resolve1.policy:144
#, fuzzy
msgid "Authentication is required to subscribe query results." msgid "Authentication is required to subscribe query results."
msgstr "נדרש אימות כדי להשהות את המערכת." msgstr "נדרש אימות כדי להירשם לתוצאות שאילתה."
#: src/resolve/org.freedesktop.resolve1.policy:154 #: src/resolve/org.freedesktop.resolve1.policy:154
msgid "Dump cache" msgid "Dump cache"
msgstr "" msgstr "היטל המטמון"
#: src/resolve/org.freedesktop.resolve1.policy:155 #: src/resolve/org.freedesktop.resolve1.policy:155
#, fuzzy
msgid "Authentication is required to dump cache." msgid "Authentication is required to dump cache."
msgstr "נדרש אימות כדי להגדיר שמות תחום." msgstr "נדרש אימות כדי להטיל את המטמון."
#: src/resolve/org.freedesktop.resolve1.policy:165 #: src/resolve/org.freedesktop.resolve1.policy:165
msgid "Dump server state" msgid "Dump server state"
msgstr "" msgstr "היטל מצב השרת"
#: src/resolve/org.freedesktop.resolve1.policy:166 #: src/resolve/org.freedesktop.resolve1.policy:166
#, fuzzy
msgid "Authentication is required to dump server state." msgid "Authentication is required to dump server state."
msgstr "נדרש אימות כדי להגדיר שרתי NTP." msgstr "נדרש אימות כדי להטיל את מצב השרת."
#: src/resolve/org.freedesktop.resolve1.policy:176 #: src/resolve/org.freedesktop.resolve1.policy:176
msgid "Dump statistics" msgid "Dump statistics"
msgstr "" msgstr "היטל סטטיסטיקה"
#: src/resolve/org.freedesktop.resolve1.policy:177 #: src/resolve/org.freedesktop.resolve1.policy:177
#, fuzzy
msgid "Authentication is required to dump statistics." msgid "Authentication is required to dump statistics."
msgstr "נדרש אימות כדי להגדיר שמות תחום." msgstr "נדרש אימות כדי להטיל סטטיסטיקה."
#: src/resolve/org.freedesktop.resolve1.policy:187 #: src/resolve/org.freedesktop.resolve1.policy:187
msgid "Reset statistics" msgid "Reset statistics"
msgstr "" msgstr "איפוס סטטיסטיקה"
#: src/resolve/org.freedesktop.resolve1.policy:188 #: src/resolve/org.freedesktop.resolve1.policy:188
#, fuzzy
msgid "Authentication is required to reset statistics." msgid "Authentication is required to reset statistics."
msgstr "נדרש אימות כדי לאפס הגדרות NTP." msgstr "נדרש אימות כדי לאפס סטטיסטיקה."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:35 #: src/sysupdate/org.freedesktop.sysupdate1.policy:35
msgid "Check for system updates" msgid "Check for system updates"
msgstr "" msgstr "חיפוש עדכוני מערכת"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:36 #: src/sysupdate/org.freedesktop.sysupdate1.policy:36
#, fuzzy
msgid "Authentication is required to check for system updates." msgid "Authentication is required to check for system updates."
msgstr "נדרש אימות כדי להגדיר את שעון המערכת." msgstr "נדרש אימות כדי לחפש עדכוני מערכת."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:45 #: src/sysupdate/org.freedesktop.sysupdate1.policy:45
msgid "Install system updates" msgid "Install system updates"
msgstr "" msgstr "התקנת עדכוני מערכת"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:46 #: src/sysupdate/org.freedesktop.sysupdate1.policy:46
#, fuzzy
msgid "Authentication is required to install system updates." msgid "Authentication is required to install system updates."
msgstr "נדרש אימות כדי להגדיר את שעון המערכת." msgstr "נדרש אימות כדי להתקין עדכוני מערכת."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:55 #: src/sysupdate/org.freedesktop.sysupdate1.policy:55
msgid "Install specific system version" msgid "Install specific system version"
msgstr "" msgstr "התקנת גרסת מערכת מסוימת"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:56 #: src/sysupdate/org.freedesktop.sysupdate1.policy:56
#, fuzzy
msgid "" msgid ""
"Authentication is required to update the system to a specific (possibly old) " "Authentication is required to update the system to a specific (possibly old) "
"version." "version."
msgstr "נדרש אימות כדי להגדיר את אזור הזמן של המערכת." msgstr "נדרש אימות כדי לעדכן את המערכת לגרסה מסוימת (כנראה ישנה)."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:65 #: src/sysupdate/org.freedesktop.sysupdate1.policy:65
msgid "Cleanup old system updates" msgid "Cleanup old system updates"
msgstr "" msgstr "ניקוי עדכוני מערכת ישנים"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:66 #: src/sysupdate/org.freedesktop.sysupdate1.policy:66
#, fuzzy
msgid "Authentication is required to cleanup old system updates." msgid "Authentication is required to cleanup old system updates."
msgstr "נדרש אימות כדי להגדיר את שעון המערכת." msgstr "נדרש אימות כדי לנקות עדכוני מערכת ישנים."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "ניהול יכולות רשות"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "נדרש אימות כדי לנהל הפעלות, משתמשים ומושבים פעילים." msgstr "נדרש אימות כדי לנהל יכולות רשות"
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-18 12:55+0900\n"
"PO-Revision-Date: 2021-09-09 03:04+0000\n" "PO-Revision-Date: 2021-09-09 03:04+0000\n"
"Last-Translator: Takuro Onoue <kusanaginoturugi@gmail.com>\n" "Last-Translator: Takuro Onoue <kusanaginoturugi@gmail.com>\n"
"Language-Team: Japanese <https://translate.fedoraproject.org/projects/" "Language-Team: Japanese <https://translate.fedoraproject.org/projects/"
@ -106,14 +106,12 @@ msgid "Authentication is required to update a user's home area."
msgstr "ユーザのホーム領域の更新には認証が必要です。" msgstr "ユーザのホーム領域の更新には認証が必要です。"
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "ホーム領域の更新" msgstr "ホーム領域の更新"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "ユーザのホーム領域の更新には認証が必要です。" msgstr "ホーム領域の更新には認証が必要です。"
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1120,12 +1118,11 @@ msgstr "過去のシステム更新を削除するには認証が必要です。
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "任意の機能の管理"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "アクティブなセッションやユーザ,シートを管理するには認証が必要です。" msgstr "任意の機能を管理するには認証が必要です。"
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: systemd\n" "Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-08-26 19:38+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n" "Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"Language-Team: Slovenian <https://translate.fedoraproject.org/projects/" "Language-Team: Slovenian <https://translate.fedoraproject.org/projects/"
"systemd/main/sl/>\n" "systemd/main/sl/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
"n%100==4 ? 2 : 3;\n" "n%100==4 ? 2 : 3;\n"
"X-Generator: Weblate 5.7\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -125,16 +125,13 @@ msgstr ""
"območja." "območja."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Posodobite domače območje" msgstr "Posodobite domače območje"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "" msgstr ""
"Preverjanje pristnosti je potrebno za posodobitev uporabnikovega domačega " "Preverjanje pristnosti je potrebno za posodobitev vašega domačega območja."
"območja."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1234,14 +1231,12 @@ msgstr ""
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Upravljaj dodatne funkcionalnosti"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr ""
"Preverjanje pristnosti je potrebno za upravljanje aktivnih sej, uporabnikov " "Preverjanje pristnosti je potrebno za upravljanje dodatnih funkcionalnosti."
"in delovišč."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -4,12 +4,13 @@
# Eugene Melnik <jeka7js@gmail.com>, 2014. # Eugene Melnik <jeka7js@gmail.com>, 2014.
# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018. # Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018.
# Yuri Chornoivan <yurchor@ukr.net>, 2019, 2020, 2021, 2022, 2023, 2024. # Yuri Chornoivan <yurchor@ukr.net>, 2019, 2020, 2021, 2022, 2023, 2024.
# Dmytro Markevych <hotr1pak@gmail.com>, 2024.
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-08-24 10:36+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Last-Translator: Dmytro Markevych <hotr1pak@gmail.com>\n"
"Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/" "Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/"
"systemd/main/uk/>\n" "systemd/main/uk/>\n"
"Language: uk\n" "Language: uk\n"
@ -18,7 +19,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 5.7\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -118,14 +119,12 @@ msgid "Authentication is required to update a user's home area."
msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання." msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Оновлення домашньої теки" msgstr "Оновіть свій домашній простір"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання." msgstr "Для оновлення домашньої області потрібна автентифікація."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1212,14 +1211,11 @@ msgstr "Для вилучення застарілих оновлень сист
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Керування додатковими функціями"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr "Для керування додатковими функціями потрібна автентифікація"
"Для того, щоб керувати сеансами, користувачами і робочими місцями, слід "
"пройти розпізнавання."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -799,16 +799,20 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
continue; continue;
} }
char *path = strdup(e + 1); _cleanup_free_ char *path = strdup(e + 1);
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
/* Refuse cgroup paths from outside our cgroup namespace */
if (startswith(path, "/../"))
return -EUNATCH;
/* Truncate suffix indicating the process is a zombie */ /* Truncate suffix indicating the process is a zombie */
e = endswith(path, " (deleted)"); e = endswith(path, " (deleted)");
if (e) if (e)
*e = 0; *e = 0;
*ret_path = path; *ret_path = TAKE_PTR(path);
return 0; return 0;
} }
} }

View File

@ -64,12 +64,18 @@
"/usr/local/lib/" n "\0" \ "/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" "/usr/lib/" n "\0"
#define CONF_PATHS(n) \ #define CONF_PATHS_ADMIN(n) \
"/etc/" n, \ "/etc/" n, \
"/run/" n, \ "/run/" n
#define CONF_PATHS_SYSTEM(n) \
"/usr/local/lib/" n, \ "/usr/local/lib/" n, \
"/usr/lib/" n "/usr/lib/" n
#define CONF_PATHS(n) \
CONF_PATHS_ADMIN(n), \
CONF_PATHS_SYSTEM(n)
#define CONF_PATHS_STRV(n) \ #define CONF_PATHS_STRV(n) \
STRV_MAKE(CONF_PATHS(n)) STRV_MAKE(CONF_PATHS(n))

View File

@ -102,8 +102,8 @@ int pid_get_comm(pid_t pid, char **ret) {
_cleanup_free_ char *escaped = NULL, *comm = NULL; _cleanup_free_ char *escaped = NULL, *comm = NULL;
int r; int r;
assert(ret);
assert(pid >= 0); assert(pid >= 0);
assert(ret);
if (pid == 0 || pid == getpid_cached()) { if (pid == 0 || pid == getpid_cached()) {
comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */ comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */
@ -143,6 +143,9 @@ int pidref_get_comm(const PidRef *pid, char **ret) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
r = pid_get_comm(pid->pid, &comm); r = pid_get_comm(pid->pid, &comm);
if (r < 0) if (r < 0)
return r; return r;
@ -289,6 +292,9 @@ int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlag
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
r = pid_get_cmdline(pid->pid, max_columns, flags, &s); r = pid_get_cmdline(pid->pid, max_columns, flags, &s);
if (r < 0) if (r < 0)
return r; return r;
@ -331,6 +337,9 @@ int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char *
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
r = pid_get_cmdline_strv(pid->pid, flags, &args); r = pid_get_cmdline_strv(pid->pid, flags, &args);
if (r < 0) if (r < 0)
return r; return r;
@ -477,6 +486,9 @@ int pidref_is_kernel_thread(const PidRef *pid) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
result = pid_is_kernel_thread(pid->pid); result = pid_is_kernel_thread(pid->pid);
if (result < 0) if (result < 0)
return result; return result;
@ -594,6 +606,9 @@ int pidref_get_uid(const PidRef *pid, uid_t *ret) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
r = pid_get_uid(pid->pid, &uid); r = pid_get_uid(pid->pid, &uid);
if (r < 0) if (r < 0)
return r; return r;
@ -794,6 +809,9 @@ int pidref_get_start_time(const PidRef *pid, usec_t *ret) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
r = pid_get_start_time(pid->pid, ret ? &t : NULL); r = pid_get_start_time(pid->pid, ret ? &t : NULL);
if (r < 0) if (r < 0)
return r; return r;
@ -1093,6 +1111,9 @@ int pidref_is_my_child(const PidRef *pid) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
result = pid_is_my_child(pid->pid); result = pid_is_my_child(pid->pid);
if (result < 0) if (result < 0)
return result; return result;
@ -1128,6 +1149,9 @@ int pidref_is_unwaited(const PidRef *pid) {
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pid))
return -EREMOTE;
if (pid->pid == 1 || pidref_is_self(pid)) if (pid->pid == 1 || pidref_is_self(pid))
return true; return true;
@ -1169,6 +1193,9 @@ int pidref_is_alive(const PidRef *pidref) {
if (!pidref_is_set(pidref)) if (!pidref_is_set(pidref))
return -ESRCH; return -ESRCH;
if (pidref_is_remote(pidref))
return -EREMOTE;
result = pid_is_alive(pidref->pid); result = pid_is_alive(pidref->pid);
if (result < 0) { if (result < 0) {
assert(result != -ESRCH); assert(result != -ESRCH);

View File

@ -220,9 +220,9 @@ static int synthesize_user_creds(
if (ret_gid) if (ret_gid)
*ret_gid = GID_NOBODY; *ret_gid = GID_NOBODY;
if (ret_home) if (ret_home)
*ret_home = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : "/"; *ret_home = FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) ? NULL : "/";
if (ret_shell) if (ret_shell)
*ret_shell = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : NOLOGIN; *ret_shell = FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) ? NULL : NOLOGIN;
return 0; return 0;
} }
@ -244,6 +244,7 @@ int get_user_creds(
assert(username); assert(username);
assert(*username); assert(*username);
assert((ret_home || ret_shell) || !(flags & (USER_CREDS_SUPPRESS_PLACEHOLDER|USER_CREDS_CLEAN)));
if (!FLAGS_SET(flags, USER_CREDS_PREFER_NSS) || if (!FLAGS_SET(flags, USER_CREDS_PREFER_NSS) ||
(!ret_home && !ret_shell)) { (!ret_home && !ret_shell)) {
@ -315,17 +316,14 @@ int get_user_creds(
if (ret_home) if (ret_home)
/* Note: we don't insist on normalized paths, since there are setups that have /./ in the path */ /* Note: we don't insist on normalized paths, since there are setups that have /./ in the path */
*ret_home = (FLAGS_SET(flags, USER_CREDS_CLEAN) && *ret_home = (FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) && empty_or_root(p->pw_dir)) ||
(empty_or_root(p->pw_dir) || (FLAGS_SET(flags, USER_CREDS_CLEAN) && (!path_is_valid(p->pw_dir) || !path_is_absolute(p->pw_dir)))
!path_is_valid(p->pw_dir) || ? NULL : p->pw_dir;
!path_is_absolute(p->pw_dir))) ? NULL : p->pw_dir;
if (ret_shell) if (ret_shell)
*ret_shell = (FLAGS_SET(flags, USER_CREDS_CLEAN) && *ret_shell = (FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) && shell_is_placeholder(p->pw_shell)) ||
(isempty(p->pw_shell) || (FLAGS_SET(flags, USER_CREDS_CLEAN) && (!path_is_valid(p->pw_shell) || !path_is_absolute(p->pw_shell)))
!path_is_valid(p->pw_shell) || ? NULL : p->pw_shell;
!path_is_absolute(p->pw_shell) ||
is_nologin_shell(p->pw_shell))) ? NULL : p->pw_shell;
if (patch_username) if (patch_username)
*username = p->pw_name; *username = p->pw_name;

View File

@ -12,6 +12,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "string-util.h"
/* Users managed by systemd-homed. See https://systemd.io/UIDS-GIDS for details how this range fits into the rest of the world */ /* Users managed by systemd-homed. See https://systemd.io/UIDS-GIDS for details how this range fits into the rest of the world */
#define HOME_UID_MIN ((uid_t) 60001) #define HOME_UID_MIN ((uid_t) 60001)
#define HOME_UID_MAX ((uid_t) 60513) #define HOME_UID_MAX ((uid_t) 60513)
@ -36,10 +38,20 @@ static inline int parse_gid(const char *s, gid_t *ret_gid) {
char* getlogname_malloc(void); char* getlogname_malloc(void);
char* getusername_malloc(void); char* getusername_malloc(void);
const char* default_root_shell_at(int rfd);
const char* default_root_shell(const char *root);
bool is_nologin_shell(const char *shell);
static inline bool shell_is_placeholder(const char *shell) {
return isempty(shell) || is_nologin_shell(shell);
}
typedef enum UserCredsFlags { typedef enum UserCredsFlags {
USER_CREDS_PREFER_NSS = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */ USER_CREDS_PREFER_NSS = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */
USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */ USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */
USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */ USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */
USER_CREDS_SUPPRESS_PLACEHOLDER = 1 << 3, /* suppress home and/or shell fields if value is placeholder (root/empty/nologin) */
} UserCredsFlags; } UserCredsFlags;
int get_user_creds(const char **username, uid_t *ret_uid, gid_t *ret_gid, const char **ret_home, const char **ret_shell, UserCredsFlags flags); int get_user_creds(const char **username, uid_t *ret_uid, gid_t *ret_gid, const char **ret_home, const char **ret_shell, UserCredsFlags flags);
@ -125,10 +137,6 @@ int fgetsgent_sane(FILE *stream, struct sgrp **sg);
int putsgent_sane(const struct sgrp *sg, FILE *stream); int putsgent_sane(const struct sgrp *sg, FILE *stream);
#endif #endif
bool is_nologin_shell(const char *shell);
const char* default_root_shell_at(int rfd);
const char* default_root_shell(const char *root);
int is_this_me(const char *username); int is_this_me(const char *username);
const char* get_home_root(void); const char* get_home_root(void);

View File

@ -855,9 +855,6 @@ static int get_fixed_user(
assert(user_or_uid); assert(user_or_uid);
assert(ret_username); assert(ret_username);
/* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway
* (i.e. are "/" or "/bin/nologin"). */
r = get_user_creds(&user_or_uid, ret_uid, ret_gid, ret_home, ret_shell, USER_CREDS_CLEAN); r = get_user_creds(&user_or_uid, ret_uid, ret_gid, ret_home, ret_shell, USER_CREDS_CLEAN);
if (r < 0) if (r < 0)
return r; return r;
@ -1883,7 +1880,10 @@ static int build_environment(
} }
} }
if (home && set_user_login_env) { /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway
* (i.e. are "/" or "/bin/nologin"). */
if (home && set_user_login_env && !empty_or_root(home)) {
x = strjoin("HOME=", home); x = strjoin("HOME=", home);
if (!x) if (!x)
return -ENOMEM; return -ENOMEM;
@ -1892,7 +1892,7 @@ static int build_environment(
our_env[n_env++] = x; our_env[n_env++] = x;
} }
if (shell && set_user_login_env) { if (shell && set_user_login_env && !shell_is_placeholder(shell)) {
x = strjoin("SHELL=", shell); x = strjoin("SHELL=", shell);
if (!x) if (!x)
return -ENOMEM; return -ENOMEM;
@ -3471,20 +3471,16 @@ static int apply_working_directory(
const ExecContext *context, const ExecContext *context,
const ExecParameters *params, const ExecParameters *params,
ExecRuntime *runtime, ExecRuntime *runtime,
const char *home, const char *home) {
int *exit_status) {
const char *wd; const char *wd;
int r; int r;
assert(context); assert(context);
assert(exit_status);
if (context->working_directory_home) { if (context->working_directory_home) {
if (!home) { if (!home)
*exit_status = EXIT_CHDIR;
return -ENXIO; return -ENXIO;
}
wd = home; wd = home;
} else } else
@ -3503,13 +3499,7 @@ static int apply_working_directory(
if (r >= 0) if (r >= 0)
r = RET_NERRNO(fchdir(dfd)); r = RET_NERRNO(fchdir(dfd));
} }
return context->working_directory_missing_ok ? 0 : r;
if (r < 0 && !context->working_directory_missing_ok) {
*exit_status = EXIT_CHDIR;
return r;
}
return 0;
} }
static int apply_root_directory( static int apply_root_directory(
@ -3785,7 +3775,7 @@ static int acquire_home(const ExecContext *c, const char **home, char **ret_buf)
if (!c->working_directory_home) if (!c->working_directory_home)
return 0; return 0;
if (c->dynamic_user) if (c->dynamic_user || (c->user && is_this_me(c->user) <= 0))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
r = get_home_dir(ret_buf); r = get_home_dir(ret_buf);
@ -4543,7 +4533,7 @@ int exec_invoke(
r = acquire_home(context, &home, &home_buffer); r = acquire_home(context, &home, &home_buffer);
if (r < 0) { if (r < 0) {
*exit_status = EXIT_CHDIR; *exit_status = EXIT_CHDIR;
return log_exec_error_errno(context, params, r, "Failed to determine $HOME for user: %m"); return log_exec_error_errno(context, params, r, "Failed to determine $HOME for the invoking user: %m");
} }
/* If a socket is connected to STDIN/STDOUT/STDERR, we must drop O_NONBLOCK */ /* If a socket is connected to STDIN/STDOUT/STDERR, we must drop O_NONBLOCK */
@ -5382,9 +5372,11 @@ int exec_invoke(
* running this service might have the correct privilege to change to the working directory. Also, it * running this service might have the correct privilege to change to the working directory. Also, it
* is absolutely 💣 crucial 💣 we applied all mount namespacing rearrangements before this, so that * is absolutely 💣 crucial 💣 we applied all mount namespacing rearrangements before this, so that
* the cwd cannot be used to pin directories outside of the sandbox. */ * the cwd cannot be used to pin directories outside of the sandbox. */
r = apply_working_directory(context, params, runtime, home, exit_status); r = apply_working_directory(context, params, runtime, home);
if (r < 0) if (r < 0) {
*exit_status = EXIT_CHDIR;
return log_exec_error_errno(context, params, r, "Changing to the requested working directory failed: %m"); return log_exec_error_errno(context, params, r, "Changing to the requested working directory failed: %m");
}
if (needs_sandboxing) { if (needs_sandboxing) {
/* Apply other MAC contexts late, but before seccomp syscall filtering, as those should really be last to /* Apply other MAC contexts late, but before seccomp syscall filtering, as those should really be last to

View File

@ -193,7 +193,7 @@ int enroll_fido2(
fflush(stdout); fflush(stdout);
fprintf(stderr, fprintf(stderr,
"\nPlease save this FIDO2 credential ID. It is required when unloocking the volume\n" "\nPlease save this FIDO2 credential ID. It is required when unlocking the volume\n"
"using the associated FIDO2 keyslot which we just created. To configure automatic\n" "using the associated FIDO2 keyslot which we just created. To configure automatic\n"
"unlocking using this FIDO2 token, add an appropriate entry to your /etc/crypttab\n" "unlocking using this FIDO2 token, add an appropriate entry to your /etc/crypttab\n"
"file, see %s for details.\n", link); "file, see %s for details.\n", link);

View File

@ -427,6 +427,9 @@ int wipe_slots(struct crypt_device *cd,
for (size_t i = n_ordered_slots; i > 0; i--) { for (size_t i = n_ordered_slots; i > 0; i--) {
r = crypt_keyslot_destroy(cd, ordered_slots[i - 1]); r = crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
if (r < 0) { if (r < 0) {
if (r == -ENOENT)
log_warning_errno(r, "Failed to wipe non-existent slot %i, continuing.", ordered_slots[i - 1]);
else
log_warning_errno(r, "Failed to wipe slot %i, continuing: %m", ordered_slots[i - 1]); log_warning_errno(r, "Failed to wipe slot %i, continuing: %m", ordered_slots[i - 1]);
if (ret == 0) if (ret == 0)
ret = r; ret = r;

View File

@ -750,7 +750,7 @@ static int ndisc_option_parse_route(Set **options, size_t offset, size_t len, co
usec_t lifetime = unaligned_be32_sec_to_usec(opt + 4, /* max_as_infinity = */ true); usec_t lifetime = unaligned_be32_sec_to_usec(opt + 4, /* max_as_infinity = */ true);
struct in6_addr prefix; struct in6_addr prefix;
memcpy(&prefix, opt + 8, len - 8); memcpy_safe(&prefix, opt + 8, len - 8);
in6_addr_mask(&prefix, prefixlen); in6_addr_mask(&prefix, prefixlen);
return ndisc_option_add_route(options, offset, preference, prefixlen, &prefix, lifetime); return ndisc_option_add_route(options, offset, preference, prefixlen, &prefix, lifetime);

View File

@ -1033,12 +1033,14 @@ global:
sd_varlink_server_listen_fd; sd_varlink_server_listen_fd;
sd_varlink_server_loop_auto; sd_varlink_server_loop_auto;
sd_varlink_server_new; sd_varlink_server_new;
sd_varlink_server_ref;
sd_varlink_server_set_connections_max; sd_varlink_server_set_connections_max;
sd_varlink_server_set_connections_per_uid_max; sd_varlink_server_set_connections_per_uid_max;
sd_varlink_server_set_description; sd_varlink_server_set_description;
sd_varlink_server_set_exit_on_idle; sd_varlink_server_set_exit_on_idle;
sd_varlink_server_set_userdata; sd_varlink_server_set_userdata;
sd_varlink_server_shutdown; sd_varlink_server_shutdown;
sd_varlink_server_unref;
sd_varlink_set_allow_fd_passing_input; sd_varlink_set_allow_fd_passing_input;
sd_varlink_set_allow_fd_passing_output; sd_varlink_set_allow_fd_passing_output;
sd_varlink_set_description; sd_varlink_set_description;

View File

@ -3265,7 +3265,7 @@ static sd_varlink_server* varlink_server_destroy(sd_varlink_server *s) {
return mfree(s); return mfree(s);
} }
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_varlink_server, sd_varlink_server, varlink_server_destroy); DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_varlink_server, sd_varlink_server, varlink_server_destroy);
static int validate_connection(sd_varlink_server *server, const struct ucred *ucred) { static int validate_connection(sd_varlink_server *server, const struct ucred *ucred) {
int allowed = -1; int allowed = -1;

View File

@ -642,7 +642,7 @@ static bool netdev_can_set_mac(NetDev *netdev, const struct hw_addr_data *hw_add
if (hw_addr_equal(&link->hw_addr, hw_addr)) if (hw_addr_equal(&link->hw_addr, hw_addr))
return false; /* Unchanged, not necessary to set. */ return false; /* Unchanged, not necessary to set. */
/* Soem netdevs refuse to update MAC address even if the interface is not running, e.g. ipvlan. /* Some netdevs refuse to update MAC address even if the interface is not running, e.g. ipvlan.
* Some other netdevs have the IFF_LIVE_ADDR_CHANGE flag and can update update MAC address even if * Some other netdevs have the IFF_LIVE_ADDR_CHANGE flag and can update update MAC address even if
* the interface is running, e.g. dummy. For those cases, use custom checkers. */ * the interface is running, e.g. dummy. For those cases, use custom checkers. */
if (NETDEV_VTABLE(netdev)->can_set_mac) if (NETDEV_VTABLE(netdev)->can_set_mac)

View File

@ -1443,6 +1443,7 @@ int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags) {
} }
typedef struct LinkReconfigurationData { typedef struct LinkReconfigurationData {
Manager *manager;
Link *link; Link *link;
LinkReconfigurationFlag flags; LinkReconfigurationFlag flags;
sd_bus_message *message; sd_bus_message *message;
@ -1473,6 +1474,12 @@ static void link_reconfiguration_data_destroy_callback(LinkReconfigurationData *
} }
if (!data->counter || *data->counter <= 0) { if (!data->counter || *data->counter <= 0) {
/* Update the state files before replying the bus method. Otherwise,
* systemd-networkd-wait-online following networkctl reload/reconfigure may read an
* outdated state file and wrongly handle an interface is already in the configured
* state. */
(void) manager_clean_all(data->manager);
r = sd_bus_reply_method_return(data->message, NULL); r = sd_bus_reply_method_return(data->message, NULL);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to reply for DBus method, ignoring: %m"); log_warning_errno(r, "Failed to reply for DBus method, ignoring: %m");
@ -1521,6 +1528,7 @@ int link_reconfigure_full(Link *link, LinkReconfigurationFlag flags, sd_bus_mess
} }
*data = (LinkReconfigurationData) { *data = (LinkReconfigurationData) {
.manager = link->manager,
.link = link_ref(link), .link = link_ref(link),
.flags = flags, .flags = flags,
.message = sd_bus_message_ref(message), /* message may be NULL, but _ref() works fine. */ .message = sd_bus_message_ref(message), /* message may be NULL, but _ref() works fine. */

View File

@ -1610,7 +1610,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
return 0; return 0;
} }
static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
uint8_t flags, prefixlen; uint8_t flags, prefixlen;
struct in6_addr a; struct in6_addr a;
int r; int r;
@ -1619,6 +1619,14 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
assert(link->network); assert(link->network);
assert(rt); assert(rt);
usec_t lifetime_usec;
r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_usec);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to get prefix lifetime: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
r = sd_ndisc_router_prefix_get_address(rt, &a); r = sd_ndisc_router_prefix_get_address(rt, &a);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get prefix address: %m"); return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
@ -1664,7 +1672,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
return 0; return 0;
} }
static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
_cleanup_(route_unrefp) Route *route = NULL; _cleanup_(route_unrefp) Route *route = NULL;
uint8_t preference, prefixlen; uint8_t preference, prefixlen;
struct in6_addr gateway, dst; struct in6_addr gateway, dst;
@ -1680,6 +1688,9 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get route lifetime from RA: %m"); return log_link_warning_errno(link, r, "Failed to get route lifetime from RA: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
r = sd_ndisc_router_route_get_address(rt, &dst); r = sd_ndisc_router_route_get_address(rt, &dst);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get route destination address: %m"); return log_link_warning_errno(link, r, "Failed to get route destination address: %m");
@ -1712,10 +1723,6 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
} }
r = sd_ndisc_router_route_get_preference(rt, &preference); r = sd_ndisc_router_route_get_preference(rt, &preference);
if (r == -EOPNOTSUPP) {
log_link_debug_errno(link, r, "Received route prefix with unsupported preference, ignoring: %m");
return 0;
}
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get router preference from RA: %m"); return log_link_warning_errno(link, r, "Failed to get router preference from RA: %m");
@ -1759,7 +1766,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_rdnss_compare_func, ndisc_rdnss_compare_func,
free); free);
static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
usec_t lifetime_usec; usec_t lifetime_usec;
const struct in6_addr *a; const struct in6_addr *a;
struct in6_addr router; struct in6_addr router;
@ -1781,6 +1788,9 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
n = sd_ndisc_router_rdnss_get_addresses(rt, &a); n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
if (n < 0) if (n < 0)
return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m"); return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
@ -1851,7 +1861,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_dnssl_compare_func, ndisc_dnssl_compare_func,
free); free);
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
char **l; char **l;
usec_t lifetime_usec; usec_t lifetime_usec;
struct in6_addr router; struct in6_addr router;
@ -1873,6 +1883,9 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get DNSSL lifetime: %m"); return log_link_warning_errno(link, r, "Failed to get DNSSL lifetime: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
r = sd_ndisc_router_dnssl_get_domains(rt, &l); r = sd_ndisc_router_dnssl_get_domains(rt, &l);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get DNSSL addresses: %m"); return log_link_warning_errno(link, r, "Failed to get DNSSL addresses: %m");
@ -1953,7 +1966,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_captive_portal_compare_func, ndisc_captive_portal_compare_func,
ndisc_captive_portal_free); ndisc_captive_portal_free);
static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
_cleanup_(ndisc_captive_portal_freep) NDiscCaptivePortal *new_entry = NULL; _cleanup_(ndisc_captive_portal_freep) NDiscCaptivePortal *new_entry = NULL;
_cleanup_free_ char *captive_portal = NULL; _cleanup_free_ char *captive_portal = NULL;
const char *uri; const char *uri;
@ -1980,6 +1993,9 @@ static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt)
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m"); return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
r = sd_ndisc_router_get_captive_portal(rt, &uri); r = sd_ndisc_router_get_captive_portal(rt, &uri);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m"); return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m");
@ -2068,7 +2084,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_pref64_compare_func, ndisc_pref64_compare_func,
mfree); mfree);
static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
_cleanup_free_ NDiscPREF64 *new_entry = NULL; _cleanup_free_ NDiscPREF64 *new_entry = NULL;
usec_t lifetime_usec; usec_t lifetime_usec;
struct in6_addr a, router; struct in6_addr a, router;
@ -2099,6 +2115,9 @@ static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get pref64 prefix lifetime: %m"); return log_link_warning_errno(link, r, "Failed to get pref64 prefix lifetime: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
if (lifetime_usec == 0) { if (lifetime_usec == 0) {
free(set_remove(link->ndisc_pref64, free(set_remove(link->ndisc_pref64,
&(NDiscPREF64) { &(NDiscPREF64) {
@ -2217,7 +2236,7 @@ static int sd_dns_resolver_copy(const sd_dns_resolver *a, sd_dns_resolver *b) {
return 0; return 0;
} }
static int ndisc_router_process_encrypted_dns(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_encrypted_dns(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
int r; int r;
assert(link); assert(link);
@ -2240,6 +2259,9 @@ static int ndisc_router_process_encrypted_dns(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m"); return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m");
if ((lifetime_usec == 0) != zero_lifetime)
return 0;
r = sd_ndisc_router_encrypted_dns_get_resolver(rt, &res); r = sd_ndisc_router_encrypted_dns_get_resolver(rt, &res);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to get encrypted dns resolvers: %m"); return log_link_warning_errno(link, r, "Failed to get encrypted dns resolvers: %m");
@ -2292,7 +2314,7 @@ static int ndisc_router_process_encrypted_dns(Link *link, sd_ndisc_router *rt) {
return 0; return 0;
} }
static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt, bool zero_lifetime) {
size_t n_captive_portal = 0; size_t n_captive_portal = 0;
int r; int r;
@ -2314,19 +2336,19 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
switch (type) { switch (type) {
case SD_NDISC_OPTION_PREFIX_INFORMATION: case SD_NDISC_OPTION_PREFIX_INFORMATION:
r = ndisc_router_process_prefix(link, rt); r = ndisc_router_process_prefix(link, rt, zero_lifetime);
break; break;
case SD_NDISC_OPTION_ROUTE_INFORMATION: case SD_NDISC_OPTION_ROUTE_INFORMATION:
r = ndisc_router_process_route(link, rt); r = ndisc_router_process_route(link, rt, zero_lifetime);
break; break;
case SD_NDISC_OPTION_RDNSS: case SD_NDISC_OPTION_RDNSS:
r = ndisc_router_process_rdnss(link, rt); r = ndisc_router_process_rdnss(link, rt, zero_lifetime);
break; break;
case SD_NDISC_OPTION_DNSSL: case SD_NDISC_OPTION_DNSSL:
r = ndisc_router_process_dnssl(link, rt); r = ndisc_router_process_dnssl(link, rt, zero_lifetime);
break; break;
case SD_NDISC_OPTION_CAPTIVE_PORTAL: case SD_NDISC_OPTION_CAPTIVE_PORTAL:
if (n_captive_portal > 0) { if (n_captive_portal > 0) {
@ -2336,15 +2358,15 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
n_captive_portal++; n_captive_portal++;
continue; continue;
} }
r = ndisc_router_process_captive_portal(link, rt); r = ndisc_router_process_captive_portal(link, rt, zero_lifetime);
if (r > 0) if (r > 0)
n_captive_portal++; n_captive_portal++;
break; break;
case SD_NDISC_OPTION_PREF64: case SD_NDISC_OPTION_PREF64:
r = ndisc_router_process_pref64(link, rt); r = ndisc_router_process_pref64(link, rt, zero_lifetime);
break; break;
case SD_NDISC_OPTION_ENCRYPTED_DNS: case SD_NDISC_OPTION_ENCRYPTED_DNS:
r = ndisc_router_process_encrypted_dns(link, rt); r = ndisc_router_process_encrypted_dns(link, rt, zero_lifetime);
break; break;
} }
if (r < 0 && r != -EBADMSG) if (r < 0 && r != -EBADMSG)
@ -2652,10 +2674,6 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return r; return r;
r = ndisc_router_process_default(link, rt);
if (r < 0)
return r;
r = ndisc_router_process_reachable_time(link, rt); r = ndisc_router_process_reachable_time(link, rt);
if (r < 0) if (r < 0)
return r; return r;
@ -2672,7 +2690,15 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return r; return r;
r = ndisc_router_process_options(link, rt); r = ndisc_router_process_options(link, rt, /* zero_lifetime = */ true);
if (r < 0)
return r;
r = ndisc_router_process_default(link, rt);
if (r < 0)
return r;
r = ndisc_router_process_options(link, rt, /* zero_lifetime = */ false);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -50,6 +50,7 @@ static int add_syscall_filters(
{ CAP_IPC_LOCK, "@memlock" }, { CAP_IPC_LOCK, "@memlock" },
/* Plus a good set of additional syscalls which are not part of any of the groups above */ /* Plus a good set of additional syscalls which are not part of any of the groups above */
{ 0, "arm_fadvise64_64" },
{ 0, "brk" }, { 0, "brk" },
{ 0, "capget" }, { 0, "capget" },
{ 0, "capset" }, { 0, "capset" },

View File

@ -2297,7 +2297,8 @@ static int start_transient_scope(sd_bus *bus) {
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS); r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell,
USER_CREDS_CLEAN|USER_CREDS_SUPPRESS_PLACEHOLDER|USER_CREDS_PREFER_NSS);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user); return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);

View File

@ -46,13 +46,17 @@ static bool argv_has_at(pid_t pid) {
return c == '@'; return c == '@';
} }
static bool is_survivor_cgroup(const PidRef *pid) { static bool is_in_survivor_cgroup(const PidRef *pid) {
_cleanup_free_ char *cgroup_path = NULL; _cleanup_free_ char *cgroup_path = NULL;
int r; int r;
assert(pidref_is_set(pid)); assert(pidref_is_set(pid));
r = cg_pidref_get_path(/* root= */ NULL, pid, &cgroup_path); r = cg_pidref_get_path(/* root= */ NULL, pid, &cgroup_path);
if (r == -EUNATCH) {
log_warning_errno(r, "Process " PID_FMT " appears to originate in foreign namespace, ignoring.", pid->pid);
return true;
}
if (r < 0) { if (r < 0) {
log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid->pid); log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid->pid);
return false; return false;
@ -86,7 +90,7 @@ static bool ignore_proc(const PidRef *pid, bool warn_rootfs) {
return true; /* also ignore processes where we can't determine this */ return true; /* also ignore processes where we can't determine this */
/* Ignore processes that are part of a cgroup marked with the user.survive_final_kill_signal xattr */ /* Ignore processes that are part of a cgroup marked with the user.survive_final_kill_signal xattr */
if (is_survivor_cgroup(pid)) if (is_in_survivor_cgroup(pid))
return true; return true;
r = pidref_get_uid(pid, &uid); r = pidref_get_uid(pid, &uid);

View File

@ -28,21 +28,28 @@ const char* user_record_state_color(const char *state) {
return NULL; return NULL;
} }
static void dump_self_modifiable(const char *heading, char **field, const char **value) { static void dump_self_modifiable(
const char *heading,
char **field,
const char **value) {
assert(heading); assert(heading);
/* Helper function for printing the various self_modifiable_* fields from the user record */ /* Helper function for printing the various self_modifiable_* fields from the user record */
if (strv_isempty((char**) value)) if (!value)
/* Case 1: the array is explicitly set to be empty by the administrator */ /* Case 1: no value is set and no default either */
printf("%13s %sDisabled by Administrator%s\n", heading, ansi_highlight_red(), ansi_normal()); printf("%13s %snone%s\n", heading, ansi_highlight(), ansi_normal());
else if (strv_isempty((char**) value))
/* Case 2: the array is explicitly set to empty by the administrator */
printf("%13s %sdisabled by administrator%s\n", heading, ansi_highlight_red(), ansi_normal());
else if (!field) else if (!field)
/* Case 2: we have values, but the field is NULL. This means that we're using the defaults. /* Case 3: we have values, but the field is NULL. This means that we're using the defaults.
* We list them anyways, because they're security-sensitive to the administrator */ * We list them anyways, because they're security-sensitive to the administrator */
STRV_FOREACH(i, value) STRV_FOREACH(i, value)
printf("%13s %s%s%s\n", i == value ? heading : "", ansi_grey(), *i, ansi_normal()); printf("%13s %s%s%s\n", i == value ? heading : "", ansi_grey(), *i, ansi_normal());
else else
/* Case 3: we have a list provided by the administrator */ /* Case 4: we have a list provided by the administrator */
STRV_FOREACH(i, value) STRV_FOREACH(i, value)
printf("%13s %s\n", i == value ? heading : "", *i); printf("%13s %s\n", i == value ? heading : "", *i);
} }

View File

@ -2165,8 +2165,15 @@ const char** user_record_self_modifiable_fields(UserRecord *h) {
assert(h); assert(h);
/* Note: if the self_modifiable_fields field in UserRecord is NULL we'll apply a default, if we have
* one. If it is a non-NULL empty strv, we'll report it as explicit empty list. When the field is
* NULL and we have no default list we'll return NULL. */
/* Note that we intentionally distinguish between NULL and an empty array here */ /* Note that we intentionally distinguish between NULL and an empty array here */
return (const char**) h->self_modifiable_fields ?: (const char**) default_fields; if (h->self_modifiable_fields)
return (const char**) h->self_modifiable_fields;
return user_record_disposition(h) == USER_REGULAR ? (const char**) default_fields : NULL;
} }
const char** user_record_self_modifiable_blobs(UserRecord *h) { const char** user_record_self_modifiable_blobs(UserRecord *h) {
@ -2180,7 +2187,10 @@ const char** user_record_self_modifiable_blobs(UserRecord *h) {
assert(h); assert(h);
/* Note that we intentionally distinguish between NULL and an empty array here */ /* Note that we intentionally distinguish between NULL and an empty array here */
return (const char**) h->self_modifiable_blobs ?: (const char**) default_blobs; if (h->self_modifiable_blobs)
return (const char**) h->self_modifiable_blobs;
return user_record_disposition(h) == USER_REGULAR ? (const char**) default_blobs : NULL;
} }
const char** user_record_self_modifiable_privileged(UserRecord *h) { const char** user_record_self_modifiable_privileged(UserRecord *h) {
@ -2201,7 +2211,10 @@ const char** user_record_self_modifiable_privileged(UserRecord *h) {
assert(h); assert(h);
/* Note that we intentionally distinguish between NULL and an empty array here */ /* Note that we intentionally distinguish between NULL and an empty array here */
return (const char**) h->self_modifiable_privileged ?: (const char**) default_fields; if (h->self_modifiable_privileged)
return (const char**) h->self_modifiable_privileged;
return user_record_disposition(h) == USER_REGULAR ? (const char**) default_fields : NULL;
} }
static int remove_self_modifiable_json_fields_common(UserRecord *current, sd_json_variant **target) { static int remove_self_modifiable_json_fields_common(UserRecord *current, sd_json_variant **target) {

View File

@ -245,7 +245,7 @@ static int add_vsock_socket(
if (r < 0) if (r < 0)
return r; return r;
log_info("Binding SSH to AF_VSOCK vsock::22.\n" log_debug("Binding SSH to AF_VSOCK vsock::22.\n"
"→ connect via 'ssh vsock/%u' from host", local_cid); "→ connect via 'ssh vsock/%u' from host", local_cid);
return 0; return 0;
} }
@ -280,7 +280,7 @@ static int add_local_unix_socket(
if (r < 0) if (r < 0)
return r; return r;
log_info("Binding SSH to AF_UNIX socket /run/ssh-unix-local/socket.\n" log_debug("Binding SSH to AF_UNIX socket /run/ssh-unix-local/socket.\n"
"→ connect via 'ssh .host' locally"); "→ connect via 'ssh .host' locally");
return 0; return 0;
} }
@ -336,7 +336,7 @@ static int add_export_unix_socket(
if (r < 0) if (r < 0)
return r; return r;
log_info("Binding SSH to AF_UNIX socket /run/host/unix-export/ssh\n" log_debug("Binding SSH to AF_UNIX socket /run/host/unix-export/ssh\n"
"→ connect via 'ssh unix/run/systemd/nspawn/unix-export/\?\?\?/ssh' from host"); "→ connect via 'ssh unix/run/systemd/nspawn/unix-export/\?\?\?/ssh' from host");
return 0; return 0;
@ -387,7 +387,7 @@ static int add_extra_sockets(
if (r < 0) if (r < 0)
return r; return r;
log_info("Binding SSH to socket %s.", *i); log_debug("Binding SSH to socket %s.", *i);
n++; n++;
} }
@ -462,7 +462,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
_cleanup_free_ char *sshd_binary = NULL; _cleanup_free_ char *sshd_binary = NULL;
r = find_executable("sshd", &sshd_binary); r = find_executable("sshd", &sshd_binary);
if (r == -ENOENT) { if (r == -ENOENT) {
log_info("Disabling SSH generator logic, since sshd is not installed."); log_debug("Disabling SSH generator logic, since sshd is not installed.");
return 0; return 0;
} }
if (r < 0) if (r < 0)

View File

@ -724,7 +724,7 @@ static void print_status_info(
printf(" Tasks: %" PRIu64, i->tasks_current); printf(" Tasks: %" PRIu64, i->tasks_current);
if (i->tasks_max != UINT64_MAX) if (i->tasks_max != UINT64_MAX)
printf(" (limit: %" PRIu64 ")\n", i->tasks_max); printf("%s (limit: %" PRIu64 ")%s\n", ansi_grey(), i->tasks_max, ansi_normal());
else else
printf("\n"); printf("\n");
} }

View File

@ -47,6 +47,7 @@ char *arg_root = NULL;
static char *arg_image = NULL; static char *arg_image = NULL;
static bool arg_reboot = false; static bool arg_reboot = false;
static char *arg_component = NULL; static char *arg_component = NULL;
static char *arg_stream = NULL;
static int arg_verify = -1; static int arg_verify = -1;
static ImagePolicy *arg_image_policy = NULL; static ImagePolicy *arg_image_policy = NULL;
static bool arg_offline = false; static bool arg_offline = false;
@ -56,6 +57,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
STATIC_DESTRUCTOR_REGISTER(arg_component, freep); STATIC_DESTRUCTOR_REGISTER(arg_component, freep);
STATIC_DESTRUCTOR_REGISTER(arg_stream, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep); STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep);
@ -180,7 +182,54 @@ static int context_read_definitions(Context *c, const char* node) {
if (arg_definitions) if (arg_definitions)
dirs = strv_new(arg_definitions); dirs = strv_new(arg_definitions);
else if (arg_component) { else if (arg_stream) {
/* Ultimately we end up with a search path along the lines of: /etc/sysupdate.d/,
* /run/sysupdate.d/, /var/cache/systemd/sysupdate@<stream>.d, /usr/lib/sysupdate@<stream>.d.
* This is very unusual! It seems wrong! But this is the correct behavior. When a
* `systemd-sysupdate --stream=` update is completed, /usr/lib/sysupdate@<stream>.d (or its
* /var/cache alternative) turns into /usr/lib/sysupdate.d, but the admin overrides remain
* untouched. So if we did this any differently, we'd end up in a situation where the admin's
* settings are ignored when first installing a major upgrade but then suddenly considered
* again once the update is completed. In my opinion, that behavior would be more unexpected
* and dangerous than what is implemented here!
*
* Is this a big and surprising footgun for the admin? Yes. But frankly, so is overriding
* anything relating to sysupdate. If an admin has overrides that do anything other than
* turning on/off optional features, they've already aimed a ballistic missile at their
* installation. It'll detonate either immediately when trying to switch streams (as
* implemented now), or when updating to the first patch of the new stream (the alternative);
* the installation is doomed either way. And failing immediately during a major OS upgrade
* seems a lot more preferable, and something that admins will be more prepared for, than a
* subsequent security patch suddenly bricking installations. */
char **admin = STRV_MAKE(CONF_PATHS_ADMIN("sysupdate.d"));
char **system = STRV_MAKE("/var/cache/systemd/", CONF_PATHS_SYSTEM(""));
size_t i = 0;
dirs = new0(char*, strv_length(admin) + strv_length(system) + 1);
if (!dirs)
return log_oom();
STRV_FOREACH(dir, admin) {
char *d;
d = strdup(*dir);
if (!d)
return log_oom();
dirs[i++] = d;
}
STRV_FOREACH(dir, system) {
char *j;
j = strjoin(*dir, "sysupdate@", arg_stream, ".d");
if (!j)
return log_oom();
dirs[i++] = j;
}
} else if (arg_component) {
char **l = CONF_PATHS_STRV(""); char **l = CONF_PATHS_STRV("");
size_t i = 0; size_t i = 0;
@ -247,6 +296,11 @@ static int context_read_definitions(Context *c, const char* node) {
"No transfer definitions for component '%s' found.", "No transfer definitions for component '%s' found.",
arg_component); arg_component);
if (arg_stream)
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
"No transfer definitions for stream '%s' found.",
arg_stream);
return log_error_errno(SYNTHETIC_ERRNO(ENOENT), return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
"No transfer definitions found."); "No transfer definitions found.");
} }
@ -1532,22 +1586,45 @@ static int component_name_valid(const char *c) {
return filename_is_valid(j); return filename_is_valid(j);
} }
static int verb_components(int argc, char **argv, void *userdata) { static int stream_name_valid(const char *s) {
_cleanup_free_ char *j = NULL;
/* See if the specified string enclosed in the directory prefix+suffix would be a valid file name */
if (isempty(s))
return false;
if (string_has_cc(s, NULL))
return false;
if (!utf8_is_valid(s))
return false;
j = strjoin("sysupdate@", s, ".d");
if (!j)
return -ENOMEM;
return filename_is_valid(j);
}
static int walk_search_paths(char **paths, bool component, char ***ret, bool *ret_has_default) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL; _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
_cleanup_set_free_ Set *names = NULL; _cleanup_set_free_ Set *names = NULL;
_cleanup_free_ char **z = NULL; /* We use simple free() rather than strv_free() here, since set_free() will free the strings for us */ _cleanup_free_ char **names_strv = NULL; /* free() b/c the set still owns the values */
char **l = CONF_PATHS_STRV(""); _cleanup_strv_free_ char **names_dup = NULL;
bool has_default_component = false; bool has_default = false;
int r; int r;
assert(argc <= 1); assert(paths);
assert(ret);
assert(ret_has_default);
r = process_image(/* ro= */ false, &mounted_dir, &loop_device); r = process_image(/* ro= */ false, &mounted_dir, &loop_device);
if (r < 0) if (r < 0)
return r; return r;
STRV_FOREACH(i, l) { STRV_FOREACH(i, paths) {
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
@ -1577,11 +1654,11 @@ static int verb_components(int argc, char **argv, void *userdata) {
continue; continue;
if (streq(de->d_name, "sysupdate.d")) { if (streq(de->d_name, "sysupdate.d")) {
has_default_component = true; has_default = true;
continue; continue;
} }
e = startswith(de->d_name, "sysupdate."); e = startswith(de->d_name, component ? "sysupdate." : "sysupdate@");
if (!e) if (!e)
continue; continue;
@ -1593,26 +1670,51 @@ static int verb_components(int argc, char **argv, void *userdata) {
if (!n) if (!n)
return log_oom(); return log_oom();
if (component)
r = component_name_valid(n); r = component_name_valid(n);
else
r = stream_name_valid(n);
if (r < 0) if (r < 0)
return log_error_errno(r, "Unable to validate component name: %m"); return log_error_errno(r, "Unable to validate %s name: %m",
component ? "component" : "stream");
if (r == 0) if (r == 0)
continue; continue;
r = set_ensure_consume(&names, &string_hash_ops_free, TAKE_PTR(n)); r = set_ensure_consume(&names, &string_hash_ops_free, TAKE_PTR(n));
if (r < 0 && r != -EEXIST) if (r < 0 && r != -EEXIST)
return log_error_errno(r, "Failed to add component to set: %m"); return log_error_errno(r, "Failed to add %s to set: %m",
component ? "component" : "stream");
} }
} }
z = set_get_strv(names); names_strv = set_get_strv(names);
if (!z) if (!names_strv)
return log_oom(); return log_oom();
strv_sort(z); names_dup = strv_copy(names_strv);
if (!names_dup)
return log_oom();
strv_sort(names_dup);
*ret = TAKE_PTR(names_dup);
*ret_has_default = has_default;
return 0;
}
static int verb_components(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **names = NULL;
bool has_default_component = false;
int r;
assert(argc <= 1);
r = walk_search_paths(CONF_PATHS_STRV(""), true, &names, &has_default_component);
if (r < 0)
return r;
if (!sd_json_format_enabled(arg_json_format_flags)) { if (!sd_json_format_enabled(arg_json_format_flags)) {
if (!has_default_component && set_isempty(names)) { if (!has_default_component && strv_isempty(names)) {
log_info("No components defined."); log_info("No components defined.");
return 0; return 0;
} }
@ -1621,13 +1723,53 @@ static int verb_components(int argc, char **argv, void *userdata) {
printf("%s<default>%s\n", printf("%s<default>%s\n",
ansi_highlight(), ansi_normal()); ansi_highlight(), ansi_normal());
STRV_FOREACH(i, z) STRV_FOREACH(i, names)
puts(*i); puts(*i);
} else { } else {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL; _cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_BOOLEAN("default", has_default_component), r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_BOOLEAN("default", has_default_component),
SD_JSON_BUILD_PAIR_STRV("components", z)); SD_JSON_BUILD_PAIR_STRV("components", names));
if (r < 0)
return log_error_errno(r, "Failed to create JSON: %m");
r = sd_json_variant_dump(json, arg_json_format_flags, stdout, NULL);
if (r < 0)
return log_error_errno(r, "Failed to print JSON: %m");
}
return 0;
}
static int verb_streams(int argc, char **argv, void *userdata) {
char **dirs = STRV_MAKE("/var/cache/systemd/", CONF_PATHS_SYSTEM(""));
_cleanup_strv_free_ char **names = NULL;
bool has_default_stream = false;
int r;
assert(argc <= 1);
r = walk_search_paths(dirs, false, &names, &has_default_stream);
if (r < 0)
return r;
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
if (!has_default_stream && strv_isempty(names)) {
log_info("No streams defined.");
return 0;
}
if (has_default_stream)
printf("%s<default>%s\n",
ansi_highlight(), ansi_normal());
STRV_FOREACH(i, names)
puts(*i);
} else {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
r = sd_json_buildo(&json, SD_JSON_BUILD_PAIR_BOOLEAN("default", has_default_stream),
SD_JSON_BUILD_PAIR_STRV("streams", names));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create JSON: %m"); return log_error_errno(r, "Failed to create JSON: %m");
@ -1659,11 +1801,13 @@ static int verb_help(int argc, char **argv, void *userdata) {
" currently booted\n" " currently booted\n"
" reboot Reboot if a newer version is installed than booted\n" " reboot Reboot if a newer version is installed than booted\n"
" components Show list of components\n" " components Show list of components\n"
" streams Show list of streams\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" --version Show package version\n" " --version Show package version\n"
"\n%3$sOptions:%4$s\n" "\n%3$sOptions:%4$s\n"
" -C --component=NAME Select component to update\n" " -C --component=NAME Select component to update\n"
" --definitions=DIR Find transfer definitions in specified directory\n" " --definitions=DIR Find transfer definitions in specified directory\n"
" --stream=STREAM Select stream to switch to\n"
" --root=PATH Operate on an alternate filesystem root\n" " --root=PATH Operate on an alternate filesystem root\n"
" --image=PATH Operate on disk image as filesystem root\n" " --image=PATH Operate on disk image as filesystem root\n"
" --image-policy=POLICY\n" " --image-policy=POLICY\n"
@ -1698,6 +1842,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_LEGEND, ARG_NO_LEGEND,
ARG_SYNC, ARG_SYNC,
ARG_DEFINITIONS, ARG_DEFINITIONS,
ARG_STREAM,
ARG_JSON, ARG_JSON,
ARG_ROOT, ARG_ROOT,
ARG_IMAGE, ARG_IMAGE,
@ -1714,6 +1859,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "definitions", required_argument, NULL, ARG_DEFINITIONS }, { "definitions", required_argument, NULL, ARG_DEFINITIONS },
{ "stream", required_argument, NULL, ARG_STREAM },
{ "instances-max", required_argument, NULL, 'm' }, { "instances-max", required_argument, NULL, 'm' },
{ "sync", required_argument, NULL, ARG_SYNC }, { "sync", required_argument, NULL, ARG_SYNC },
{ "json", required_argument, NULL, ARG_JSON }, { "json", required_argument, NULL, ARG_JSON },
@ -1770,6 +1916,24 @@ static int parse_argv(int argc, char *argv[]) {
return r; return r;
break; break;
case ARG_STREAM:
if (isempty(optarg)) {
arg_stream = mfree(arg_stream);
break;
}
r = stream_name_valid(optarg);
if (r < 0)
return log_error_errno(r, "Failed to determine if stream name is valid: %m");
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Stream name invalid: %s", optarg);
r = free_and_strdup_warn(&arg_stream, optarg);
if (r < 0)
return r;
break;
case ARG_JSON: case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags); r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0) if (r <= 0)
@ -1856,6 +2020,12 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_definitions && arg_component) if (arg_definitions && arg_component)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --definitions= and --component= switches may not be combined."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --definitions= and --component= switches may not be combined.");
if (arg_definitions && arg_stream)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --definitions= and --stream= switches may not be combined.");
if (arg_component && arg_stream)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --component= and --stream= switches may not be combined.");
return 1; return 1;
} }
@ -1864,6 +2034,7 @@ static int sysupdate_main(int argc, char *argv[]) {
static const Verb verbs[] = { static const Verb verbs[] = {
{ "list", VERB_ANY, 2, VERB_DEFAULT, verb_list }, { "list", VERB_ANY, 2, VERB_DEFAULT, verb_list },
{ "components", VERB_ANY, 1, 0, verb_components }, { "components", VERB_ANY, 1, 0, verb_components },
{ "streams", VERB_ANY, 1, 0, verb_streams },
{ "features", VERB_ANY, 2, 0, verb_features }, { "features", VERB_ANY, 2, 0, verb_features },
{ "check-new", VERB_ANY, 1, 0, verb_check_new }, { "check-new", VERB_ANY, 1, 0, verb_check_new },
{ "update", VERB_ANY, 2, 0, verb_update }, { "update", VERB_ANY, 2, 0, verb_update },

View File

@ -105,9 +105,9 @@ int main(void) {
} }
for (j = 0; symbols_from_source[j].name; j++) { for (j = 0; symbols_from_source[j].name; j++) {
struct symbol*n = bsearch(symbols_from_source+j, symbols_from_source, sizeof(symbols_from_sym)/sizeof(symbols_from_sym[0])-1, sizeof(symbols_from_sym[0]), sort_callback); struct symbol *n = bsearch(symbols_from_source+j, symbols_from_sym, sizeof(symbols_from_sym)/sizeof(symbols_from_sym[0])-1, sizeof(symbols_from_sym[0]), sort_callback);
if (!n) if (!n)
printf("Found in sources, but not in symbol file: %s\\n", symbols_from_source[i].name); printf("Found in sources, but not in symbol file: %s\\n", symbols_from_source[j].name);
} }
return i == j ? EXIT_SUCCESS : EXIT_FAILURE; return i == j ? EXIT_SUCCESS : EXIT_FAILURE;

View File

@ -7,24 +7,26 @@ TEST(audit_loginuid_from_pid) {
_cleanup_(pidref_done) PidRef self = PIDREF_NULL, pid1 = PIDREF_NULL; _cleanup_(pidref_done) PidRef self = PIDREF_NULL, pid1 = PIDREF_NULL;
int r; int r;
assert_se(pidref_set_self(&self) >= 0); ASSERT_OK(pidref_set_self(&self));
assert_se(pidref_set_pid(&pid1, 1) >= 0); ASSERT_OK(pidref_set_pid(&pid1, 1));
uid_t uid; uid_t uid;
r = audit_loginuid_from_pid(&self, &uid); r = audit_loginuid_from_pid(&self, &uid);
assert_se(r >= 0 || r == -ENODATA); if (r != -ENODATA)
ASSERT_OK(r);
if (r >= 0) if (r >= 0)
log_info("self audit login uid: " UID_FMT, uid); log_info("self audit login uid: " UID_FMT, uid);
assert_se(audit_loginuid_from_pid(&pid1, &uid) == -ENODATA); ASSERT_ERROR(audit_loginuid_from_pid(&pid1, &uid), ENODATA);
uint32_t sessionid; uint32_t sessionid;
r = audit_session_from_pid(&self, &sessionid); r = audit_session_from_pid(&self, &sessionid);
assert_se(r >= 0 || r == -ENODATA); if (r != -ENODATA)
ASSERT_OK(r);
if (r >= 0) if (r >= 0)
log_info("self audit session id: %" PRIu32, sessionid); log_info("self audit session id: %" PRIu32, sessionid);
assert_se(audit_session_from_pid(&pid1, &sessionid) == -ENODATA); ASSERT_ERROR(audit_session_from_pid(&pid1, &sessionid), ENODATA);
} }
static int intro(void) { static int intro(void) {

View File

@ -9,7 +9,7 @@
({ \ ({ \
typeof(ret) _r = (ret); \ typeof(ret) _r = (ret); \
user_record_unref(*_r); \ user_record_unref(*_r); \
assert_se(user_record_build((ret), SD_JSON_BUILD_OBJECT(__VA_ARGS__)) >= 0); \ assert_se(user_record_build((ret), SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR_STRING("disposition", "regular"), __VA_ARGS__)) >= 0); \
0; \ 0; \
}) })

View File

@ -363,7 +363,7 @@ def test_config_priority(tmp_path):
assert opts.pcr_public_keys == ['PKEY2', 'some/path8'] assert opts.pcr_public_keys == ['PKEY2', 'some/path8']
assert opts.pcr_banks == ['SHA1', 'SHA256'] assert opts.pcr_banks == ['SHA1', 'SHA256']
assert opts.signing_engine == 'ENGINE' assert opts.signing_engine == 'ENGINE'
assert opts.signtool == ukify.SbSign # from args assert opts.signtool == 'sbsign' # from args
assert opts.sb_key == 'SBKEY' # from args assert opts.sb_key == 'SBKEY' # from args
assert opts.sb_cert == pathlib.Path('SBCERT') # from args assert opts.sb_cert == pathlib.Path('SBCERT') # from args
assert opts.sb_certdir == 'some/path5' # from config assert opts.sb_certdir == 'some/path5' # from config

View File

@ -267,7 +267,7 @@ class UkifyConfig:
signing_engine: Optional[str] signing_engine: Optional[str]
signing_provider: Optional[str] signing_provider: Optional[str]
certificate_provider: Optional[str] certificate_provider: Optional[str]
signtool: Optional[type['SignTool']] signtool: Optional[str]
splash: Optional[Path] splash: Optional[Path]
stub: Path stub: Path
summary: bool summary: bool
@ -466,6 +466,17 @@ class SignTool:
def verify(opts: UkifyConfig) -> bool: def verify(opts: UkifyConfig) -> bool:
raise NotImplementedError() raise NotImplementedError()
@staticmethod
def from_string(name) -> type['SignTool']:
if name == 'pesign':
return PeSign
elif name == 'sbsign':
return SbSign
elif name == 'systemd-sbsign':
return SystemdSbSign
else:
raise ValueError(f'Invalid sign tool: {name!r}')
class PeSign(SignTool): class PeSign(SignTool):
@staticmethod @staticmethod
@ -1141,15 +1152,16 @@ def make_uki(opts: UkifyConfig) -> None:
if opts.linux and sign_args_present: if opts.linux and sign_args_present:
assert opts.signtool is not None assert opts.signtool is not None
signtool = SignTool.from_string(opts.signtool)
if not sign_kernel: if not sign_kernel:
# figure out if we should sign the kernel # figure out if we should sign the kernel
sign_kernel = opts.signtool.verify(opts) sign_kernel = signtool.verify(opts)
if sign_kernel: if sign_kernel:
linux_signed = tempfile.NamedTemporaryFile(prefix='linux-signed') linux_signed = tempfile.NamedTemporaryFile(prefix='linux-signed')
linux = Path(linux_signed.name) linux = Path(linux_signed.name)
opts.signtool.sign(os.fspath(opts.linux), os.fspath(linux), opts=opts) signtool.sign(os.fspath(opts.linux), os.fspath(linux), opts=opts)
if opts.uname is None and opts.linux is not None: if opts.uname is None and opts.linux is not None:
print('Kernel version not specified, starting autodetection 😖.') print('Kernel version not specified, starting autodetection 😖.')
@ -1310,7 +1322,9 @@ def make_uki(opts: UkifyConfig) -> None:
if sign_args_present: if sign_args_present:
assert opts.signtool is not None assert opts.signtool is not None
opts.signtool.sign(os.fspath(unsigned_output), os.fspath(opts.output), opts) signtool = SignTool.from_string(opts.signtool)
signtool.sign(os.fspath(unsigned_output), os.fspath(opts.output), opts)
# We end up with no executable bits, let's reapply them # We end up with no executable bits, let's reapply them
os.umask(umask := os.umask(0)) os.umask(umask := os.umask(0))
@ -1663,26 +1677,6 @@ class ConfigItem:
return (section_name, key, value) return (section_name, key, value)
class SignToolAction(argparse.Action):
def __call__(
self,
parser: argparse.ArgumentParser,
namespace: argparse.Namespace,
values: Union[str, Sequence[Any], None] = None,
option_string: Optional[str] = None,
) -> None:
if values is None:
setattr(namespace, 'signtool', None)
elif values == 'sbsign':
setattr(namespace, 'signtool', SbSign)
elif values == 'pesign':
setattr(namespace, 'signtool', PeSign)
elif values == 'systemd-sbsign':
setattr(namespace, 'signtool', SystemdSbSign)
else:
raise ValueError(f"Unknown signtool '{values}' (this is unreachable)")
VERBS = ('build', 'genkey', 'inspect') VERBS = ('build', 'genkey', 'inspect')
CONFIG_ITEMS = [ CONFIG_ITEMS = [
@ -1856,7 +1850,6 @@ CONFIG_ITEMS = [
ConfigItem( ConfigItem(
'--signtool', '--signtool',
choices=('sbsign', 'pesign', 'systemd-sbsign'), choices=('sbsign', 'pesign', 'systemd-sbsign'),
action=SignToolAction,
dest='signtool', dest='signtool',
help=( help=(
'whether to use sbsign or pesign. It will also be inferred by the other ' 'whether to use sbsign or pesign. It will also be inferred by the other '
@ -2173,24 +2166,24 @@ def finalize_options(opts: argparse.Namespace) -> None:
) )
elif bool(opts.sb_key) and bool(opts.sb_cert): elif bool(opts.sb_key) and bool(opts.sb_cert):
# both param given, infer sbsign and in case it was given, ensure signtool=sbsign # both param given, infer sbsign and in case it was given, ensure signtool=sbsign
if opts.signtool and opts.signtool not in (SbSign, SystemdSbSign): if opts.signtool and opts.signtool not in ('sbsign', 'systemd-sbsign'):
raise ValueError( raise ValueError(
f'Cannot provide --signtool={opts.signtool} with --secureboot-private-key= and --secureboot-certificate=' # noqa: E501 f'Cannot provide --signtool={opts.signtool} with --secureboot-private-key= and --secureboot-certificate=' # noqa: E501
) )
if not opts.signtool: if not opts.signtool:
opts.signtool = SbSign opts.signtool = 'sbsign'
elif bool(opts.sb_cert_name): elif bool(opts.sb_cert_name):
# sb_cert_name given, infer pesign and in case it was given, ensure signtool=pesign # sb_cert_name given, infer pesign and in case it was given, ensure signtool=pesign
if opts.signtool and opts.signtool != PeSign: if opts.signtool and opts.signtool != 'pesign':
raise ValueError( raise ValueError(
f'Cannot provide --signtool={opts.signtool} with --secureboot-certificate-name=' f'Cannot provide --signtool={opts.signtool} with --secureboot-certificate-name='
) )
opts.signtool = PeSign opts.signtool = 'pesign'
if opts.signing_provider and opts.signtool != SystemdSbSign: if opts.signing_provider and opts.signtool != 'systemd-sbsign':
raise ValueError('--signing-provider= can only be used with--signtool=systemd-sbsign') raise ValueError('--signing-provider= can only be used with--signtool=systemd-sbsign')
if opts.certificate_provider and opts.signtool != SystemdSbSign: if opts.certificate_provider and opts.signtool != 'systemd-sbsign':
raise ValueError('--certificate-provider= can only be used with--signtool=systemd-sbsign') raise ValueError('--certificate-provider= can only be used with--signtool=systemd-sbsign')
if opts.sign_kernel and not opts.sb_key and not opts.sb_cert_name: if opts.sign_kernel and not opts.sb_key and not opts.sb_cert_name:

View File

@ -2182,6 +2182,10 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
(void) sd_event_add_signal(event, NULL, (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, NULL); (void) sd_event_add_signal(event, NULL, (SIGRTMIN+18) | SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, NULL);
r = sd_event_add_memory_pressure(event, NULL, NULL, NULL);
if (r < 0)
log_debug_errno(r, "Failed allocate memory pressure event source, ignoring: %m");
/* Exit when the child exits */ /* Exit when the child exits */
(void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL); (void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL);

View File

@ -1,18 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=router-low
[Network]
IPv6AcceptRA=no
IPv6SendRA=yes
[IPv6SendRA]
# changed from low to high
RouterPreference=high
EmitDNS=no
EmitDomains=no
[IPv6Prefix]
Prefix=2002:da8:1:98::/64
PreferredLifetimeSec=1000s
ValidLifetimeSec=2100s

View File

@ -1,18 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=router-high
[Network]
IPv6AcceptRA=no
IPv6SendRA=yes
[IPv6SendRA]
# changed from high to low
RouterPreference=low
EmitDNS=no
EmitDomains=no
[IPv6Prefix]
Prefix=2002:da8:1:99::/64
PreferredLifetimeSec=1000s
ValidLifetimeSec=2100s

View File

@ -6391,6 +6391,27 @@ class NetworkdRATests(unittest.TestCase, Utilities):
self.check_ipv6_sysctl_attr('client', 'hop_limit', '43') self.check_ipv6_sysctl_attr('client', 'hop_limit', '43')
def check_router_preference(self, suffix, metric_1, preference_1, metric_2, preference_2):
self.wait_online('client:routable')
self.wait_address('client', f'2002:da8:1:99:1034:56ff:fe78:9a{suffix}/64', ipv='-6', timeout_sec=10)
self.wait_address('client', f'2002:da8:1:98:1034:56ff:fe78:9a{suffix}/64', ipv='-6', timeout_sec=10)
self.wait_route('client', rf'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric {metric_1}', ipv='-6', timeout_sec=10)
self.wait_route('client', rf'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric {metric_2}', ipv='-6', timeout_sec=10)
print('### ip -6 route show dev client default')
output = check_output('ip -6 route show dev client default')
print(output)
self.assertRegex(output, rf'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric {metric_1} expires [0-9]*sec pref {preference_1}')
self.assertRegex(output, rf'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric {metric_2} expires [0-9]*sec pref {preference_2}')
for i in [100, 200, 300, 512, 1024, 2048]:
if i not in [metric_1, metric_2]:
self.assertNotIn(f'metric {i} ', output)
for i in ['low', 'medium', 'high']:
if i not in [preference_1, preference_2]:
self.assertNotIn(f'pref {i}', output)
def test_router_preference(self): def test_router_preference(self):
copy_network_unit('25-veth-client.netdev', copy_network_unit('25-veth-client.netdev',
'25-veth-router-high.netdev', '25-veth-router-high.netdev',
@ -6409,72 +6430,47 @@ class NetworkdRATests(unittest.TestCase, Utilities):
networkctl_reconfigure('client') networkctl_reconfigure('client')
self.wait_online('client:routable') self.wait_online('client:routable')
self.check_router_preference('00', 512, 'high', 2048, 'low')
self.wait_address('client', '2002:da8:1:99:1034:56ff:fe78:9a00/64', ipv='-6', timeout_sec=10) # change the map from preference to metric.
self.wait_address('client', '2002:da8:1:98:1034:56ff:fe78:9a00/64', ipv='-6', timeout_sec=10)
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 512', ipv='-6', timeout_sec=10)
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 2048', ipv='-6', timeout_sec=10)
print('### ip -6 route show dev client default')
output = check_output('ip -6 route show dev client default')
print(output)
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 512 expires [0-9]*sec pref high')
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 2048 expires [0-9]*sec pref low')
with open(os.path.join(network_unit_dir, '25-veth-client.network'), mode='a', encoding='utf-8') as f: with open(os.path.join(network_unit_dir, '25-veth-client.network'), mode='a', encoding='utf-8') as f:
f.write('\n[Link]\nMACAddress=12:34:56:78:9a:01\n[IPv6AcceptRA]\nRouteMetric=100:200:300\n') f.write('\n[Link]\nMACAddress=12:34:56:78:9a:01\n[IPv6AcceptRA]\nRouteMetric=100:200:300\n')
networkctl_reload() networkctl_reload()
self.wait_online('client:routable') self.check_router_preference('01', 100, 'high', 300, 'low')
self.wait_address('client', '2002:da8:1:99:1034:56ff:fe78:9a01/64', ipv='-6', timeout_sec=10)
self.wait_address('client', '2002:da8:1:98:1034:56ff:fe78:9a01/64', ipv='-6', timeout_sec=10)
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 100', ipv='-6', timeout_sec=10)
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 300', ipv='-6', timeout_sec=10)
print('### ip -6 route show dev client default')
output = check_output('ip -6 route show dev client default')
print(output)
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 100 expires [0-9]*sec pref high')
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 300 expires [0-9]*sec pref low')
self.assertNotIn('metric 512', output)
self.assertNotIn('metric 2048', output)
# swap the preference (for issue #28439) # swap the preference (for issue #28439)
remove_network_unit('25-veth-router-high.network', '25-veth-router-low.network') with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
copy_network_unit('25-veth-router-high2.network', '25-veth-router-low2.network') f.write('\n[IPv6SendRA]\nRouterPreference=low\n')
with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
f.write('\n[IPv6SendRA]\nRouterPreference=high\n')
networkctl_reload() networkctl_reload()
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 300', ipv='-6', timeout_sec=10) self.check_router_preference('01', 300, 'low', 100, 'high')
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 100', ipv='-6', timeout_sec=10)
print('### ip -6 route show dev client default')
output = check_output('ip -6 route show dev client default')
print(output)
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 300 expires [0-9]*sec pref low')
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 100 expires [0-9]*sec pref high')
self.assertNotRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 100')
self.assertNotRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 300')
self.assertNotIn('metric 512', output)
self.assertNotIn('metric 2048', output)
# Use the same preference, and check if the two routes are not coalesced. See issue #33470. # Use the same preference, and check if the two routes are not coalesced. See issue #33470.
with open(os.path.join(network_unit_dir, '25-veth-router-high2.network'), mode='a', encoding='utf-8') as f: with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
f.write('\n[IPv6SendRA]\nRouterPreference=medium\n') f.write('\n[IPv6SendRA]\nRouterPreference=medium\n')
with open(os.path.join(network_unit_dir, '25-veth-router-low2.network'), mode='a', encoding='utf-8') as f: with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
f.write('\n[IPv6SendRA]\nRouterPreference=medium\n') f.write('\n[IPv6SendRA]\nRouterPreference=medium\n')
networkctl_reload() networkctl_reload()
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 200', ipv='-6', timeout_sec=10) self.check_router_preference('01', 200, 'medium', 200, 'medium')
self.wait_route('client', r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 200', ipv='-6', timeout_sec=10)
print('### ip -6 route show dev client default') # Use route options to configure default routes.
output = check_output('ip -6 route show dev client default') # The preference specified in the RA header should be ignored. See issue #33468.
print(output) with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a99 proto ra metric 200 expires [0-9]*sec pref medium') f.write('\n[IPv6SendRA]\nRouterPreference=high\n[IPv6RoutePrefix]\nRoute=::/0\nLifetimeSec=1200\n')
self.assertRegex(output, r'default nhid [0-9]* via fe80::1034:56ff:fe78:9a98 proto ra metric 200 expires [0-9]*sec pref medium') with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
self.assertNotIn('pref high', output) f.write('\n[IPv6SendRA]\nRouterPreference=low\n[IPv6RoutePrefix]\nRoute=::/0\nLifetimeSec=1200\n')
self.assertNotIn('pref low', output) networkctl_reload()
self.assertNotIn('metric 512', output) self.check_router_preference('01', 200, 'medium', 200, 'medium')
self.assertNotIn('metric 2048', output)
# Set zero lifetime to the route options.
# The preference specified in the RA header should be used.
with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
f.write('LifetimeSec=0\n')
with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
f.write('LifetimeSec=0\n')
networkctl_reload()
self.check_router_preference('01', 100, 'high', 300, 'low')
def _test_ndisc_vs_static_route(self, manage_foreign_nexthops): def _test_ndisc_vs_static_route(self, manage_foreign_nexthops):
if not manage_foreign_nexthops: if not manage_foreign_nexthops:

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
(! systemd-run --wait -p DynamicUser=yes \
-p EnvironmentFile=-/usr/lib/systemd/systemd-asan-env \
-p WorkingDirectory='~' true)
assert_eq "$(systemd-run --pipe --uid=root -p WorkingDirectory='~' pwd)" "/root"
assert_eq "$(systemd-run --pipe --uid=nobody -p WorkingDirectory='~' pwd)" "/"
assert_eq "$(systemd-run --pipe --uid=testuser -p WorkingDirectory='~' pwd)" "/home/testuser"
(! systemd-run --wait -p DynamicUser=yes -p User=testuser \
-p EnvironmentFile=-/usr/lib/systemd/systemd-asan-env \
-p WorkingDirectory='~' true)

View File

@ -16,6 +16,7 @@ ConditionDirectoryNotEmpty=|/run/confexts
ConditionDirectoryNotEmpty=|/var/lib/confexts ConditionDirectoryNotEmpty=|/var/lib/confexts
ConditionDirectoryNotEmpty=|/usr/local/lib/confexts ConditionDirectoryNotEmpty=|/usr/local/lib/confexts
ConditionDirectoryNotEmpty=|/usr/lib/confexts ConditionDirectoryNotEmpty=|/usr/lib/confexts
ConditionDirectoryNotEmpty=|/.extra/confext
DefaultDependencies=no DefaultDependencies=no
After=local-fs.target After=local-fs.target