The helper reaches a user manager with the uid@ machine transport. That
transport runs systemd-run, which opens a PAM login session for the user.
In that session, systemd-stdio-bridge connects to the user's D-Bus broker.
rpm runs the helper once per package scriptlet. A large transaction therefore
opens many login sessions for every logged-in user. The operations also fail
whenever the user's D-Bus broker is not running.
The user manager accepts connections from root on its private socket, and
systemctl --user uses the same socket. Connect to
/run/user/UID/systemd/private directly with bus_connect_user_systemd_by_uid().
The user owns /run/user/UID. The function therefore refuses a socket that the
user does not own or that a process of another user listens on. Otherwise a
user could point the helper at the private socket of the system manager.
systemd-update-helper runs as root and needs to connect to the private socket
of each user manager. The user owns /run/user/UID, which contains that socket,
and can replace the socket with a symlink or a hardlink. The private socket of
a capsule is in a directory that the capsule user owns too.
bus_set_address_capsule() therefore refuses symlinks and pins the socket inode
before connecting.
Generalize pin_capsule_socket() to take a full path, and add
bus_connect_user_systemd_by_uid() on top of it. The function connects only to
a socket that the user owns, and only when a process that runs as the user
listens on it. The owner of a socket inode is not always the process that
listens on it. For example, PID 1 listens as root on the socket of a socket
unit with SocketUser= set to the user.
A process of the user passes both checks when it listens on the socket. That
process can send file descriptors until the file descriptor table of the
caller is full. The function therefore refuses file descriptors from the peer.
Most lookups find the range in the window of their category. On such a
hit, mmap_cache_fd_get() still calls category_attach_window(), which
returns without doing anything because the window is attached already.
mmap_cache_fd_get() also gets the cache through mmap_cache_fd_cache(),
which is not inlined.
Set the flag and return directly on a hit. Reading 1M entries of a real
journal takes 1.3% fewer cycles.
ret_parameters (and ret_error_id) returned by sd_varlink_call()/
sd_varlink_callbo() are borrowed from the connection, as documented in
sd-varlink.h, and must not be unreffed by the caller. process_hostname()
declared its reply as _cleanup_(sd_json_variant_unrefp), freeing memory
owned by the Varlink connection and leading to a use-after-free/
double-free (the same bug class and ownership mistake just fixed for
pcrextend_pcr_now()/pcrextend_nvpcr_now() in 76a6dc6d).
The arg_verb was copying the pointer to the shutdown verb, but that
pointer was being overwritten. When the shutdown scripts run, the forked
child calls rename_process() which overwrites argv, so the scripts got
an empty $1 instead of reboot, poweroff, etc.
Make a copy of the verb with strdup() so it is not affected.
Fixes: #44087
Follow-up for: 4927588993
Like other pre-Vivaldi Chromebooks, the Pixelbook's top row sends the
standard F1-F10 scancodes and Chrome OS translates them to actions in
userspace, so elsewhere the keys come through as F1-F10 even though
they are labelled Back, Refresh, Fullscreen, Overview, brightness down
and up, play/pause, mute and volume down and up. Map them to the
printed functions. Also map the menu key next to volume up (scancode
0x5d, F13 by default) to KEY_CONTROLPANEL and the Assistant key
(scancode 0xd8, which atkbd reports as unknown) to KEY_ASSISTANT, as
Chrome OS's own Eve hwdb does.
XKB_FIXED_MODEL=chromebook, used for Falco and Peppy, does not fit:
that model follows the original Chromebook top row (F2 Forward, F3
Refresh, brightness on F6/F7), while the Eve has Refresh on F2,
brightness on F5/F6, Play/Pause on F7 and no Forward key.
Tested on a Pixelbook with the DMI modalias
dmi:bvncoreboot:bvrGoogle_Eve.9584.230.0:...:svnGoogle:pnEve:...
The 2017 Google Pixelbook (Eve) is a 2-in-1 with a 360° hinge, but its
firmware reports SMBIOS chassis type 3 (Desktop), so hostnamed reports
"desktop". Override it to "convertible". The ACPI power profile also
says "desktop", so nothing else corrects it.
Tested on a Pixelbook with the DMI modalias
dmi:bvncoreboot:bvrGoogle_Eve.9584.230.0:...:svnGoogle:pnEve:...
logind now implements io.systemd.Metrics on
/run/systemd/report/io.systemd.Login, via the new
systemd-logind-metrics.socket, and reports:
- io.systemd.Login.SessionsStarted: counter of sessions started since
boot, by session class (field class=)
- io.systemd.Login.CurrentSessions: gauge of current sessions, including
those in closing state, by session class (field class=)
- io.systemd.Login.SuspendCounter: counter of suspend cycles, as reported
by the kernel in /sys/power/suspend_stats/ (field result=success|fail)
logind now counts started sessions by session class in
/run/systemd/login-counters, which it keeps mapped for its whole
runtime. The counters are monotonic (i.e. are not decreased on logout),
survive restarts of logind, but are reset on reboot.
Sessions are counted where they are created (via D-Bus or Varlink), not
in session_start(), since the latter is also called for sessions
restored after a restart of logind.
The counters are an array indexed by SessionClass (minus SESSION_NONE,
which is never registered with logind), hence the enum now carries a
note that its order determines the file layout.
journald now implements io.systemd.Metrics on
/run/systemd/report/io.systemd.JournalDaemon, via the new
systemd-journald-metrics.socket, and reports the message counters as
io.systemd.JournalDaemon.MessagesByPriority (field priority=) and
io.systemd.JournalDaemon.MessagesByTransport (field transport=).
Metrics requests are processed at a lower event loop priority than
incoming log messages. For now only the main journald instance provides
metrics, not the namespace instances.
Like the audit socket, the metrics socket is not listed in Sockets= of
the service, so that it can be disabled.
journald now counts received log messages by priority and by transport
in $RUNTIME_DIRECTORY/counters, which it keeps mapped for its whole
runtime. The counters hence survive restarts of journald, but are reset
on reboot.
Messages are counted in each transport right after their priority is
known, i.e. before any filtering (LogLevelMax=, LogFilterPatterns=,
MaxLevelStore=, Storage=none) or rate limiting is applied. Kernel
messages are only counted after the kernel seqnum check, so that
messages seen before a restart are not counted twice. journald's own
messages are not counted.
This introduces a JournalTransport enum for the transports we receive
messages on, whose string names match the _TRANSPORT= field.
This adds a small helper that creates (if needed) and maps a file in
/run/ that contains a 64-bit version field followed by raw 64-bit
counters. If the file has a different size or version than expected it
is reset. This is intended for daemons that want to maintain monotonic
counters that survive restarts of the daemon, but not reboots.
This new wrapper for munmap() asserts on a bunch of unexpected
conditions:
1. if we try to unmap a valid pointer with a zero size
2. if we try to unmap a valid pointer with a size of SIZE_MAX (this
is supposed to catch PAGE_SIZE() overflows, which is often used in
combination)
3. munmap() failing
It also turns invocations with a NULL or MAP_FAILED pointer into NOPs.
That's useful to simplify error clean-up paths in case mmap() failed.
Finaly it returns a NULL pointer to the input type, so that we can
write:
p = mummap_safe(p, sz);
to invalidate both memory and the pointer p in one go.
Otherwise, if sd_event_add_inotify() is called with NULL for ret,
the event source is disabled and never triggered.
Fixes a bug introduced by e67d738a87.
manager_get_dns_server() may re-read /etc/resolv.conf and replace
m->dns_servers and m->search_domains, but it was passed as an argument
to dns_configuration_json_append() together with those lists, and the
order of evaluation of the arguments is unspecified. gcc with LTO reads
the list heads first, so after a foreign /etc/resolv.conf has changed
the freed lists are walked. Typically the serialization then fails with
EUCLEAN, which makes the SubscribeDNSConfiguration method of
io.systemd.Resolve.Monitor and in turn systemd-networkd-wait-online
--dns fail.
Call manager_get_dns_server() first and store the result in a local
variable.
Tests exist to test stuff, hence we should not use plain assert(), but
the ASSERT_XYZ() macros, which are never compiled out and print useful
information on failure.
gcc 13 on armhf complains with -Wmaybe-uninitialized about family, port
and server_name in bus_message_read_dns_array(), even though they are
always set when bus_message_read_dns_one() returns > 0.
journal_file_move_to_object() maps the object header, reads the object
size from it, and then looks up the window again for the whole object.
That second lookup finds the same window nearly every time, since
windows are 8 MiB and most objects are small.
Have mmap_cache_fd_get() return how many bytes the window has after the
offset, and skip the second lookup when the object fits in the window
and in the file. Reading 1M entries of a real journal takes 10.7% fewer
cycles.
The root row in systemd-cgtop previously displayed whole-system RAM
usage read from /proc/meminfo (MemTotal - MemAvailable), not a cgroup
sum. This is a pragmatic fallback — the kernel intentionally does not
expose memory.current on the v2 root cgroup (see the existing
is_root_cgroup() comment about avoiding 'multiple truth about system
state'), so cgtop picked /proc/meminfo to fill the gap.
Nevertheless, that caued the '/' row to provide different information
than every other row in the table:
- All child rows: 'what is this cgroup charged for?' (anon + file
+ sock + shmem attributable to the cgroup).
- Root row: 'what is the whole system using?' (includes kernel
slab, vmalloc, pagetables, zram mem_used, and anything not
attributable to any cgroup).
On a typical desktop the root row can read ~10 GB while the sum of
direct children is ~5 GB, with no explanation visible in the tool
itself.
This commit:
1. Introduces --root-memory= command line option.
2. Flips the default for the root row to the sum of memory.current
over its direct children.
3. Adds a '/' interactive key that toggles between the two modes.
4. Updates the interactive help string ('?' / 'h'), the man page,
and the bash completion for the new option.
Inside a container (detect_container() > 0), is_root_cgroup() already
returns false, so none of this applies — the container's '/' still
reads memory.current from the namespaced cgroup as before.
Co-authored-by: Zbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
cleanup() is only called via 'trap cleanup EXIT', which newer shellcheck
versions report as SC2329 rather than SC2317. Disable both, like the other
test scripts do.
On CI (Azure runners) the accelerated networking PCI VF behind the
Hyper-V vmbus PCI bridge may be hot-unplugged while the test runs,
causing sd_device_new_from_syspath() to fail with ENODEV for a device we
just enumerated:
test_sd_device_one(/sys/devices/LNXSYSTM:00/.../pci7870:00/7870:00:00.0)
Assertion failed: Expected "sd_device_new_from_syspath(&dev, syspath)"
to succeed, but got error: -19/ENODEV
Skip devices whose syspath vanished since enumeration rather than
failing.
One of the fundamental counters we need to cover in metrics are
packet/byte counters on network interfaces. Let's add this.
We do this separately from networkd, to not unnecessarily affect
networkd operations.
These checks stem from a rework from strv to a proper varlink object,
but the whole rework's point was to allow more expressive field types,
hence drop the unnecessary verification of the string type.
While systemd-report is conceptually designed to provide freshness
guarantees without nonces (for example via TPM clock, TSA or generation
counters), it sometimes is useful to provide a nonce, when talking
directly and synchronously to a node, instead of asynchronously.
Hence, let's just extend the Generate Varlink calls with a nonce
argument.
… determine system uptime
And while we are at it, let's also expose CLOCK_REALTIME, all in nsec
accuracy.
(The realtime clock is also included in the report header, but in
calendar format with second granularity.)
The birth time of the root inode of the file system backing /var/ is a
good approximation of when the system was deployed, i.e. when its
persistent file system was created. If /var/ is not a mount point of its
own, use the root file system instead.
The metric is skipped if the file system does not record birth times.
And while we are at it, let's also expose CLOCK_REALTIME, all in nsec
accuracy.
(The realtime clock is also included in the report header, but in
calendar format with second granularity.)
getpid_cached() runs a compare-and-exchange on every call, also when
the PID is cached already. On x86 that is a locked read-modify-write
even when the comparison fails. sd-journal calls getpid_cached() in
every public function to detect use after fork(). Reading the entries
of a journal hence calls it once per entry and field.
Load the cached value first, and only fall back to the exchange if it
is not set. Reading 1M entries of a real journal takes about 2% fewer
cycles.
The Embedded Controller (EC) on the Lenovo ThinkBook 16 G7 (Product
Name: 21MW) fails to transmit PS/2 break codes (E0 B0) for Volume Down
(ae) and Volume Up (b0) upon physical key release after auto-repeat
(long press). This causes the volume keys to become logically stuck
down in the Linux input subsystem. Adding the '!' force-release flag
instructs udev/evdev to automatically synthesize a release event
immediately upon receiving the keypress.