Commit Graph
262 Commits
Author SHA1 Message Date
Yu Watanabe 7f6086d530 tree-wide: do not use %m with SYNTHETIC_ERRNO() 2025-07-22 03:05:54 +09:00
Yu Watanabe 9eabf82750 core: it is not necessary to send message after fsconfig() for bpffs
Instead, let's wait for the helper process being finished.
2025-07-18 20:15:25 +09:00
Yu Watanabe 8509ceea10 core/exec-invoke: negative errno needs to be passed to report_errno_and_exit()
Hence, we cannot pass errno as is to report_errno_and_exit().

This splits out bpffs_helper(), which returns negative errno on failure,
and 0 on success. And make the returned value passed to report_errno_and_exit().

Follow-up for #36134.
2025-07-18 20:15:20 +09:00
Mike Yuan db54d1a6b7 core/exec-invoke: pass "/" instead of "" for cgroup root 2025-07-12 17:32:32 +02:00
Yu Watanabe 543a48b653 libc-wrapper: introduce a tiny libc wrapper
Then, move syscall definitions to the wrapper, and prototypes are moved
to relevant headers.

This also adds checks for add_key() and request_key(), as one day
glibc may be going to add some of them separatedly.

The check for fspick in meson.build is dropped, as it is currently
unused in our code.

This also moves
- basic/missing_bpf.h -> include/override/linux/bpf.h,
- basic/missing_keyctl.h -> include/override/linux/keyctl.h.
2025-07-11 13:05:46 +09:00
Matteo Croce ea9826eb94 core: add options to delegate BPFFS token creation
Add four new options BPFDelegate{Commands,Maps,Programs,Attachments}=
in order to delegate to a BPFFS instance the permission to create tokens.

The value is a list of options taken from:
https://github.com/torvalds/linux/blob/v6.14/include/uapi/linux/bpf.h#L922-L1121
The special value "any" means to allow every possible values.

More informations about BPF tokens here:
https://lwn.net/Articles/947173/
2025-07-08 22:35:29 +02:00
Matteo Croce 3a47437fc9 core: Introduce PrivateBPF= to mount a private BPFFS
Add a new option PrivateBPF= to mount a new instance of bpffs within a
namespace.
PrivateBPF= can be set to "no" to use the host bpffs in readonly mode
and "yes" to do a new mount.
The mount is done with the new fsopen()/fsmount() API because in future
we'll hook some commands between the two calls.
2025-07-08 22:33:28 +02:00
Matteo Croce 2c7dabff50 core: split out setup_private_users_child()
Drop support for kernels older than 3.19, as this is where
/proc/<pid>/setgroups was added.

https://github.com/torvalds/linux/commit/9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8
2025-07-08 18:23:46 +02:00
Andres Beltran 26c6f3271a core: add quota support for State, Cache, and Log exec directories 2025-07-07 17:28:47 +00:00
Yu Watanabe 2643cb1ade core: rename ExecContext.ioprio_set -> .ioprio_is_set
To make it not conflict with syscall ioprio_set().
This is important as we have
```
 #define ioprio_set missing_ioprio_set
```
in missing_syscall.h.
2025-07-06 13:31:40 +02:00
Yu Watanabe 237bdd2771 basic: move missing_sched.h -> include/sched.h 2025-07-01 12:29:15 +09:00
Yu Watanabe 4f18ff2e29 tree-wide: include unistd.h where necessary
We use symbols provided by unistd.h without including it. E.g.
open(), close(), read(), write(), access(), symlink(), unlink(), rmdir(),
fsync(), syncfs(), lseek(), ftruncate(), fchown(), dup2(), pipe2(),
getuid(), getgid(), gettid(), getppid(), pipe2(), execv(), _exit(),
environ, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, F_OK, and their
friends and variants, so on.

