Commit Graph
90821 Commits
Author SHA1 Message Date
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
dongshengyuan eb4abd2d14 hostnamectl: document JSON status object output
status with --static, --pretty, or --transient prints only the
selected hostname in regular output. JSON status output is built from
hostnamed's Describe data and remains a full status object.

Document this distinction so callers do not expect the name type
switches to turn JSON status into a single scalar value.

Follow-up for: ac8a4f6b78
2026-07-23 12:19:48 +09:00
Luca Boccassi 765dc96746 homed: verify privileged worker changes
Workers may return a newer embedded identity while processing
an owner update. Accept self-modifiable changes, but require
privileged changes to carry a trusted signature.

Follow-up for 70a5db5822
2026-07-22 17:11:08 +02:00
Luca Boccassi b9ef5951f8 rm-rf: downgrade root check log when directory doesn't exist
When a unit is stopped we try to destroy the credential mount point,
which might not exist. This logs at error level, which is noisy and
pointless. Downgrade to debug level on ENOENT.

systemd[1]: Failed to determine whether '/run/credentials/run-p119516-i119816.service' is the root file system: No such file or directory

Follow-up for 9dd2dab37e
2026-07-22 15:09:36 +02:00
Liu Zheng 3ac01c2512 man: document that ExitType=cgroup is rejected for Type=oneshot
The ExitType= documentation stated that ExitType=main "cannot be used
with Type=oneshot", which is incorrect: ExitType=main is the default
and works fine with Type=oneshot. The restriction actually enforced by
the code is that ExitType=cgroup is refused for Type=oneshot services
(see service_verify() in src/core/service.c).

Move the "cannot be used with Type=oneshot" note from the ExitType=main
bullet to the ExitType=cgroup bullet where it belongs.

Fixes #42327

