Commit Graph
90841 Commits
Author SHA1 Message Date
Daniel28972897 65f62301c2 test: add coverage for systemctl preset in test-systemctl-enable.sh
Repeats the enable/disable specifier-expansion check with 'systemctl
preset' instead. preset-all is intentionally not exercised here, since
$root accumulates unit files from earlier sections that are
deliberately invalid, and preset-all would trip on those unrelated
units.
2026-07-26 15:10:33 +09:00
dongshengyuan 414777a108 sysupdate: don't double-prefix definitions with --root=
Definitions enumerated under --root= are already rooted. Passing those
paths to the config parsers with the same root prefixes the root again,
so feature and transfer files are parsed from the wrong path.

Repro: create root/etc/sysupdate.d/rootfeat.feature and
01-root.transfer, then run:
build/systemd-sysupdate --root="$root" --verify=no --offline features rootfeat

Before: parsing failed at line 1 with a bogus Source Type= error.

Fixes #42783.
Follow-up for: e1384cfb09
2026-07-26 14:40:05 +09:00
dongshengyuan 99c6f01321 veritysetup: keep parsing after ignored NvPCR options
tpm2-measure-nvpcr=no and invalid NvPCR names only affect the current
comma-separated option. They returned from parse_options(), so later
options were silently skipped.

Repro:
build/systemd-veritysetup attach testvol /dev/null /no/such \
    0000000000000000000000000000000000000000000000000000000000000000 \
    tpm2-measure-nvpcr=no,root-hash-signature=relative

Before: root-hash-signature=relative was skipped, and execution continued
to the missing block-device error.

After: root-hash-signature=relative is parsed and rejected. Invalid NvPCR
names take the same continue path.

Follow-up for: 85d7fb2247
2026-07-26 14:40:05 +09:00
dongshengyuan 47536f5aac escape: add --stdin input mode
systemd-escape currently only processes strings passed as
command line arguments. This is awkward for callers that already
have a generated list of strings, because they need to loop around
the tool or use xargs and carefully preserve whitespace and other
special characters.

Add --stdin to read one string per line from standard input and
write one escaped result per output line. Keep command line strings
mutually exclusive with --stdin so the input source remains
unambiguous.

Use an explicit option instead of treating '-' specially, since '-'
is itself a valid string to escape. The existing escape, unescape,
mangle, path, suffix, and template rules are reused unchanged.
2026-07-26 13:20:55 +09:00
Eric Curtin 5ef2510988 shared/dropin: don't re-derive drop-in name candidates per lookup dir
unit_file_find_dirs() is called once for every (unit name or alias,
lookup directory, drop-in suffix) combination while enumerating units
at boot, to check whether that unit has a ".d", ".wants", ".requires"
or ".upholds" drop-in directory in that particular lookup path. On a
typical system with ~270 loaded units and ~12 directories in the unit
search path, this adds up to tens of thousands of calls.

For every one of those calls, the function used to independently
re-derive the full chain of candidate unit names to check for that one
directory: the name itself, its template if it is a template instance,
and its "-" prefix chain (e.g. for "foo-bar-waldo.service" also
"foo-bar-.service" and "foo-.service"), recursively expanding further
where applicable. That derivation only depends on the unit name itself
and does not involve the lookup directory at all, so it produces the
exact same list of candidate names regardless of which of the 12
lookup directories is currently being checked. Despite this, it was
being fully recomputed for every single directory, doing several small
allocations and unit-name parsing calls (unit_name_template(),
unit_name_to_prefix(), unit_name_build_from_type(), ...) each time.

Split the name-derivation logic out into its own function,
unit_file_expand_dropin_names(), and compute it once per unit
name/alias, then reuse the resulting candidate list across all lookup
directories instead of re-deriving it for each of them. The order in
which candidate directories end up being added is unchanged, so this
is not expected to alter drop-in resolution behaviour: I confirmed this
by comparing the sorted unit load state, fragment path and drop-in path
output of "systemd --test --system" before and after this change on the
same unit tree, which is byte-for-byte identical.

I measured the effect by instrumenting manager_enumerate() with
CLOCK_MONOTONIC timestamps and running systemd, built from this exact
tree, as actual PID 1 in a container with ~270 real units loaded, 50
runs each before and after this change:

  before: mean 45.35ms (stddev 0.60ms)
  after:  mean 38.81ms (stddev 0.81ms)