Currently, unistd.h is indirectly included mainly in the following two paths:
- through missing_syscall.h, which is planned to covert to .c file.
- through signal.h -> bits/sigstksz.h, which is new since glibc-2.34.
  Note, signal.h is included by sd-eevent.h. So, many source files
  indirectly include unistd.h if newer glibc is used.

Currently, our baseline on glibc is 2.31. We need to support glibc older
than 2.34, but unfortunately, we do not have any CI environments with
such old glibc. CIFuzz uses glibc-2.31, but it builds only fuzzers, and
many files are even not compiled.
2025-06-30 09:19:15 +02:00
Lennart Poettering 5584632f40 cpu-set-util: fix null pointer dereference and several cleanups (#37900)
Fixes CID#1611618.
2025-06-27 14:59:25 +02:00
Lennart Poettering 2be3a06bb2 core: when PrivateDevices= is enabled and we need to decrypt TPM2 credentials, go via IPC
Also, if a device ACL list is defined, also go via IPC (instead of
trying to patch it, as before).

The outcome is that the tighter rules continue to apply when configured.

Fixes: #35959
2025-06-24 22:16:01 +02:00
Yu Watanabe 296fe3d511 cpu-set-util: rename cpu_set_reset() -> cpu_set_done()
This also introduces cpu_set_done_and_replace().

No functional change, just refactoring.
2025-06-24 00:20:20 +09:00
Yu Watanabe df77ec5d3a exec-invoke: modernize exec_context_cpu_affinity_from_numa()
- always assign 'ret' on success,
- do not modify previous assignment of 'ret', and simply overwrite it.

No functional change, just refactoring.
2025-06-24 00:20:20 +09:00
Daan De Meyer f8f67eab70 core: Make sure we handle DelegateSubgroup= in combo with cgroupns
Currently, if we use a cgroup namespace together with DelegateSubgroup=,
the subgroup becomes the root of the cgroup namespace because we move the
service process to the subgroup before we unshare the cgroup namespace, and
the current cgroup becomes the root of the cgroup namespace when we unshare
the cgroup namespace.

Let's fix the problem by not moving the service process to the subgroup until
we've unshared the cgroup namespace. Note that this doesn't break the primary use
case of CLONE_INTO_CGROUP since we still use it to immediately clone into the service
main cgroup, just not anymore into the subgroup, but this shouldn't matter in practice.

Additionally, we need special handling for control processes, as those *do*
need to get spawned into the subcgroup immediately if delegation is configured to
avoid violating the cgroupsv2 "no inner processes" rule.

Effectively, this leaves us with the following logic:
- In exec_spawn(), spawn into subgroup if we're spawning a control process
  that needs to be spawned into a subgroup immediately. Otherwise, spawn into
  main service cgroup.
- In exec_invoke(), move into subgroup early if we don't need a cgroup namespace.
  Otherwise, move into subgroup after we've unshared the cgroup namespace.
2025-06-05 12:37:02 +02:00
Daan De Meyer 2d8191f4af core: Disable pid namespacing for control processes
PID namespaces frankly don't make any sense for control processes, so
let's gracefully degrade to no pid namespaces for control processes.
2025-06-05 12:37:02 +02:00
Mike Yuan 6131dc0aad core/exec-invoke: skip query of /dev/console $TERM if we're child of pid1 2025-05-29 21:25:28 +02:00
Mike Yuan 8ffebaaf4d core/exec-invoke: propagate $COLORTERM and $NO_COLOR from pid1 as well
Follow-up for 19aff5f775
2025-05-29 21:16:28 +02:00
Mike Yuan 3235fae685 core/exec-invoke: rework where to apply $TERM fallback logic
Follow-up for 728dbaeffb
and ad6ca4a612

This is inspired by #37538, see the discussion in
https://github.com/systemd/systemd/pull/37538#discussion_r2110229075.

If the user already specifies $TERM (which is actually
quite common if you look at run0), we'd needlessly invoke
the "fallback" logic and
a) possibly issue a DCS query whose result we end up simply
   discarding in strv_env_merge()
