We have two bools followed by a func pointer, which is aligned to e.g. 8 bytes,
so whether the two bools take one bit, one byte, or even a full word, makes no
difference in storage size. But the code generated to service a bitfield is
more complicated.
Also switch to FOREACH_ARRAY().
Follow-up for 4d8b0f0f7a
After the mentioned commit, when the ExecCommand executable is missing,
and failure will be ignored by manager, we exit with EXIT_SUCCESS at executor
side too. The behavior however contradicts systemd.service(5), which states:
> If the executable path is prefixed with "-", an exit code of the command
> normally considered a failure (i.e. non-zero exit status or abnormal exit
> due to signal is _recorded_, but has no further effect and is considered
> equivalent to success.
and thus makes debugging unexpected failures harder. Therefore, let's still
exit with EXIT_EXEC, but just skip LOG_ERR level log.
This is useful for situations where an array of FDs is to be passed into
a child process (i.e. by passing it through safe_fork). This function
can be called in the child (before calling exec) to pack the FDs to all
be next to each-other starting from SD_LISTEN_FDS_START (i.e. 3)
Though, when unit_prepare_exec() is called, the unit should always
have the cgroup runtime context 'crt'. So, I think we can insert assert().
But, for consistency with other places that call unit_get_cgroup_runtime(),
here use the simple non-NULL check for 'crt' instead of using assert().
Follow-up for 9cc545447e.
Fixes CID#1534667.
This refactors the Unit structure a bit: all cgroup-related state fields
are moved to a new structure CGroupRuntime, which is only allocated as
we realize a cgroup.
This is both a nice cleanup and should make unit structures considerably
smaller that have no cgroup associated, because never realized or
because they belong to a unit type that doesn#t have cgroups anyway.
This makes things nicely symmetric:
ExecContext → static user configuration about execution
ExecRuntime → dynamic user state of execution
CGroupContext → static user configuration about cgroups
CGroupRuntime → dynamic user state of cgroups
And each time the XyzContext is part of the unit type structures such as
Service or Slice that need it, but the runtime object is only allocated
when a unit is started.
Let's make sure that versions generated by meson-vcs-tag.sh always
sort higher than official and stable releases. We achieve this by
immediately updating the meson version in meson.build after a new
release. To make sure this version always sorts lower than future
rcs, we suffix it with "~devel" which will sort lower than "~rcX".
The new release workflow is to update the version in meson.build
for each rc and the official release and to also update the version
number after a new release to the next development version.
The full version is exposed as PROJECT_VERSION_FULL and used where
it makes sense over PROJECT_VERSION.
We also switch to reading the version from a meson.version file in
the repo instead of hardcoding it in meson.build. This makes it
easier to access both inside and outside of the project.
The meson-vcs-tag.sh script is rewritten to query the version from
meson.version instead of passing it in via the command line. This
makes it easier to use outside of systemd since users don't have to
query the version themselves first.
The situation is a service like
Type=notify
NotifyAccess=main
and the service uses some of the systemd helper utilities, e.g.
coredumpctl. The service process will pass NOTIFY_SOCKET to the helper
child (accidentally) and the result is a spurious notification and
the warning message:
> Jan 18 09:38:01 host systemd[1]: sdnotify.service: Got notification message from PID 13736, but reception only permitted for main PID 13549
Notification from helpers seem like an unintentional composition of the
commit c118b577fa ("coredumpctl: define main through macro") and commit
6b636c2d27 ("main-func: send main exit code to parent via sd_notify() on
exit"). The former used the handy macro for a main function, the latter
equipped any main function with the notification. (Further extended in
the commit 623a00020f ("notify: Add EXIT_STATUS field").)
Since notification from systemd utitilities are meant to extend
rudimentary exit()/wait() pair generally, they may happen to land into
service's NOTIFY_SOCKET. Tone down messages of notification that won't
match NotifyAccess=.
The setting currently puts limits on connections per IP address and
AF_UNIX CID. Let's extend it to cover AF_UNIX too, where it puts a limit
on connections per UID.
This is particularly useful for the various Accept=yes Varlink services
we now have, as it means, the number of per-user instance services
cannot grow without bounds.
I think this was just overlooked in #13754, which removed
the restriction of Restart= on Type=oneshot services.
There's no reason to prevent RestartForceExitStatus=
now that Restart= has been allowed.
Closes#31148
This was discussed in
https://github.com/systemd/systemd/pull/13754#discussion_r333395362.
I think we should actually list "success" Restart= settings instead.
There are more error statuses than success ones after all, and this
list hasn't really changed for quite some time.
Currently in many of our test cases you'll see a warning about a tun
device not being around. Let's make that quiet, since if there's no such
device there's no point in adding it to a policy anyway, and it makes
useless noise go away.
We keep the warning as a warning if a device node is missing for other
errors than ENOENT.
under some conditions we suppress generating BPF programs. Let's
systematically return 0 when we do this, and 1 if we did actually
soething, instead of second guessing this in the caller.
This is not only more correct, but allows us to suppress BPF programs in
more cases in later commits.
There's some unclarity whether major/minor of device nodes are supposed
to be "unsigned" or "dev_t". Various codebases assume the latter, but
glibc's major()/minor() types actually return a value typed to
"unsigned". On glibc dev_t is actually 64bit even if the kernel only
exposes 32bit. Hence this distinction kinda matters.
Let's clean things up a bit with handling: let's followe glibc's type
system here, and use unsigned (and not int).
Also let's pass invalid major/minor values around as UINT_MAX rather
than via pointers, to match how we usually do this, and to shorten our
code a bit. This is safe, since given the linux dev_t space being 32bit
only we can't possibly have a valid major or minor this hight, given
they must be smaller in size. While other archs disagree on the types of
major/minor, they also tend to have similar limits. In fact on FreeBSD
for example major()/minor() returns a signed int. Which would hence also
mean that UINT_MAX cannot be a valid major or minor.
fresh otherwise
Currently, exec_setup_credential() always rewrite all credentials
upon exec_invoke(), i.e. invocation of each ExecCommand, and within
a single tmpfs instance. This is problematic though:
* When writing each tmp cred file, we essentially double the size
of the credential. Therefore, if one cred is bigger than half
of CREDENTIALS_TOTAL_SIZE_MAX, confusing ENOSPC occurs (see also
https://github.com/systemd/systemd/pull/24734#issuecomment-1925440546)
* Credential is a unit-wide thing and thus should not change
during the whole lifetime of main process. However, if e.g.
a on-disk credential or SetCredential= in unit file
changes between ExecStart= and ExecStartPost=,
the credentials are overwritten when the latter gets to run,
and the already-running main process is suddenly seeing
completely different creds.
So, let's try to reuse final cred dir if the main process has started
and the tmpfs has been populated, so that the creds used is stable
across all ExecStart= and ExecStartPost=-s. We still want to retain
the ability of updating creds through ExecStartPre= though, therefore
we forcibly use a fresh cred dir for those. 'Fresh' means to actually
unmount the old tmpfs first, so the first problem goes away, too.
I tried to be conservative here, and hence in doubt I left the flag off,
but in some cases I really can't see any reason why it would make sense
to specifiy paths into API VFS, hence add it there, to lock things down
a bit.
Inspired by CVE-2024-21626, let's add a longer comment explaining why
the code really shouldn#t be moved any earlier.
Just in the hope that anyone who feels tempted to move this around maybe
actually reads the comment and reconsiders.
In various contexts it's a bit icky to allow paths below /proc/, /sys/,
/dev/ i.e. file hierarchies where API VFS are placed. Let's add a new
flag for path_simplify_and_warn() to check for this and refuse a path if
in these paths.
Enable this when parsing WorkingDirectory=.
This is inspired by CVE-2024-21626, which uses trickery around the cwd
and /proc/self/fd/.
AFAICS we are not actually vulnerable to the same issue as explained in
the CVE since we execute the WorkingDirectory= setting very late, i.e.
long after we set up the new mount namespace. But let's filter out icky
stuff better earlier than later, as extra safety precaution.
This seems to be a mistake in #27279. I believe credentials should
not be made available to condition or reload tasks. In most cases
they're irrelevant from the actual job of the service. Also, currently
the first ExecCondition= or ExecReload= cannot access creds anyway,
making the incompatibility introduced negligible.
If people actually come up with valid use cases, we can always
revisit this.