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.
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.
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.
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.
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).
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
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
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
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
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
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>
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.
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.
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.
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.
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.
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.
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.
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 ===
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.
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.
Add Sony PlayStation controller entries to 70-sound-card.hwdb so that their
ALSA sound devices are tagged with SOUND_FORM_FACTOR=controller:
- DualSense (054c:0ce6)
- DualSense Edge (054c:0df2)
- DualShock 4 CUH-ZCT1x (054c:05c4)
- DualShock 4 CUH-ZCT2x (054c:09cc)
These controllers expose USB audio but are neither headsets nor speakers.
Pinning them in the hwdb ensures they are identified correctly before any
fallback matching occurs.
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.
Add TEST-17-UDEV.hwdb.sh to verify that hwdb.bin files contain the
path inside the root, but not the path of the root.
Nowadays, varlink is used to control systemd-udevd. Let's drop the
legacy socket.
Note, the existence of /run/udev/control socket is widely used in both
our code and external projects. Also, the dependency to
systemd-udevd-control.socket is widely used in many projects. Hence, we
need to create a symlink to the socket file and .socket unit file.
Add a new --no-reconfigure flag to 'networkctl reload' that reloads
.network and .netdev files from disk without reconfiguring any network
interfaces. This may be useful to avoid reconfiguring multiple interfaces
simultaneously when multiple .network files are updated, or when an updated
.network file is applied to multiple interfaces.
On the networkd side, manager_reload() gains a reconfigure_links parameter
that gates the per-link reconfiguration loop. A new io.systemd.Network.Reload
varlink method is added that exposes this as an optional reconfigureLinks
boolean (defaults to true). Both plain 'networkctl reload' and
'--no-reconfigure' now unconditionally call this method first. If an older
networkd returns MethodNotFound, plain reload falls back to
io.systemd.service.Reload for backward compatibility; '--no-reconfigure'
fails with a clear error in that case.
bus_init_api() issued a synchronous GetId call on every API bus
(re-)connection to decide whether saved subscription state could be
coldplugged onto the new connection.
If the D-Bus socket unit is listening while the message bus daemon
behind it is gone, connect() succeeds against the socket backlog but
nothing answers the authentication handshake. The synchronous call
then blocks PID 1 for BUS_AUTH_TIMEOUT (90 seconds by default), and
queued bus operations can trigger repeated reconnection attempts.
This was observed during shutdown as roughly 15 minutes of teardown
progressing only in 90-second intervals.
Query the instance ID asynchronously on every connection. Defer API
setup until the reply is processed, so saved subscriptions are
validated and coldplugged before new subscription requests can arrive.
If the query cannot be queued or its reply is invalid, discard the
unvalidated state and expose the API without blocking the manager.
Reset the live bus ID on every connection and serialize pending bus ID
and subscription state across reload and reexec. During daemon-reload,
preserve state that was already awaiting the asynchronous reply while
discarding the duplicate state produced by the reload itself.
Also remove the now-unused synchronous bus_get_instance_id() helper.