a ~14% reduction with about 8 standard deviations of separation between
the two distributions, i.e. well outside of run-to-run noise.

unit_file_expand_dropin_names()'s out parameter is renamed from
ret_names to names, since it is appended to (including recursively)
rather than only being populated on success, matching the ret_ naming
convention used elsewhere for output-only parameters. Also, a failure
partway through expanding a name's candidates (e.g. OOM) no longer
discards the candidates already derived before the failure, keeping
unit_file_find_dirs() closer to the original recursive
implementation's error handling.

unit_file_add_dir_if_exists(), which builds the path to check for each
(lookup directory, candidate name) pair, is now the hottest remaining
part of this code: with the per-directory re-derivation gone, it is
called once for every directory/candidate combination instead of once
per candidate. It used to build that path with strjoin(name, suffix)
followed by path_join(unit_path, name_and_suffix), i.e. two heap
allocations plus path_join()'s normalization pass. Lookup paths are
already normalized (path_simplify() + strv_uniq()), so a single
strjoin(unit_path, "/", name, suffix) produces the same string while
halving the allocations and skipping the redundant normalization.
2026-07-26 05:33:22 +09:00
Armaan Sandhu 151dafcf16 ask-password: refuse agent requests with unsafe characters in prompt fields
The message, icon and id fields are written verbatim into single-line
assignments of the [Ask] section of the agent request file, so a newline in
them lets the caller append arbitrary further assignments. Agents let a later
assignment override an earlier one, so an injected Socket= line redirects the
password to a path of the injector's choosing. Validate the fields and refuse
the request instead.
2026-07-26 05:30:02 +09:00
Yu Watanabe a8e93919c3 Minor follow-ups for recent PRs (#43148) 2026-07-25 21:08:37 +09:00
Yu Watanabe b556e151b9 po: update Japanese translation
The commit 843bba839a dropped space after
colon, but Weblate dislikes that. Let's readd space.
2026-07-25 20:41:47 +09:00
Mike Yuan c2624fe9a7 various: attach errno to structured logs, even if not used in msg 2026-07-25 19:37:47 +09:00
Mike Yuan 8c98dac0dc imds-generator: do not enable IMDS logic if detect_container() failed 2026-07-25 19:37:47 +09:00
Mike Yuan 37f760f787 imds-generator: use read_full_virtual_file() 2026-07-25 19:37:47 +09:00
Mike Yuan 8fa8e29656 imdsd: use free_many_charp() where appropriate 2026-07-25 19:37:47 +09:00
Mike Yuan d5d76ddd80 Revert "basic/allow-util: make free_many non-inline"
This reverts commit 3abe1e53f6.

I remain unconvinced. The function is very short, and
by making it inline the assert()s can be optimized away.
2026-07-25 19:37:47 +09:00
Mike Yuan 89d48b71ae efi-loader: move $SYSTEMD_FORCE_MEASURE override to efi_measured_os()
Follow-up for cd911bec6e

The (debug) envvar should have highest priority, hence move it
to the new entrypoint function and give it precedence over
systemd.tpm2_measured_os=.
2026-07-25 19:37:47 +09:00
Mike Yuan b82e739cb5 efi-loader: shorten the code a bit 2026-07-25 19:37:47 +09:00
Yu Watanabe d20313d086 homed/fscrypt: default new homes to v2 policies (#18280) (#42397)
## Summary

Closes #18280.

`systemd-homed` currently writes fscrypt v1 policies, which bind the
master key to the calling process's keyring. This means files in a
homed-managed directory aren't readable when accessed through a
container bind mount, a different mount namespace, or by any process
other than the one that first unlocked the home. Reading the file from a
context that has the key first warms the page cache, but the underlying
problem remains.

v2 policies (Linux 5.4+) route the master key through the filesystem
keyring, via `FS_IOC_ADD_ENCRYPTION_KEY` /
`FS_IOC_REMOVE_ENCRYPTION_KEY`, so the key is visible to every process
accessing the filesystem.

This PR switches `systemd-homed` to v2 by default and keeps existing v1
homes working.

## Changes

**`shared/crypto-util`**: Add `kdf_hkdf_derive` (HKDF, RFC 5869) wrapper
around OpenSSL's `EVP_KDF` "HKDF", alongside the existing SSKDF/KBKDF
helpers.

**`homed/fscrypt`**:
- Read the existing policy via `FS_IOC_GET_ENCRYPTION_POLICY_EX`,
falling back to the legacy ioctl on pre-5.4 kernels.
- `HomeSetup` now carries a full `struct fscrypt_key_specifier` instead
of a bare 8-byte descriptor. Slot decryption derives either the v1
descriptor (double SHA-512) or the v2 identifier (HKDF-SHA512 with the
kernel's info string) from the unwrapped volume key and compares against
the policy.
- Install the master key the right way per version: `add_key("logon",
...)` to thread+user keyrings for v1, `FS_IOC_ADD_ENCRYPTION_KEY` for
v2.
- `home_flush_keyring_fscrypt` opens the image directory, reads the
policy version, and either calls `FS_IOC_REMOVE_ENCRYPTION_KEY` (v2) or
walks the user keyring (v1).
- New homes default to v2; fall back to v1 only when the kernel rejects
v2.

The on-disk slot xattr format is unchanged - the volume key is the same,
only how it binds to the directory changes. There is no v1 -> v2
migration; existing v1 homes continue to unlock, rekey, and deactivate
as before.
2026-07-25 19:36:35 +09:00
Tim Culverhouse 4517e7e4d9 core: support CollectMode in Varlink StartTransient
The io.systemd.Unit context exposes CollectMode, but StartTransient
rejects it as unsupported. This prevents Varlink clients from selecting
whether failed transient units should be garbage-collected.

Accept CollectMode when creating transient units and persist the setting
in the runtime unit configuration. Extend the integration test to verify
the value in both the Varlink response and the resulting unit.
2026-07-25 15:35:28 +09:00
logical-misha e09402326c format-table: give mixed cell types a stable sort order (#43129)
Mixed-type cells were compared by their insertion indices, while cells
of the same type were compared by value. Combining those rules
could make `cell_data_compare()` non-transitive.

Give different non-empty `TableDataType` values a stable order. Define
empty cells as greater than non-empty cells, so they appear last in
ascending sorts and first when the order is reversed. This ensures that
the comparator defines a consistent ordering.

Fixes #43128.
2026-07-25 14:38:23 +09:00
Hilal Rahmatullah c844a88f69 man: fix typo 2026-07-25 04:11:29 +09:00
Yu Watanabe 7cc277fb97 cryptsetup: avoid state leaks from ignored options (#43135) 2026-07-24 21:35:34 +09:00
Yu Watanabe e6cc9d0298 tmpfiles: fix root handling and target resolution (#43031) 2026-07-24 21:15:11 +09:00
dongshengyuan 33d9f3840b cryptsetup: ignore invalid password-cache= fully
password-cache= tracks both the cache mode and whether the option was
configured explicitly. The parser set arg_password_cache_set before
validating the value, so an invalid value was logged as ignored but
still blocked the PKCS#11 default no-cache policy.

Only mark password-cache= as configured after accepting read-only or a
valid boolean.

Repro:
build/systemd-cryptsetup attach sdscan /dev/null - \
    pkcs11-uri=auto,password-cache=bogus

Before: warned ignored, then failed with the PKCS#11 cache error.
After: warned ignored, then continued to the device check.

Follow-up for: fd8ed7f26b
2026-07-24 16:38:19 +08:00
dongshengyuan 89ad718762 cryptsetup: don't keep invalid size= values
size= is specified in bits, but arg_key_size stores bytes after
parsing. The parser used arg_key_size as temporary storage before
validation. When the value was not divisible by 8, the warning said
the option was ignored, but the invalid bit count remained.

Parse into a local variable and update arg_key_size only after
validation.

Repro:
build/systemd-cryptsetup attach sdscan /tmp/plain.img /tmp/key \
    plain,size=7

Before: warned ignored, then used key size 56 bits.
After: warned ignored, then kept the default key size 256 bits.

Follow-up for: 6131a78b4d
2026-07-24 16:38:19 +08:00
dongshengyuan 3cc7ccc02c tmpfiles: inherit age-by for X entries
X entries inherit the cleanup age from the closest parent directory rule.
Inherit the age-by fields too, so parent rules such as m:1d keep their
full cleanup policy.

Reproducer:
  mkdir -p /tmp/tmpfiles-ageby/parent/{child,other}
  printf old >/tmp/tmpfiles-ageby/parent/child/file
  printf old >/tmp/tmpfiles-ageby/parent/other/file
  touch -d '3 days ago' /tmp/tmpfiles-ageby/parent/{child,other}/file
  systemd-tmpfiles --clean - <<'EOT'
  d /tmp/tmpfiles-ageby/parent - - - m:1d
  X /tmp/tmpfiles-ageby/parent/child - - - -
  EOT

Before:
  child/file remained because X used the default age-by set.
  other/file was removed by the parent m: rule.

Follow-up for 7f7a50dd15.
2026-07-24 13:44:37 +08:00
Yu Watanabe bbd8386999 Allow arbitrary standalone progs to be installed and really stop building all standalone for tests (#43130) 2026-07-24 14:22:07 +09:00
Frantisek Sumsal f978a4a1e0 Revert "test: re-enable sync in TEST-25-IMPORT"
This shouldn't be necessary anymore, as we don't block openat2() when
running nspawn with --suppress-sync=yes.

This reverts commit c955e24916.
2026-07-24 14:10:58 +09:00
Frantisek Sumsal fb73687370 seccomp-util: allow openat2() with --suppress-sync=yes
When --suppress-sync=yes was introduced in
4a4654e024 it filtered out openat2()
completely, as we can't check its "flags" argument because it's hidden
in an indirect struct. This was perfectly fine at that time, as
openat2() was quite new and software shipped with a fallback to
open()/openat() if the syscall wasn't present.

However, today the situation is different and an increasing number of
software is moving to openat2() without any fallback - tar [0] being the
most common one in the recent reports and workarounds, and attr recently
fixed a CVE by switching to openat2() [1] as well, to name a few.

Given that we already block all the sync-family syscalls and calling
openat2() with O_SYNC is relatively rare, let's just blanket-enable it
in the --suppress-sync=yes mode. This means that we might issue a
synchronous write when something calls openat2() with O_SYNC, but not
breaking the apps here feels like a reasonable trade-off, at least until
a better solution pops up.

Note that the same situation is in seccomp_restrict_sxid(), but allowing
the openat2() syscall there could actually have some security-related
implications under certain circumstances.

Resolves: #41868

[0] https://cgit.git.savannah.gnu.org/cgit/tar.git/commit/?id=75b03fdff48916bd0654677ed21379bdb0db016d
[1] https://cgit.git.savannah.gnu.org/cgit/attr.git/commit/?id=1cea2fc5e8b5c8a5f29abf1141399e01a57a3154
2026-07-24 14:10:58 +09:00
dongshengyuan aa776aefba machine-id-setup: follow symlink target on --commit
Resolve /etc/machine-id before checking the mount state and before
writing back, so symlinked targets are committed correctly.

Fixes: #43104
Follow-up for: efabf4e044
2026-07-24 14:10:30 +09:00
gkehren 9d217e051b core: tolerate kernels without POSIX mqueue support
PrivateIPC= sets up a private mqueue mount for the service. When
CONFIG_POSIX_MQUEUE is disabled, mounting mqueue fails with ENODEV and
prevents the service from starting.

Treat ENODEV as an unavailable optional kernel feature while preserving
the private IPC namespace. Keep all other mount errors fatal.

Add coverage verifying that PrivateIPC= still creates a separate IPC
namespace when POSIX message queues are unavailable.

Fixes #42582
2026-07-24 13:44:59 +09:00
Ronan Pigott c6c6a3f3fd test-ndisc-send: correct add_link_layer_address argument order
Found by inspection while working on networkd.
2026-07-24 13:44:32 +09:00
Yu Watanabe b8b7c04672 network: make VLAN= and friends take multiple names
Previously, specifying multiple stacked netdevs of the same type required
repeating the corresponding setting, e.g.:
```
[Network]
VLAN=vlan_10
VLAN=vlan_20
VLAN=vlan_30
```

With this change, the same configuration can be written as:
```
[Network]
VLAN=vlan_10 vlan_20 vlan_30
```

Specifying an empty string now also clears all previously assigned stacked
netdevs.

Closes #43103.
2026-07-24 13:44:04 +09:00
Zbigniew Jędrzejewski-Szmek 55f52b1180 meson: stop registering .standalone in executables_by_name
af4c5730e5 tried to have meson stop
building all possible .standalone binaries in for tests. But it turns out
that those binaries are still built for meson-test-prereq, because they
are listed in executables_by_name, and we interate over
executables_by_name and add all exes found there as dependencies for two
tests: test-link-abi and libshared-unused-symbols. So we'd end up still
building all the .standalone binaries. To really fix this, define the
executables() for .standalone targets, but don't add them to this array.

A secondary change is to set build_by_default to true for .standalone
binaries if have_dlopen_tests is set. This means that we'll build more
binaries in the "build" phase, instead of only building them "on demand"
for tests. I think it is nicer to build everything that'll be used in one
step, and then only run the tests in the test target. For example, tests
may be run under root or in some special environment, and building thins
there is iffy.

The overall effect of this change should be that we stop building or
testing .standalone variants for binaries that we'll not later install,
unless -Ddlopen-tests=true is specified.

Also exclude .standalone binaries from check-help test. The test fails
for some binaries when the width is exceeded because of the ".standalone"
suffix in the name. The actual binary would be called without the
suffix, so the test is not testing a realistic scenario.
2026-07-24 00:36:44 +02:00
Zbigniew Jędrzejewski-Szmek 7be812ae70 meson: rework -Dstandalone-binaries= option
The option is generalized from a simple boolean switch that enables
a fixed list to a list-of-patterns.
The old value works, but is deprecated: -Dstandalone-binaries=true is translated
to -Dstandalone-binaries=repart,report,tmpfiles,sysusers,shutdown.

We could already build all normal executables as .standalone, but the
installation only supported a small fixes subset. This wasn't flexible
enough:
- packagers might want to provide additional standalone binaries then the
  small subset that was already enabled
- but at the same time, whenever new binaries were added to this subset,
  downstream packaging had to be adjusted in sync, at least in the case of
  Fedora, because otherwise we'd get a complaint about unexpected .standalone
  binaries in the temporary install root.
With the new option, downstreams can just specify the binaries that they
want to be installed in the .standalone variant.

As usual with this type of change, the build dir must be reprovisioned.
2026-07-24 00:35:10 +02:00
logical-misha 841ebcbb7d user-record: validate JSON shell fields with valid_shell()
The user record loader currently uses a generic filename-or-path check
for shell and fallbackShell. This allows values that homectl rejects,
including relative names, control characters, colons, and trailing
slashes.

Use valid_shell() for all three record locations and cover the top-level,
matching per-machine, and status fallback fields at the loader boundary.

Fixes #43066
2026-07-24 02:57:04 +09:00
Ananth 34c60f113e timer: clamp future calendar base after clock jumps back
A calendar timer that is already waiting keeps the base timestamp it was
last armed from. When the wall clock is set backwards, that base can end
up in the future relative to the new realtime, and passing it to
calendar_spec_next_usec() schedules the next elapse relative to the old
future time instead of recalculating from now. systemctl list-timers
then keeps showing the stale pre-adjustment elapse (e.g. "3 years left"
after the clock moved back two years) and the timer never catches up.

Clamp the selected calendar base to the current realtime before asking
calendar_spec_next_usec() for the next occurrence. The clamp only kicks
in when the base is genuinely in the future, so Persistent=yes timers
whose last trigger is still in the past keep their catch-up behaviour and
we don't reintroduce the missed-run regression seen after suspend.

Fixes #6036.
2026-07-24 01:54:40 +09:00
Zbigniew Jędrzejewski-Szmek af4c5730e5 meson: disable dlopen tests by default, enable in gcc github workflow
1f76654f94 added support to build .standalone
variants of most binaries. test-dlopen-note.py is hooked in the test suite for
everything that can do .standalone, but this means that the .standalone
variants become a prerequisite for tests. This means that meson will build the
.standalone variants for all binaries before running tests, which takes quite a
bit of time in some situations. (Arguably, the dlopen test suite was excluded
by default, so maybe meson could be smart and figure out that those tests are
not enabled by default. But it doesn't seem to make this distinction.)
2026-07-24 01:51:22 +09:00
Alexandre Saou 4ae4470ad9 hwdb: add numlock mapping for PATEN/Labtec USB Numpad 2026-07-23 17:41:24 +01:00
dongshengyuan c56420a362 tmpfiles: do not follow copy source symlinks
C lines copy symlinks as symlinks. The post-copy type check should
inspect the source symlink itself, not follow its target.

Reproducer:
  src=/tmp/tmpfiles-src-link.$$
  dst=/tmp/tmpfiles-dst-link.$$
  conf=/tmp/tmpfiles-conf.$$
  ln -s missing-target "$src"
  printf 'C %s - - - - %s\n' "$dst" "$src" >"$conf"
  systemd-tmpfiles --create "$conf"

Before:
  Failed to stat($src): No such file or directory
  status=73
  $dst -> missing-target already existed

Follow-up for 8f6fb95cd0.
2026-07-23 19:33:08 +08:00
Yu Watanabe c023311fe4 network: invalidate cached driver when an interface is renamed
During early boot, interfaces may be renamed frequently, which can lead to
caching the driver name of a different interface. Invalidate the cached
driver whenever an interface rename is detected so it can be re-read using
the new name.

Follow-up for #42545.
Fixes #43099.
2026-07-23 19:23:47 +09:00
Armaan Sandhu 92e2f70a3c ask-password: reject oversized Plymouth prompts (#43102)
Plymouth encodes the password prompt length in a single byte.
Reject prompts whose length cannot be represented instead of
wrapping the encoded length while sending the complete message.
2026-07-23 19:18:13 +09:00
Armaan Sandhu 7359f11be6 strv: refuse invalid UTF-8 in strv_rebreak_lines()
The scan pointer was advanced with utf8_next_char(), which blindly skips
utf8_skip_data[lead byte] bytes, so a line ending in a truncated multibyte
sequence like "foo\xF0" stepped over the NUL and the loop read past the end
of the string. Decode each character with utf8_encoded_to_unichar() and
propagate the error instead of measuring broken characters.

Fixes #43052.
2026-07-23 19:16:59 +09:00
Sven Joachim d336ef5e76 emacs: Fix warning when opening shell scripts
Opening a shell script, Emacs notified me in the echo area:

sh-indentation is obsolete (since 26.1); use ‘sh-basic-offset’ instead

Commit 0c40aef7ef ("emacs: drop obsolete emacs property") got it backwards,
keeping sh-indentation rather than sh-basic-offset.  The latter is an obsolete
alias for the former.
2026-07-23 12:08:50 +02:00
dongshengyuan f936c9b366 tmpfiles: restore timestamps after removing directories
dir_cleanup() restored parent timestamps after removing files, but not
after removing child directories. Mark directory removals as changes too.

Reproducer:
  rm -rf /tmp/tf-mtime-dir
  mkdir -p /tmp/tf-mtime-dir/old-child
  touch -d '2020-01-01 00:00:00' \
        /tmp/tf-mtime-dir/old-child /tmp/tf-mtime-dir
  before=$(stat -c %Y /tmp/tf-mtime-dir)
  systemd-tmpfiles --clean - <<'EOT'
  d /tmp/tf-mtime-dir - - - M:1s
  EOT

Before:
  equal=no
  gone=yes

Follow-up for 3b63d2d31d.
2026-07-23 16:56:06 +08:00
dongshengyuan ac18c0569e tmpfiles: propagate copy errors after opening target
Opening the destination only proves that it exists. If copy_tree_at()
failed for any reason other than an existing destination, report that
copy error.

Reproducer:
  name=tmpfiles-copy-bug.$$
  src=/tmp/$name.src; dst=/tmp/$name.dst; conf=/tmp/$name.conf
  mkdir "$src" "$dst"
  printf payload >"$src/file"
  chmod 500 "$dst"
  printf 'C %s - - - - %s\n' "$dst" "$src" >"$conf"
  systemd-tmpfiles --create "$conf"

Before:
  exit=0
  copied=no

Follow-up for 8f6fb95cd0.
2026-07-23 16:56:06 +08:00
dongshengyuan 35e9ca257d tmpfiles: check relative L? targets beside the link
Relative symlink targets are resolved from the directory containing the
link. Make the L? existence check use the same rule.

Reproducer:
  tmp=$(mktemp -d /tmp/tmpfiles-link.XXXXXX)
  conf=$(mktemp /tmp/tmpfiles-conf.XXXXXX)
  printf data >"$tmp/target"
  printf 'L? %s/link - - - - target\n' "$tmp" >"$conf"
  systemd-tmpfiles --create --dry-run "$conf"

Before:
  The target was checked root-relative, not beside the link.

Follow-up for b5dc805583.
2026-07-23 16:56:06 +08:00
Yu Watanabe b27e324272 fixups for systemd-osc-context (#43091)
I noticed that the use of sed in the `80-systemd-osc-context.sh` was
unnecessary, and upon writing a replacement in pure bash and testing it,
actually buggy. While in there, I also spotted some other minor things
that might be worth doing.

Getting rid of fork+exec for doing sed is probably the biggest win, but
there are still quite a few subshell invocations (that only do fork, not
exec). I haven't measured the overhead of those, but it seems that we
could get rid of those as well if we want.

Another thing I wonder about is whether we should emit an end= marker on
shell exit. There's no guaranteed way of doing it. Just as everything
else, we could get killed before getting a chance to do it. But also,
unlike PROMPT_COMMANDS, there's no "at_exit" array to hook into. Still,
we could ask if there is a 'trap exit' hook installed, and if not,
install one ourselves; if the user's bashrc subsequently overrides that,
so be it (though .bash_logout would be more appropriate).
2026-07-23 16:01:41 +09:00
dongshengyuan 58496809c0 tmpfiles: keep directory specifiers rootless
%t and the other directory specifiers are parsed as normal paths.
They are prefixed by --root= later, so the specifier itself must stay
rootless.

Reproducer:
  tmp=$(mktemp -d /tmp/tmpfiles-root.XXXXXX)
  conf=$(mktemp /tmp/tmpfiles-conf.XXXXXX)
  printf 'd %%t/tmpfiles-repro 0755 - - -\n' >"$conf"
  systemd-tmpfiles --root="$tmp" --create --dry-run "$conf"

Before:
  Would create directory $tmp/$tmp/run/tmpfiles-repro

Follow-up for de61a04b18.
2026-07-23 14:33:16 +08:00
Yu Watanabe 5c0d4b5061 utf8: split out unichar_console_width() from utf8_char_console_width()
It will be used later.
2026-07-23 14:40:37 +09:00
dongshengyuan 8a5c8b751b machined: refresh resolve hook addresses per machine
Track which machine the cached address list belongs to and refresh it
when ResolveRecord() advances to another machine. This keeps A/AAAA
reuse for the same machine while avoiding mixed name/address records.

Reproducer: register two machines with private addresses 10.88.1.1
and 10.88.2.1, then call io.systemd.Resolve.Hook.ResolveRecord
with both A questions in one request.

Before: the answer for the second machine used its own name but
reused the first machine's address, e.g. resolve-bug-m2 returned
10.88.1.1 instead of 10.88.2.1.

Follow-up: 3cd929f837
2026-07-23 13:19:11 +09:00
dongshengyuan 48b1109b0c kernel-install: keep ukify cmdline inside conf root
KERNEL_INSTALL_CONF_ROOT overrides kernel-install config lookup. When it
was set and cmdline was absent, 60-ukify still fell back to
/proc/cmdline and embedded host boot options into the target UKI.

Return an empty base cmdline in that case, matching the adjacent
90-loaderentry behavior of not searching outside the override root.

Reproducer:
  KERNEL_INSTALL_CONF_ROOT=$(mktemp -d) python3 -c '
  import runpy
  ns = runpy.run_path("src/kernel-install/60-ukify.install.in",
                      run_name="not_main")
  print(ns["kernel_cmdline_base"]())'

Before:
  The host /proc/cmdline was returned.

Follow-up for: 40c0c9d4bc
2026-07-23 12:19:48 +09:00