Signed-off-by: Liu Zheng <liuzheng@uniontech.com>
2026-07-22 12:24:15 +01:00
Armaan Sandhu eb03267070 escape: reject UTF-16 surrogates in \u escapes in cunescape_one() (#43079)
A `\u` escape in `cunescape_one()` was accepted for any 16-bit value
except NUL. That range `0x0000`-`0xFFFF` includes the UTF-16 surrogates
`0xD800`-`0xDFFF`, which are not valid Unicode scalar values and cannot
be encoded as valid UTF-8.
2026-07-21 23:40:26 +09:00
Yu Watanabe cc594a83f4 home: insert a space before '=' 2026-07-21 23:38:40 +09:00
Beniamino Galvani 9af2d7e4c8 man: update the sample glib/sd-event integration
The normal order of operations when iterating the GLib main loop is:

 - prepare()  -> sd_event_prepare()
 - poll the file descriptors
 - check()    -> sd_event_wait()
 - dispatch() -> sd_event_dispatch()

GLib does not guarantee that check() is always called between two
consecutive prepare() invocations. When another thread attaches or
removes a source with poll fds while the main thread is inside
poll(), g_main_context_check_unlocked() returns immediately without
calling any source's check() callback.

Since the sd_event GSource adapter maps prepare/check/dispatch to
sd_event_prepare/sd_event_wait/sd_event_dispatch, a skipped check()
leaves sd_event in ARMED state. The next prepare() then hits
assertion "e->state == SD_EVENT_INITIAL".

The following program reproduces the faulty scenario by creating a
thread that attaches a new fd during the poll phase:

  #include <stdio.h>
  #include <stdlib.h>
  #include <sys/socket.h>
  #include <glib.h>
  #include <systemd/sd-event.h>
  #include <unistd.h>

  /* from glib-event-glue.c */
  extern GSource *g_sd_event_create_source(sd_event *event);

  static gpointer thread_func(gpointer user_data) {
    GSource *source;
    GPollFD pollfd;
    int fd;

    g_usleep(G_USEC_PER_SEC / 10);

    fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
    if (fd < 0)
      abort();

    source = g_source_new(&(GSourceFuncs){0}, sizeof(GSource));
    pollfd.fd = fd;
    pollfd.events = G_IO_IN;
    pollfd.revents = 0;
    g_source_add_poll(source, &pollfd);
    g_source_attach(source, NULL);
    g_source_destroy(source);
    g_source_unref(source);

    close(fd);

    return NULL;
  }

  int main(int argc, char *argv[]) {
    sd_event *event = NULL;
    GSource *source;
    GThread *thread;
    int i, r;

    r = sd_event_default(&event);
    if (r < 0)
      return 1;

    source = g_sd_event_create_source(event);
    if (!source)
      return 1;

    g_source_attach(source, NULL);

    for (i = 0; i < 50; i++) {
      thread = g_thread_new("check-skip", thread_func, NULL);
      g_main_context_iteration(NULL, TRUE);
      g_thread_join(thread);
      g_main_context_iteration(NULL, FALSE);
    }

    g_source_destroy(source);
    g_source_unref(source);
    sd_event_unref(event);

    return 0;
  }

When the program uses the current glue code, it crashes with:

  Assertion 'e->state == SD_EVENT_INITIAL' failed at src/libsystemd/sd-event/sd-event.c:4560, function sd_event_prepare(). Aborting.

Fix the problem by skipping sd_event_prepare() if the event is
already ARMED: it was already prepared in a previous iteration and
it can be polled immediately.
2026-07-21 14:50:02 +01:00
Guillaume Kehren ac64b2dfa3 man: document unlocked as default IMDS network mode
The default IMDS network mode was changed to unlocked, but the
systemd-imdsd@.service documentation still described locked as the
default.

Fixes #42687
2026-07-21 11:43:52 +01:00
Rasmus Villemoes 8c6f1c4a21 profile/systemd-osc-context: also escape $USER and $HOSTNAME
Claude pointed out that while rather unlikely, it is possible for the USER and
HOSTNAME environment variables to contain problematic characters that require
escaping. Now that that escaping no longer involves the fork+exec overhead of
calling sed, let's ensure those fields do get put through the escape routine.

Refactor __systemd_osc_context_escape so that it not only takes the value and
prints that, but also the format specifier used for emitting the field. That
way, we avoid an extra subshell (i.e. fork+pipe and all that overhead), and
combined with the previous commit, we now only spawn one subshell instead of
two per start= sequence.

That could be reduced to zero, if the "callers" were rewritten to something
like

    printf "\033]3008;start=%.64s;type=shell" "$systemd_osc_context_shell_id"
    __systemd_osc_context_common
    printf "\033\\"

but that will mean that the sequence is not emitted with a single write()
system call [which isn't really guaranteed currently either, just very likely],
so some background process could end up writing to the middle of the sequence,
thus losing that output and mangling the OSC3008 info. This in turn could be
overcome by building the whole sequence in a shell variable using 'printf -v'
and only printing at the end, but that would be a somewhat invasive change.
2026-07-21 11:21:00 +02:00
Rasmus Villemoes ccace17d2f profile/systemd-osc-context: fold emitting cwd= field into __systemd_osc_context_common
Now that the %s specifier used to embed the common fields in the output appears
immediately before the cwd= field, we can just emit that cwd= field as part of
the common fields.
2026-07-21 11:06:30 +02:00
Rasmus Villemoes ac4c3e4290 profile/systemd-osc-context: emit type= field first
Not because it is required by the specification, but it will make the following
patches simpler. Also, the fact that the spec explicitly does call out that
type= can appear at the end or in the middle suggests that people would
normally expect it to appear at the beginning.
2026-07-21 11:06:30 +02:00
Rasmus Villemoes ba95ad74e2 profile/systemd-osc-context: don't do arithmetic expansion on systemd_exitstatus
There's really no point in having bash do arithmetic expansion on the
systemd_exitstatus variable, i.e. have it convert the string to a number, do no
actual arithmetic, then convert it back to a string to be used as the argument to
the printf, which will again convert it to a number for the %d specifier, and
finally emit it as a decimal. Also, it deviates for no obvious reason from how
it is passed to printf in the "probably died by signal" case just above.
2026-07-21 11:06:30 +02:00
Rasmus Villemoes 10a356629a profile/systemd-osc-context: do not zero-pad pid value
The %.20d specifier was introduced in 2d738a0aee ("profile/systemd-osc-context:
Enforce length limits"). But, for numeric conversions, the precision is not an
upper bound, but rather a lower bound on the output width, padding as necessary
with 0 on the left. So as-is, this does not in fact limit the output to at most
20 characters.

Of course, in practice, pids on linux are never greater than 2^22, and
certainly never larger than what would fit in a 20-digit decimal. On the other
hand, that more or less guarantees that the pid= field is always emitted with
12+ leadings zeroes, which is a bit silly. Moreover, a leading 0 can cause a
parser to treat it as octal.

Since $$ does expand to the PID in decimal, just print that as a string, with the
enforced 20 character limit.
2026-07-21 11:06:30 +02:00
Rasmus Villemoes 9ca5488046 profile/systemd-osc-context: do not use sed for escaping
Bash is perfectly capable of performing the simple substitutions needed for
escaping according to the OSC 3008 spec, so there is no need for the fork+exec
and other overhead of calling sed.

In fact, when writing a test for ensuring that this is a drop-in replacement, I
found out that the current sed method is flawed: If $PWD contains newline
characters, they are passed through unchanged, because sed obviously is
line-oriented.

I do not know which bash version started supporting
${foo//pattern/replacement}, but I ran the below on all Debian images from docker
hub going back to Debian 6 (EOL 2016), carrying BASH_VERSION =
4.1.5(1)-release, and they all succeeded. Since the logic otherwise relies on
PROMPT_COMMAND being an array variable, which happened in 5.1, this should be
all good.

=== test.sh ===
#!/bin/bash

echo "BASH_VERSION = $BASH_VERSION"
ret=0

using_sed() {
    echo "$1" | sed -e 's/\\/\\x5c/g' -e 's/;/\\x3b/g' -e 's/[[:cntrl:]]/⍰/g'
}

pure_bash() {
    local str="$1"
    str="${str//\\/\\x5c}"
    str="${str//;/\\x3b}"
    str="${str//[[:cntrl:]]/⍰}"
    printf "%s" "${str}"
}

do_test() {
    local r0="$1"
    local r1="$(using_sed "$r0")"
    local r2="$(pure_bash "$r0")"
    local s0="$(printf '%s' "$r0" | od -A x -t x1z -w40 | head -n1)"
    local s1="$(printf '%s' "$r1" | od -A x -t x1z -w40 | head -n1)"
    local s2="$(printf '%s' "$r2" | od -A x -t x1z -w40 | head -n1)"
    if [ "$r1" != "$r2" ] || [ "$s1" != "$s2" ] ; then
        echo "Input: $s0"
        echo "sed:   $s1"
        echo "bash:  $s2"
        ret=1
    fi
}

do_test ''
do_test "one ; semicolon"
do_test "two ; semicolons ;"
do_test 'bs \ sc ; bs \ sc ;'
do_test $'\t'
do_test $'sc ; cntrl \x01 \x02 \x03 \x1f \t bs \\ bs \\ sc ; '
do_test $'sc ; tab \x09 del \x7f  bs \\ ;'

# The last cases show that the existing function doesn't actually work in
# the case of $PWD containing a newline character, because sed is
# line-oriented, so a newline character will never be replaced.
if [ "$1" = "all" ] ; then
    do_test $'embedded \n newline'
    do_test $'ending in newline\n'
fi

exit "$ret"
=== test.sh ===
2026-07-21 11:06:26 +02:00
Yu Watanabe ab373b2cec Assorted cleanups for #42978 (#43051)
https://github.com/systemd/systemd/pull/42978
2026-07-21 14:03:49 +09:00
Yu Watanabe bda98358d2 tools: reject invalid inputs and align machine-readable output (#43040) 2026-07-21 12:23:00 +09:00
Yu Watanabe 8eede7122f sd-device: allow non-safe characters in uevent files
This partially reverts 13ce62caba.

Sometimes, the kernel passes non-safe characters in uevent files,
such as the UNIQ= property for USB serial devices.

Instead of rejecting the entire uevent file, let's only ignore the
specific key-value pairs that contain non-safe characters.

Fixes #43008.
2026-07-21 12:19:32 +09:00
Yu Watanabe 97653d10ff hwdb: strip the root from filenames when generating hwdb.bin (#43062)
The modern hwdb.bin format contains the filenames of the input data that
makes up the database. This is useful but in offline builds where --root
is used, the filenames are the full build paths including the specified
root. This introduces build paths and thus information leakage and
non-reproducible data.

Solve this by stripping the root prefix off the original path when
passing to import_file.
2026-07-21 12:19:00 +09:00