Prompted by https://github.com/systemd/systemd/pull/37646#discussion_r2126882561
Follow-up for 879952a853
Currently, almost all cgroup attr getters check cgroup_path for whether
cgroup is around. This is actually great, because we never want to expose
a non-existent cgroup path via IPC and such. However, it is spuriously
initialized at places where it shouldn't be, e.g. in unit_warn_leftover_processes().
This matters especially to units that *may* carry processes to run, but
not *always*, notably socket units. unit_warn_leftover_processes() is supposed
to be informative only and not try to set cgroup tracking to realized in
a half-assed way.
Hence, let's kill cgroup_realized field, and make sure cgroup_path is set
only if cgroup has been created. Be extra careful with deserialization
though, since the previous versions don't follow this rule and we need
to patch cgroup_path manually based on cgroup_realized we got from deserialization.
Calls to unit_watch_cgroup*() are dropped in cgroup_runtime_deserialize_one(),
because unit_deserialize_state() will invalidate cgroup realized state and
reapply later.
When starting unit A, a dependent unit B may be loaded if it is not
loaded yet, and the dependencies in unit A may be updated.
As Hashmap does not allow a new entry to be added in a loop, we need to
restart loop in such case.
Fixes a bug introduced by cda667722c.
Fixes#36031.
Our baseline is v5.4 and cgroup v2 is enforced now,
which means CPU accounting is cheap everywhere without
requiring any controller, hence just remove the directive.
If DefaultDependencies=no, /var/ may not be mounted yet when the service
is being started. Previously, In such case, if the service has
PrivateTmp=disconnected, the service manager created /var/tmp/ on the
root filesystem and mounted the disconnected private tmpfs there. That
poluted the root filesystem and disturbed gpt-auto-generator on next
boot, as /var/ would not be empty anymore. See issue #37258.
This changes PrivateTmp=disconnected as the following:
- If DefaultDependencies=no and RootDirectory=/RootImage= are not set,
then a private tmpfs is mounted _only_ on /tmp/, and set $TMPDIR=/tmp
environment variable to suggest the service to use /tmp/.
- If DefaultDependencies=yes and RootDirectory=/RootImage= are not set,
then implies RequiresMountsFor=/var/, though that is typically
redundant, but anyway. Hence, we can safely mount /var/tmp/.
- Otherwise, i.e. when one of RootDirectory=/RootImage= is set, behaves
as the same as the previous, as the private root filesystem for the
service is explicitly prepared by the service manager, and we can
safely mount a private tmpfs on /var/tmp/ without any extra
dependencies.
Fixes#37258.
Co-authored-by: Mike Yuan <me@yhndnzj.com>
Currently there are various circular dependencies between headers
in core/. Let's get rid of these by making judicious use of forward
declarations and moving includes into implementation files instead of
having them in header files.
Getting rid of circular header includes simplifies the code and makes
various clang based tooling such as iwyu work much better on our code.
The most important change is getting rid of the manager.h include in
unit.h which is possible thanks to the previous commits. We also move
the OOMPolicy and StatusType enums to unit.h to remove the need for
other unit headers to include manager.h to get access to these enums.
There's no need for these to be fields inside the manager struct,
let's turn them into functions in unit.h instead, again to allow
forward declaring the Manager struct in a later commit.
The PidRefs are in all cases owned by Unit.pids, and gets removed
from Manager.watch_pids(_more) when the unit is destructed, via
unit_unwatch_pidref(). This hasn't caused any issue because
manager_clear_jobs_and_units() is called before destroying
Manager.watch_pids(_more), but let's get this right.
We'd previously return what was already set. Let's instead return a
clear ENOEXEC in this case, to make clear what is going on: preset logic
doesn't apply to units which lag a fragment path.
"-1" is not a valid enum value. Use a better one. All code using this
considers negative values error codes anyway, hence the old code was
just a weird way to write -EPERM. Let's clean this up.
I noticed that we keep querying the preset database for transient units,
which makes little sense, since transient units are well, transient, and
hence not suject to enablement/disablement. Hence, let's shortcut things
and simply not check the preset database for them.
While we are at it, shortcut unit file state checks for transient units,
too. We know they are transient already, we can return that directly,
no need to go to disk.
Finally, treat perpetual units like transient units for the the preset
case: also bypass the preset database. (But keep checking for the unit
file state for them, since it *is* relevant to know whether they were
generated or not.)
This introduce LOG_ITEM() macro that checks arbitrary formats in
log_struct().
Then, drop _printf_ attribute from log_struct_internal(), as it does not
help so much, and compiler checked only the first format string.
Hopefully, this silences false-positive warnings by Coverity.
This adds a new EMERGENCY_ACTION_SLEEP_5S flag, which when set will
delay the emergency action for 5s. This is supposed to be used together
with EMERGENCY_ACTION_WARN so that users can actually read the message
we output.
We enable this with all emergency action requests that already set
EMERGENCY_ACTION_WARN, except for the 7x ctrl-alt-del burst reboot,
where the user knows what they do and there's no real reason to wait,
they don't need to be informed.
This also enables both EMERGENCY_ACTION_WARN + EMERGENCY_ACTION_SLEEP_5S
for FailureAction= processing of regular units, where these were so far
off. (it leaves this off for SuccessAction= however!). This is a good
thing to make things more debuggable: if something fails and we reboot
this really deserves notification of the user.
(For SuccessAction= this logic does not apply, since the shutdown action
induced here is apparently intended part of the codeflow, for example in
systemd-reboot.service or a similar unit, where the shutdown is goal and
not exception and derserves no additional noisy reporting).
Inspired by: https://github.com/systemd/systemd/pull/36705#issuecomment-2717014120
This also ports over things to use chase() to create/pin the underlying
to mount, and in particular checks that the path does not contain any
symlinks. That's crucial since we cannot allow mounts to be established
with that, since it would mean we couldn't recognize the entries in
/proc/self/mountinfo anymore.
Note that this drops a lot of "const" qualifiers on PidRef arguments.
That's because pidref_is_self() suddenly might end changing the PidRef
because it acquires the pidfd ID.
We had this previously already with pidfd_equal(), but this amplifies
the problem.
I guess we C's "const" doesn't really work for stuff that contains
caches, that is just conceptually constant, but not actually.
If bus_add_match_full() is called without install callback and we failed
to install the signal match e.g. by timeout, then add_match_callback()
will disconnect from the bus.
Let's use a custom install handler and handle failures gracefully.
This does not *solve* the root cause of issue #30573, but should improve
the situation when the issue is triggered.
Follow-up for c26948c6da
We only want to get rid of cred mount here, and RuntimeDirectory=
is documented to be retained for SERVICE_EXITED state.
Fixes#35427
This new setting allows unsharing the pid namespace in a unit. Because
you have to fork to get a process into a pid namespace, we fork in
systemd-executor to get into the new pid namespace. The parent then
sends the pid of the child process back to the manager and exits while
the child process continues on with the rest of exec_invoke() and then
executes the actual payload.
Communicating the child pid is done via a new pidref socket pair that is
set up on manager startup.
We unshare the PID namespace right before the mount namespace so we
mount procfs correctly. Note PrivatePIDs=yes always implies MountAPIVFS=yes
to mount procfs.
When running unprivileged in a user session, user namespace is set up first
to allow for PID namespace to be unshared. However, when running in
privileged mode, we unshare the user namespace last to ensure the user
namespace does not own the PID namespace and cannot break out of the sandbox.
Note we disallow Type=forking services from using PrivatePIDs=yes since the
init proess inside the PID namespace must not exit for other processes in
the namespace to exist.
Note Daan De Meyer did the original work for this commit with Ryan Wilson
addressing follow-ups.
Co-authored-by: Daan De Meyer <daan.j.demeyer@gmail.com>
Given that we have the LabelOps abstraction these days, we can teach
write_string_file() to use it, which means we can get rid of
fileio-label.[ch] as a separate concept.
(The only reason that fileio-label.[ch] exists independently of
fileio.[ch] was that the former linekd to libselinux potentially, and
thus had to be in src/shared/ while the other always was in src/basic/.
But the LabelOps vtable provides us with a nice work-around)
Let's debug log the returned dbus error where we want the logging, but
don't log it, where we don't.
This removes the noisy logging from the property handler for the
CanLiveMount property, but keeps it in place for the MountImage() method
call where we want it.
Alternative to #34175
Follow-up for 5162829ec8 and 1cafbecabe
The name of the parameter is misleading and it does not save us much
work because it is not used during regular unit property queries.
It is only used during unit_log_resources(), and the cgroup is already
dead by that point so it won't be read anyway.