b) set $COLORTERM to "truecolor" unconditionally, whereas
   the explicit $TERM value might intend to disable the color output

To address this, the logic of setting fallback $TERM and friends
has been split out of build_environment(), and we'd call into it
only after all envvars have been collected.
2025-05-29 21:16:25 +02:00
Mike Yuan 94f533e305 core: strv_env_clean() modifies in-place, no need to set buf to itself 2025-05-29 21:01:43 +02:00
Mike Yuan c51379e6d8 Use DCS sequence to query terminal name and set $TERM automatically (#37538)
This code seems to work quickly and nicely for a bunch of modern
terminals. Setting $TERM automatically removes an common annoyance for
users. This code will not work for all terminal emulators, but by adding
it in systemd we'll entice maintainers of those terminals to add support
for the sequences. For the terminals that don't support the sequence, we
get a bit of a slowdown of `< 1 ms`, which seems hardly noticeable. The
user can always set TERM explicitly to avoid this if upgrading to a
newer terminal emulator is not possible.

Closes https://github.com/systemd/systemd/issues/36994.
2025-05-29 21:01:01 +02:00
Zbigniew Jędrzejewski-Szmek ad6ca4a612 core: use terminal DCS sequence to set $TERM
query_term_for_tty() is used in two places: in fixup_environment(),
which affects PID1 itself, and in build_environment(), which affects
spawned services. There is obviously some cost to the extra call,
but I think it's worthwhile to do it. When $TERM is set incorrectly,
basic output works OK, but then there are various annoying corner
cases. In particular, we get the support for color (or lack of it)
wrong, and when output is garbled, users are annoyed. Things like
text editors are almost certain to behave incorrectly. Testing in
test-terminal-util indicates that the time required to make a successful
query is on the order of a dozen microseconds, and an unsuccessful
query costs as much as our timeout, i.e. currently 1/3 ms. I think
this is an acceptable tradeoff.

No caching is used, because fixup_environment() is only called once,
and the other place in build_environment(), only affects services
which are connected to a tty, which is only a handful of services,
and often only started in special circumstances.

Fixes https://github.com/systemd/systemd/issues/36994.
2025-05-29 19:20:31 +02:00
Mike Yuan 8b0a0298b7 core/exec-invoke: don't set $TMPDIR if sandboxing is disabled
Follow-up for 6156bec7a4
2025-05-27 22:35:03 +02:00
Daan De Meyer 836e4e7ea8 core: Clean up includes
Split out of #37344.
2025-05-22 09:37:20 +02:00
Mike Yuan 81d5eda6c5 core: accept "|" ExecStart= prefix to spawn target user's shell; teach run0 about the new logic (#37071)
I've always been reluctant to invoke the current user's shell in another
user's context, hence was fully grounded in `sudo -i`. With this bit in
place `run0` will finally be feature-complete on my side ;-)
2025-05-12 16:10:03 +02:00
Yu WatanabeandMike Yuan 6156bec7a4 core: disable mounting disconnected private tmpfs on /var/tmp/ when DefaultDependencies=no
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>
2025-05-11 03:33:02 +09:00
Mike Yuan 5b8bcbcf00 core: accept "|" ExecStart= prefix to spawn target user's shell
When switching to another user it's oftentimes desirable to also spawn
the target user's shell. sudo supports this via -i flag, run0 currently
doesn't. We don't want to proactively query NSS ourselves, since
that would fall short when operating remotely. Let's instead teach
the service manager to spawn the command using the user's default shell.

