Currently only a single job for a single unit can be enqueued atomically,
so there is no guarantee that, e.g., starting a unit and its socket
at the same time will happen in the same transaction. That forces
callers to 'know' the right order in which to start new units being
installed, or failures will occur. It also means some ordering
constraints are ignored, in case the separate calls are done
in the wrong manual order.
Add a new EnqueueUnitJobMany() D-Bus method that takes a list of units
to start.
Fixes https://github.com/systemd/systemd/issues/8102
Co-authored-by: Michal Koutný <mkoutny@suse.com>
Without CAP_SYS_ADMIN and without the 'user_subvol_rm_allowed' mount
option, BTRFS_IOC_SNAP_DESTROY is rejected with EPERM (or EROFS for a
read-only subvolume), so rm_rf_subvolume() left subvolumes behind.
test-btrfs thus accumulated leftover subvolumes in /var/tmp on every
unprivileged run on a btrfs filesystem.
An unprivileged owner can however clear the RDONLY flag, empty a
subvolume and rmdir() it. So clear the RDONLY flag on EPERM/EACCES too
(not just EROFS) to leave the subvolume writable, and let rm_rf() fall
through on EPERM/EACCES to empty the subvolume recursively and rmdir()
it, matching what rm_rf_at() already did.
Fixes https://github.com/systemd/systemd/issues/42674
hashmap_replace() failure left t in s->manager->dns_transactions with
t->scope still NULL, causing the destructor to skip hashmap_remove().
Add the missing cleanup mirroring the earlier error path in the same
function.
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Let's translate openssl's errors to proper errnos
where we can instead of returning EIO for everything.
Let's also make log_openssl_errors() public so we can
use it everywhere and migrate the rest of the codebase
to use it.
Two fixes to get this byte-stable:
- `fd_copy_directory()` was using `FOREACH_DIRENT_ALL`, which doesn't
give stable ordering. Read all paths, sort, then iterate.
- `mcopy -s` depends on `readdir()` ordering and thus isn't
reproducible. Implement the recursion/sorting here and only invoke
mcopy/mmd per dir.
First change increases memory usage, as we don't stream the paths
anymore, second increases the number of context switches when invoking
external tools. Both should be fine given the ESP content should usually
be pretty limited.
I'd like to write a test for this, but didn't come up with a way that
doesn't require privileges and would surface the error reliably.
The TPM2_NV_Read commands returns the requested data in a
TPM2B_MAX_NV_BUFFER type, the maximum size of which is TPM-specific and
can be determined by querying the value of the TPM_PT_NV_BUFFER_MAX
property.
The value of this may be smaller than the payload size of some NV
indexes, particularly when that payload is a X509 certificate with a RSA
public key. Eg, the manufacturer supplied RSA EK certificate on my own
machine has a size of 1035 bytes, and the value of TPM_PT_NV_BUFFER_MAX
is 1024.
To handle this case and make it possible to read any EK certificate from
the TPM, make tpm2_read_nv_index support chunked reads when the payload
size is larger than what the TPM can return in a single command.
OpenSSL 4 broke ABI, so we need to look for both SONAMEs.
Try libssl.so.3 first, and fallback to libssl.so.4,
so that the older and more stable version is used if both
are installed, giving distros time to fix regressions.
Follow-up for ccdd42351f
Fixes https://github.com/systemd/systemd/issues/42675
This is a bit of an RFC (but I hope I got it mostly right), @daandemeyer
suggested in
https://github.com/systemd/systemd/pull/42161#pullrequestreview-4336323314
to improve the abstractions around the Exec= in
io.systemd.Unit.StartTransient as we will add a bunch more of those. So
this PR adds first a better abstraction and then uses it. See the
individual commits for details.
This commit extracts the initialization of the transient parameters
for io.systemd.Unit.StartTransient into a set of helpers that follow
the _parameters_init() pattern. This way the code is more uniform
and easier to extend and less fragile. It also means there is a
single (logical) place to init the fields.
This commit uses the abstractions added in the previous commit to
add a bunch more properties to the io.systemd.StartTransient()
to showcase how straightforward this is now.
New helpers for tristate bools and an init helper are added. A
dedicated dispatcher for LogLevelMax parses the string-form name
("info", "debug" etc.) declared in the varlink IDL.
The new properties are: DynamicUser, IgnoreSIGPIPE, LockPersonality,
MemoryDenyWriteExecute, NoNewPrivileges, OOMScoreAdjust, RemoveIPC,
RestrictRealtime, RestrictSUIDSGID, RootEphemeral, UMask.
The remaining ProtectKernel*, Private*, ProtectClock properties are
declared as STRING in the varlink IDL (matching the modern *Ex/enum
form) so a bool dispatcher does not pass schema validation. Those
need a string-parsing dispatcher and will be added in a follow-up.
This brings us closer to parity with the D-Bus code (still a long
way to go though).
The handling of the `Exec` parameters for the varlink
`io.systemd.Unit.StartTransient()` became a bit unwieldy. So
this commit creates another abstraction to handle the various
fields in the `Exec` part of the StartTransient code.
Each Exec property is now described by a single TransientExecProperty
entry and adding a new property is just a single entry there plus
an apply function.
Thanks to Ivan Kruglov for many useful suggestions.
The Acer Nitro AN515-58 has a dedicated NitroSense button (scan code
0xf5) with no entry in its device-specific block. It currently falls
through to the generic Acer rule:
KEYBOARD_KEY_f5=presentation
This is semantically wrong — the button has no relation to
presentation mode. Other Nitro models (AN515-47, AN517-54, ANV15-51)
already map it to prog1 (XF86Launch1), making it a user-programmable
button that desktop environments (KDE, GNOME, etc.) can bind to any
action.
Add the same mapping for AN515-58 for consistency:
KEYBOARD_KEY_f5=prog1 # NitroSense button
Tested on Acer Nitro AN515-58 with Linux 7.0.12 and KDE Plasma 6.7
It's needed for the userspace fallback verity verification, so
it needs to be pre-loaded to avoid getting blocked by RTLD_NOLOAD:
[ 57.163995] (cat)[1560]: minimal-app0-foo.service: Validation of dm-verity signature failed via the kernel, trying userspace validation instead: Required key not available
[ 57.194696] (cat)[1560]: minimal-app0-foo.service: Refusing loading of 'libcrypto.so.3', as loading further dlopen() modules has been blocked.
[ 57.197940] (cat)[1560]: minimal-app0-foo.service: Shared library 'libcrypto.so.3' is not available: Operation not permitted
[ 57.204283] (cat)[1560]: minimal-app0-foo.service: Failed to activate verity device /dev/mapper/2b2fd83f324c3aa2ea1a979899f9c630761f1de3c5e00ce8c6bb36f4d137f450-verity: Operation not supported
[ 57.272782] (cat)[1560]: minimal-app0-foo.service: Failed to set up mount namespacing: Operation not supported
[ 57.274250] (cat)[1560]: minimal-app0-foo.service: Failed at step NAMESPACE spawning cat: Operation not supported
Follow-up for efaf5a763d
During soft-reboot teardown, systemd-cryptsetup@.service's ExecStop runs
libcryptsetup's crypt_deactivate(), which issues DM_REMOVE with a udev
cookie and blocks in dm_udev_wait() until 95-dm-notify.rules decrements
the cookie semaphore via "dmsetup udevcomplete $env{DM_COOKIE}".
The generated cryptsetup unit had only After=systemd-udevd-kernel.socket,
not After=systemd-udevd.service. The .socket has IgnoreOnIsolate=yes and
is not stopped during soft-reboot, so it provides no ordering at all for
the service teardown. Meanwhile systemd-udevd.service has
Conflicts=soft-reboot.target (added in 0d1819e791) and stops as soon as
soft-reboot.target starts, with no ordering relative to cryptsetup's
ExecStop.
Once udevd's device monitor event source is disabled in manager_exit(),
pending DM_REMOVE uevents are no longer processed and the cookie
semaphore stays at 1 forever, blocking soft-reboot at "Stopping
Cryptography Setup..." until JobTimeoutSec=30min on soft-reboot.target
fires.
Add systemd-udevd.service to the After= ordering of the generated
cryptsetup, veritysetup and integritysetup units. By systemd's job
ordering rules (job_compare() in src/core/job.c), when two units are
both being stopped and one has After= the other, the After= unit is
stopped first. So with cryptsetup@*.service After=systemd-udevd.service,
cryptsetup stops first (cookie acknowledged by the still-live udevd),
then udevd stops.
Putting After=umount.target on systemd-udevd.service does not work: at
soft-reboot, udevd's stop job runs concurrently with umount.target's
start job, and JOB_STOP unconditionally precedes JOB_START in the
transaction (see src/core/job.c:1742). The ordering has to be expressed
between two stop jobs, which is what putting After=systemd-udevd.service
on the dm consumers achieves.
Fixes: #40298
This adds support in pam_systemd for acquiring an inhibitor lock when a
pam session is active, and can be used (for example) to prevent
suspend/sleep of a host when an ssh session is active on the host. The
reason string can be customized via `inhibit-why=`.
For example, /etc/pam.d/sshd can now contain this line: `-session
optional pam_systemd.so inhibit=sleep`
And sleep will be blocked when someone is logged into the system over
ssh:
```
foo:~$ systemd-inhibit --list --no-pager
WHO UID USER PID COMM WHAT WHY MODE
NetworkManager 0 root 397 NetworkManager sleep NetworkManager nee… delay
Realtime Kit 0 root 401 rtkit-daemon sleep Demote realtime sc… delay
sshd 0 root 667 sshd-session.pa sleep Active PAM session block
```
Fixes: #20654
The existing tpm2_index_to_handle helper has optional return arguments
for an object's public area and its qualified name. However, it can also
be called for handles corresponding to NV indexes, where the public area
and qualified name don't apply.
I'm working on another change that would benefit from having an
equivalent helper for NV indexes, and there is already some code in
shared/tpm2-util.c that could use this as well.
This splits the existing tpm2_index_to_handle function into 3 functions:
- tpm2_index_to_handle, which works for both objects and NV indexes and
returns a name and handle.
- tpm2_object_index_to_handle, which works the same as the existing
function for transient or persistent objects, returning a public area,
name, qualified name and handle.
- tpm2_nv_index_to_handle, which works for NV indexes, returning the NV
public area, name and handle.
This commit adds support to /etc/hostname for substitution of $ from
wordlists located in /etc,/run,/usr/lib}/systemd/. Each $ is resolved to
a number (1,2,3...) and the corresponding file "1" is opened to acquire
the word. With that we can do a petname [1] style hostname in systemd,
e.g. below a possible expansion for a hostname template:
$-$-$-???? -> wildly-happy-octopus-92a9
The substitution of words is stable (based on machine-id) but if the
wordlist changes the hostname would change. We could pick it once and
cache it but Lennart did not like this so this version instead always
picks it (based on offset of the file so the operation is cheap). To
persist it one can use the `firstboot.hostname` credential. One a live
system this will be expanded and then written in the expanded form to
/etc/hostname.
This also includes a wordlist from the "petname" project that can be
optionally installed.
Thanks to Dustin Kirkland for this wonderful project.
[1] https://github.com/dustinkirkland/petname
---
I'm a bit unsure if this should include the word lists (I think its nice
to have them though) and if so if they should be their own commit.
This implements a close facsimile of
[sudo](https://man.archlinux.org/man/sudo.8#K)'s -k/-K/-v options, which
manipulate the temporary authorizations used by sudo. Use like `run0 -k
whoami` to always re-auth, or just `run0 -k` to revoke a prior temporary
authorization.
~~Depends on polkit-org/polkit#662 due to a bug in polkit.~~ Now it
should work ok despite the bug.
When placing new partitions and there's space left because the new partitions
aren't occupying the whole free space, context_grow_partitions_on_free_area()
is supposed to distribute the free space between the new partitions. If still
no partition wants the free space, the free space ends up becoming padding.
Currently that padding is allocated to the partition preceding the FreeArea
(ie. a->after). This obviously means that the new partitions now end up at
the *end* of the free area rather than at the beginning, which is somewhat
unexpected given how partition placement usually is done.
Fix it by finding the last partition that belongs to the free area, and then
allocating the padding to that partition, so that the new partitions end up
getting aligned with the beginning of the free area, not the end.
Because the span might not be rounded to grain if there's a pre-allocated
a->after partition before the free area, we need to round it down ourselves
(otherwise the "left >= p->new_padding" assertion in context_place_partitions()
is going to fail).
Also ensure the fix works as expected by adding a test.
`tpm2_get_best_pcr_bank()` only ever considered the SHA256 and SHA1
banks (both the `LoaderTpm2ActivePcrBanks` path and the capability
guesswork). On a TPM whose only active bank is SHA384 it returned
`-EOPNOTSUPP`, breaking sealing/enrollment (cryptenroll, credential
encryption, legacy unseal). The restriction looks like a historical
simplification — `efi_get_active_pcr_banks()` already decodes
SHA384/SHA512 and `tpm2_hash_algorithms[]` already lists them.
This PR introduces an explicit preference table (SHA256 > SHA512 >
SHA384 > SHA1) and selects from it. SHA256 stays the top preference for
backwards compatibility, so existing systems keep using the same bank
and the legacy unseal-guess in `tpm2_unseal()` stays consistent;
SHA384/SHA512 are only chosen when SHA256 is unavailable, SHA1 remains
the last resort.
Behavior for existing SHA256/SHA1 systems is unchanged. Includes a unit
test for the bank-preference logic.
Related to https://github.com/systemd/systemd/pull/42537
UEFI firmware type hwids must be matched against the current hardware first.
This change implements that. Additionally, some extra validations on the hwids
entries have also been added.
libnss_systemd currently uses a thread_local recursion guard to
avoid re-entering nss-systemd during NSS lookups.
Since libnss_systemd.so.2 is loaded lazily by glibc, accessing ELF TLS
may trigger dynamic TLS allocation in __tls_get_addr(). Under allocation
failure conditions, glibc terminates the process from the dynamic loader
instead of allowing the NSS module to return a normal failure.
Replace the recursion guard with POSIX thread-specific data to preserve the
same per-thread semantics while avoiding ELF TLS in the NSS module.
Note that pthread_setspecific() may still allocate internally on first use
per thread. The key improvement is that any such failure is returned
as a normal error code rather than terminating the process from inside
the dynamic loader.
Related: #42559
Lennart suggested to use a more uniform algorithm for
the picking of the hostname words that is not biased
for long words by just (predictably) randomly going over
the offsets until we land on a word boundary. This is a
very nice suggestion so this commit implements it with
a fallback to the "old" behavior if we do not find a
word boundary within a reasonable amount of attempts.
A small python script shows that 64 iterations plus
fallback is a good number:
```
$ python3 simulate-hostname-pick.py 64
hostname-wordlist/adverbs
words=261 p_accept=0.1119 avg_bytes/word=1/p=8.94
max_iterations=64, n_trials=1000000
fallback rate : 0.051000% (510/1_000_000)
mean seeks per word : 8.93
hostname-wordlist/adjectives
words=449 p_accept=0.1380 avg_bytes/word=1/p=7.24
max_iterations=64, n_trials=1000000
fallback rate : 0.007500% (75/1_000_000)
mean seeks per word : 7.25
hostname-wordlist/nouns
words=449 p_accept=0.1472 avg_bytes/word=1/p=6.79
max_iterations=64, n_trials=1000000
fallback rate : 0.002700% (27/1_000_000)
mean seeks per word : 6.79
```
Combined with the fallback to the previous method if
we can't find anything within the 64 attemps this seems
to be the best tradeoff and give us very good uniformity.
Similar to the support for ?/$ in /etc/hostname and the credentials
we now add this to the kernel commandline systemd.hostname= option.
If the expansion fails, e.g. in the initrd where the word lists (and
possibly the machine ID) are not available yet, the option is ignored
and the usual default hostname logic applies. Once the host system is
up the expansion succeeds and the intended name is applied.
Now that we support the `$` we want to also make this available
inside the system.hostname and firstboot.hostname credentials and
the firstboot --hostname option. This commit adds it (and also `?`).
This commit adds support to /etc/hostname for substitution
of $ wordlists from {/etc,/run,/usr/lib}/systemd/hostname-wordlist.
The first $ will lookup hostname-wordlist/1, the next
hostname-wordlist/2 and so on.
With that we can do a petname [1] style hostname in systemd, e.g.
below a possible expansion for a hostname template:
$-$-$-???? -> wildly-happy-octopus-92a9
The substitution of words is stable (based on machine-id) but
not persisted, it is picked on every boot via a stable file
offset so the operation is cheap. But this means that if the
wordlist changes the hostname would change. The next commit
will add the pattern to the firstboot.hostname credential which
is persistet with the resolved names to avoid this issue.
This also includes a wordlist from the "petname" project
that can be optionally installed.
Thanks to Dustin Kirkland for this wonderful project.
[1] https://github.com/dustinkirkland/petname
For a good user experience, users expect to be informed of how many
attempts they have before being locked out of their FIDO2 device.
By displaying such information in advance, the user can make strategy to
obtain the accurate PIN or wait when they are close to an authority who
can provide them for a recovery key.
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
We already support exponential backoff for automatic restarts via
RestartSec=/RestartSteps=/RestartMaxDelaySec=, but there is no way to
randomize the restart delay. When many instances of a service fail at
the same time (e.g. because a shared resource briefly went away) they
are all restarted in lockstep, creating a thundering herd problem.
So this commit adds a simple `RestartRandomizedDelaySec=` service
option which is similar to the timer `RandomizedDelaySec=` and
adds a randomized restart delay.
test_wildcard() was never executed: run_testcases() only picks up
functions named testcase_* so this test never ran. This commmit
makes it run and fixes two issues in the test:
1. /etc/hostname is absent in the test image so we need to guard
for that.
2. The pattern check was written as [[ "$P" == "$H" ]] with both
sides quoted, but we need to one side unquoted as otherwise
the comparison will always be false.
This adds a new function, acquire_inhibit_lock, that takes a logind
inhibitor lock for the duration of the PAM session. The lock fd is
stored in PAM data with pam_cleanup_close. In pam_sm_close_session, the
lock is released explicitly by passing NULL to pam_set_data, which
triggers the registered cleanup function immediately rather than waiting
for pam_end.
The inhibit type and reason string can also be configured via the
XDG_SESSION_INHIBIT and XDG_SESSION_INHIBIT_WHY environment variables,
which take precedence over the module arguments.
Fixes: #20654
This adds two new module arguments to parse_argv:
1) inhibit= takes a colon-separated list of inhibitor lock types to acquire
2) inhibit-why= takes an optional human-readable reason string.
Both are currently parsed but are unused until a later commit.