I opted for "|" instead of "." in the end because the latter seems
a bit obscure. But happy to change it to something else if a better option
comes up.
2025-05-07 18:32:19 +02:00
Daan De Meyer fda652117e fs-util: Reduce transitive includes 2025-05-07 22:04:46 +09:00
Daan De Meyer 44d50ba88e execute: Get rid of custom logging macros
We already have LOG_CONTEXT_PUSH_EXEC() which with two additions
does exactly the same as the custom logging macros, so let's get rid
of the custom logging macros and use LOG_CONTEXT_PUSH_EXEC() instead.
2025-04-23 14:48:45 +02:00
Daan De Meyer 4ea4abb651 core: Remove circular dependencies between headers
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.
2025-04-23 10:33:35 +02:00
Daan De Meyer 8aa304d313 shared: Remove circular dependency between image-policy.h and dissect-image.h
ImagePolicy can just be a forward declaration in dissect-image.h.
2025-04-23 09:53:43 +02:00
Mike Yuan 418082596c namespace-util: generalize namespace_type_supported() 2025-04-21 16:54:37 +02:00
Stefan Hansson b1236ce38b missing_fcntl: Introduce O_ACCMODE_STRICT
On musl, O_ACCMODE is defined as (03|O_SEARCH), unlike glibc which
defines it as (O_RDONLY|O_WRONLY|O_RDWR). Additionally, O_SEARCH is
simply defined as O_PATH.

This causes problems for systemd on musl, as it changes the
behaviour of open_mkdir_at_full() to return -EINVAL if O_PATH is
included in flags due to the fact that O_ACCMODE includes O_SEARCH
(i.e. O_PATH). Consequently, this makes the test-fs-util test fail.

Upstream musl seems content with this behaviour and doesn't seem
interested in matching glibc's behaviour due to that defining it this
way allows for O_SEARCH to match POSIX better by allowing it to open
directories where read permission is missing. Apparently musl does some
emulation in other places to make this work more consistently as well.

Initially I took the approach of working around this by redefining
O_SEARCH as O_RDONLY if O_SEARCH == O_PATH. This fixes the test and is
the approach taken by both XZ[1] and Gzip[2][3], but was not taken as
redefining system headers potentially could be problematic.

Instead, introduce O_ACCMODE_STRICT which just is a copy of glibc's
O_ACCMODE and use it everywhere. This way we don't have to deal with
unusual definitions of O_ACCMODE from C standard libraries other than
glibc.

 [1]: https://git.tukaani.org/?p=xz.git;a=blob;f=src/xz/file_io.c;h=8c83269b13fa31284f7ea5f3627a1dfbce7d6e14;hb=HEAD#l72
 [2]: https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/fcntl.in.h
      (lines 380 and 396, commit d7f551b30f3f2a0fa57c1b10c12f4eea41a9b89e)
 [3]: https://lists.gnu.org/archive/html/bug-gzip/2025-01/msg00000.html
2025-04-18 05:22:06 +09:00
Yu Watanabe 188286eec6 cgroup-setup: drop unnecessary controller argument
This also removes unnecessary cg_{create,attach,trim}_everywhere(),
and rename cg_enable_everywhere() -> cg_enable().
2025-04-16 03:56:04 +09:00
Yu Watanabe 3988e2489a core: drop several more cgroup version check 2025-04-16 03:56:04 +09:00
Mike Yuan 9c0d8b8c4f core/exec-invoke: consult NSS for root user creds if SetLoginEnvironment=/PAMName= 2025-04-09 19:31:58 +02:00
Mike Yuan 2fb438cc88 core/exec-invoke: never override acquired user cred with fallback one 2025-04-09 19:30:17 +02:00
Daan De Meyer ad04dc4116 exec-invoke: Fix two log messages 2025-04-09 16:21:03 +02:00
Daan De Meyer 2b0087e5b1 exec-invoke: Always go via stdin fd in setup_pam() to get tty
We might have resolved the tty to something else if it was set to
/dev/console, so let's always go via stdin in setup_pam(). This also
means we won't set the pam tty if only stdout or stderr are connected
to a tty, which seems like a sensible thing to do.
2025-04-04 17:13:16 +02:00
Daan De Meyer 6f1d594d63 core: Resolve /dev/console if it's connected to stdin
If /dev/console is connected to stdin there's a possibility that
the unit might try to start a logind session from within the unit.
Let's make sure that any such sessions are started on the tty that
/dev/console points to and not on /dev/console itself.
2025-04-04 17:13:14 +02:00
Mike Yuan 32b69b190b core: delegate mountns implicitly when any of pidns/cgns/netns is in use 2025-03-30 18:57:18 +02:00
Mike Yuan 2b4cfbf91f core/execute: drop unused function param and cg unified check for cgns
While at it, remove TODO about assuming availability of cgns.
We generally want to keep that optional still.
2025-03-30 18:54:34 +02:00
Luca Boccassi 5aee5bda1a tree-wide: introduce LOG_ITEM() macro for verifying format string (#36780)
This introduce `LOG_ITEM()` macro that checks format strings in
log_struct() and friends.

Hopefully, this silences false-positive warnings by Coverity.
2025-03-24 12:58:14 +00:00
Daan De Meyer 38748596f0 core: Make DelegateNamespaces= work for user managers with CAP_SYS_ADMIN
Currently DelegateNamespaces= only works for services spawned by the
system manager. User managers will always unshare the user namespace
first even if they're running with CAP_SYS_ADMIN.

Let's add support for DelegateNamespaces= for user managers if they're
running with CAP_SYS_ADMIN. By default, we'll still delegate all namespaces
for user managers, but this can now be overridden by explicitly passing
DelegateNamespaces=.

If a user manager is running without CAP_SYS_ADMIN, the user manager is
still always unshared first just like before.
2025-03-19 10:01:19 +01:00
Daan De Meyer 918a188fda core: Also check if we can mount /proc if pid namespace is delegated
If the pid namespace is delegated, it doesn't matter if we have CAP_SYS_ADMIN,
we'll still fail to mount /proc if part of it is masked on the host so also
check if we can mount /proc if the pid namespace is delegated.
2025-03-19 10:00:45 +01:00
Daan De Meyer af6a8b6969 exec-invoke: Rename various variables from has_ to have_
All of these encode information of the current process, so have_ is
more approriate than has_, which refers to something else.
2025-03-19 10:00:45 +01:00
Yu Watanabe 3cf6a3a3d4 tree-wide: check more log message format in log_struct() and friends
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.
2025-03-19 01:56:48 +09:00
Lennart Poettering 728dbaeffb exec: when we have no $TERM configuration, and we default to vt220, also set $COLORTERM
When we configure a serial or VM terminal and have no $TERM
configuration, then we default to vt220 as a fallback. This is a pretty
safe bet, since the termcap/terminfo definitions for vt220 are
relatively widely available (much like vt100), and (in contrast to
vt100) it supports pageup/pagedown keys. vt220 is a terminal without
color support however, but we do want color support, because in 2025
there's really no terminal emulator without color in this world.

The $COLORTERM env var is used my many emulators and tools to
communicate that ANSI color support is available, despite what $TERM
says. Hence, let's tweak systemd's logic to also set $COLORTERM in case
we set the vt220 $TERM fallback.

This means we define an ahistoric frankenterminal: a vt220 (that
historically definitely didn't have color) that is explicitly configured
to have color.

One effect of this is that coreutils' dircolors command will start to
output color sequences in systemd's serial or VM terminals. (Since it
actually honours $COLORTERM).

Also note that systemd itself checks $COLORTERM since a long time, hence
it makes sense for us to also set it.

Note that this unfortunately doesn't have the desired effect of
propagating $COLORTERM into any getty shell sessions yet. That's because
util-linux' login package currently fiters $COLORTERM (but lets $TERM
though). I filed a bug about that here:

https://github.com/util-linux/util-linux/issues/3463
2025-03-17 10:15:51 +01:00