Commit Graph
310 Commits
Author SHA1 Message Date
Daan De Meyer 74d392ed1b tree-wide: standardize header names across src/fundamental, src/basic and src/shared
Drop the -fundamental suffix from src/fundamental/ headers in favor of names
that match their src/basic/ or src/shared/ counterparts (e.g.
macro-fundamental.h -> macro.h, assert-fundamental.h -> assert-util.h,
cleanup-fundamental.h -> cleanup-util.h). Rename src/basic/{btrfs,label}.{c,h}
to use the -util suffix to match the existing shared/btrfs-util and
shared/label-util siblings. Rename src/shared/mkdir-label.{c,h} to mkdir.{c,h}
and src/shared/tmpfile-util-label.{c,h} to tmpfile-util.{c,h} to match the
corresponding src/basic names.

This saves us from having to come up with separate names for files that do
the same thing across tiers, and it makes it easier to move stuff between
src/fundamental, src/basic and src/shared: consumers just #include "foo.h"
and pick up whichever tier their -I path resolves to first, so call sites
don't need to be updated when an API moves between layers.

Where a higher-tier wrapper exists (e.g. src/basic/macro.h wrapping
src/fundamental/macro.h), the wrapper uses an explicit "../fundamental/foo.h"
or "../basic/foo.h" relative include for the lower-tier header. We can't use
GCC's #include_next directive for this — when the wrapper is reachable both
via same-dir-as-source lookup and via -I (e.g. -Isrc/shared) for the
directory it lives in, #include_next advances by exactly one slot in libcpp's
internal directory chain and lands on the same physical directory it was
already in, never reaching the lower-tier sibling (see make_cpp_dir() in
gcc/libcpp/files.cc:1986).

To make sure the right headers are always picked up, the include directories
are reordered so that e.g. src/shared always takes priority over src/basic and
similar for the other directories.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 10:33:03 +09:00
Daan De Meyer 7d822ca8af bpf-util: rename from bpf-dlopen, unify version-specific symbol handling
Renames src/shared/bpf-dlopen.{c,h} to src/shared/bpf-util.{c,h} and
folds the former src/shared/bpf-compat.h (struct forward decl and
compat_bpf_map_create() helper) into the new header.

Aligns dlopen_bpf() with the standard wrapper pattern: drops the
manual dlopen_safe()/dlsym_many_or_warn()/TAKE_PTR(dl) plumbing and
the bespoke 'cached' int in favor of dlopen_many_sym_or_warn() inside
a FOREACH_STRING() soname-fallback loop.

Unifies declaration of the version-specific symbols (bpf_create_map,
bpf_map_create, bpf_object__next_map, bpf_token_create) into a single
DISABLE_WARNING_REDUNDANT_DECLS block in the header, and alphabetically
merges the DLSYM_PROTOTYPE list. DLSYM_OPTIONAL is used to load each
one — call sites already handle NULL (compat_bpf_map_create() and the
sym_bpf_object__next_map guard in userns-restrict.c). bpf_token_create
additionally defaults to a missing_bpf_token_create() stub returning
-ENOSYS, so callers can branch on the errno instead of NULL-checking
the pointer.

Updates test-bpf-token to match: drops the compile-time
LIBBPF_MAJOR_VERSION ≥ 1.5 gate and the direct <bpf/bpf.h> include in
favor of dlopen_bpf() + sym_bpf_token_create(), and treats -ENOSYS as
the test-skip path (covering both 'libbpf too old' and 'kernel lacks
BPF_TOKEN_CREATE support').
2026-05-18 21:17:38 +00:00
Lennart Poettering 37c272228d core: ensure all types from execute.h start with Exec
Until very recently all types defined by execute.h started with "Exec"
in the name. I think that was useful, since it made clear that the types
are associated with the ExecContext infrastructure. Let's hence restore
this.

(If we every move these types out of execute.h we should drop the "Exec"
prefix again. But today is not that day.)

No real code changes, just dumb renaming.
2026-04-28 12:37:21 +01:00
Christian Brauner 35a5e10e85 Merge branch 'main' into inode-ref 2026-04-23 19:10:15 +02:00
Daan De Meyer d49f3f287a dlopen: take log_level argument and log in fallback stubs
Every dlopen_xxx() helper now takes an int log_level argument. It is
passed through to dlopen_many_sym_or_warn() (which in turn propagates it
to dlopen_verbose() for the library-not-installed case), and is used by
the fallback stub when support for the library is not compiled in to
emit a "<lib> support is not compiled in." message at the caller's level.
Callers pass LOG_DEBUG when gracefully degrading, or a higher level when
the failure should surface, and no longer need to log redundantly at the
call site.

As part of this, dlopen_bpf_full() (which already took a log_level) is
merged into dlopen_bpf() rather than keeping both.

The static inline fallbacks used to live in the headers, which required
pulling log.h in from every header that declared a dlopen_xxx(). Move
them into the .c files instead: the declaration is always outside the
#if HAVE_XXX block, the impl sits outside the outer #if HAVE_XXX wrap
with its own internal #if HAVE_XXX/#else/#endif, and apparmor-util.c,
idn-util.c, libmount-util.c and pam-util.c are now always compiled so
they can host their stubs.
2026-04-22 17:41:42 +02:00
Daan De Meyer 79862d33a0 chase: add explicit root_fd parameter to chaseat() and drop CHASE_AT_RESOLVE_IN_ROOT
Split the single directory fd that chaseat() used to take into two separate
fds: a root_fd that sets the chroot boundary (symlinks may not escape it,
absolute symlinks resolve relative to it), and a dir_fd that path resolution
starts from. This makes the chroot semantics of chaseat() explicit at every
call site instead of encoding them in the CHASE_AT_RESOLVE_IN_ROOT flag,
which is removed. It also decouples the starting directory from the root
boundary, so callers can descend from any inode inside the tree without
having to reopen the root separately.

XAT_FDROOT passed as root_fd means "no containment" (host root); as dir_fd
it means "start at root_fd". For a smoother transition, AT_FDCWD is also
accepted as root_fd and treated as XAT_FDROOT. When root_fd points to a
directory that is actually the host root, it is normalized to XAT_FDROOT
up front so the existing shortcut path can kick in.

Absolute paths returned by chaseat() are now relative to root_fd, and
relative paths are relative to dir_fd. The result is absolute only when
there is no chroot boundary (root_fd is XAT_FDROOT), or when an absolute
symlink made resolution jump out of the dir_fd subtree; otherwise callers
get a relative path they can feed straight back into an openat()-style
call against dir_fd. Specifically, when dir_fd == root_fd and we're not
operating on the host's root directory, we return a relative path even if
we received an absolute path or resolved an absolute symlink to allow
passing the path directly to openat() style functions. We do this to not
have to go modify every caller of chaseat() to make sure they deal properly
with any absolute paths they might receive. Only when root_fd != dir_fd do
we have to return an absolute path to indicate that the path is relative to
root_fd and not dir_fd.

The shortcut that skips the per-component walk is reworked around a new
chase_xopenat() helper that funnels CHASE_NOFOLLOW, CHASE_MUST_BE_* and
CHASE_TRIGGER_AUTOFS through xopenat_full()'s O_NOFOLLOW, O_DIRECTORY,
XO_REGULAR, XO_SOCKET and XO_TRIGGER_AUTOMOUNT flags. As a result these
flags no longer force us off the shortcut and can be dropped from
CHASE_NO_SHORTCUT_MASK, and the old openat_opath_with_automount() helper
goes away. A CHASE_MUST_BE_ANY alias is introduced for shortcut callers
(stat/access paths) that don't go through xopenat_full() and still need
to bail on those flags locally.

All *_and_* helpers built on top of chaseat() (chase_and_openat,
chase_and_opendirat, chase_and_statat, chase_and_accessat,
chase_and_fopenat_unlocked, chase_and_unlinkat, chase_and_open_parent_at)
gain the same root_fd parameter, and every call site in the tree is
ported to the new signature.

chase_and_open() is also fixed to correctly handle CHASE_EXTRACT_FILENAME
without CHASE_PARENT.
2026-04-20 23:35:31 +02:00
Zbigniew Jędrzejewski-Szmek 5cd61c1330 Define array cleanup funcs through macros (#41559) 2026-04-10 21:45:14 +02:00
Zbigniew Jędrzejewski-Szmek 79f90f4ae0 various: use DEFINE_ARRAY_FREE_FUNC 2026-04-10 15:08:03 +02:00
Daan De Meyer 316d17fcbd core: Add support for CPU pressure notifications
Works the same way as memory pressure notifications. Code is refactored
to work on enum arrays to reduce duplication.
2026-04-09 22:47:10 +02:00
Daan De Meyer b3bb4fefde test-mempress: Support unprivileged operation 2026-04-09 22:47:10 +02:00
Mike Yuan eb8df25a37 core/exec-invoke: make fd array sizing less error-prone
History has clearly shown that we're terrible at keeping
the size of the dont_close array up-to-date. Hence let's
step away from a hardcoded max size for that, instead
always collect all fds in the array initializer and
let compiler figure it out, taking advantage of the fact
that close_all_fds() gracefully handles invalid fds in
the 'except' array.
2026-03-01 13:55:39 +01:00
Mike Yuan f2e7ba1074 core/exec-invoke: drop duplicate addition of handoff_timestamp_fd to dont_close array
Follow-up for 12001b1bf0

It is part of the keep_fds array already, which is intended
for fds that need to survive until the very end of executor
runtime, i.e. across the second close_all_fds() call.
2026-03-01 13:55:39 +01:00
Mike Yuan 0aa70bef5e core/exec-invoke: correct size for dont_close array in close_remaining_fds()
Follow-up for 79dd24cf14
2026-03-01 13:55:39 +01:00
Mike Yuan ec93edc4ca core/exec-invoke: fix potential double close of socket/bpffs fds on failure
The owned fds should be closed before close_all_fds() along the lines
of exec_params/runtime_close(), otherwise they would be left dangling
afterwards.
2026-03-01 13:55:39 +01:00
Zbigniew Jędrzejewski-Szmek fa33eef344 core: upgrade /tmp when PrivateTmp=yes/DefaultDeps=no to disconnected
In https://github.com/systemd/systemd/issues/28515, multiple people report that
services that have PrivateTmp=yes and DefaultDependencies=no fail to create the
temporary directories under /tmp, when /tmp is e.g. a bind mount or some other
kind of mount that takes more time.

Before PrivateTmp=disconnected was added, we didn't have a nice solution:
DefaultDependencies=no is used to start services very early, so we wouldn't
want to add a dependency on /tmp automatically. With PrivateTmp=disconnected we
have a fairly nice solution. Let's "upgrade" to this mode automatically.
Strictly speaking, it is a small compat break, but in practice it's unlikely to
matter for early-boot services whether their /tmp is private or disconnected.

The dependency on /tmp that is checked is After. I think this is enough,
since any tmp.mount would be pulled in by local-fs.target and the rest of
the transaction anyway, so we don't need to check more than After.

The asserts are relaxed, because now the two settings can now diverge
in either way.

Resolves https://github.com/systemd/systemd/issues/28515.

[yhndnzj: fix unit_add_exec_dependencies() to handle the new
          combination; add a comment in exec_needs_sys_admin()]
2026-02-25 12:38:11 +01:00
Mike Yuan 9984a35d65 core/execute: stop looking at ExecSharedRuntime to determine PrivateTmp= state
The only reason why ExecSharedRuntime.(var_)tmp_dir might
be suppressed is when (/var)/tmp/ is listed in InaccessiblePaths=,
in which case mount namespace is needed anyways. Moreover,
the current logic imposes a chicken-and-egg problem:
at various places in pid1 we'd need to check whether
the unit runs in a mountns, but the ExecSharedRuntime
may not be allocated for it just yet.
2026-02-25 12:38:11 +01:00
Zbigniew Jędrzejewski-Szmek 92a0761d55 core/exec-invoke: add missing char in comment 2026-02-25 12:36:44 +01:00
Lennart Poettering e93fd71094 core: introduce PinnedResource
This introduces PinnedResources as a structure combining pinned
references to a root directory, root image, or root mstack. This is not
only easier to work with, but essential to make certain unpriv things
work, as we need some mechanism to pin resources before we drop into a
userns which might possibly not provide access anymore to those
resources.

Hence this does two things: introduce the new structure, and immediately
hook it up so that we pin things properly before dropping into userns,
and then makes use of this after dropping the right way, and enables
unpriv userns operation.

The concept is generic enough to eventually implement extension images +
mount images with the same structure, but in order to keep the changes
managable this is left for another time.

(This also makes one further clean-up: client-side verity-reuse checks
are moved server side if we are unpriv. Previously we'd do them client
side, but they were doomed to fail because of lack of privs. Hence let's
drop the client side if we are unpriv and purely do them server-side in
that case.)
2026-02-19 15:08:20 +01:00
Lennart Poettering 68ed4f3c66 mountfsd,nsresource: allow recycling mountfsd/nsresourced client connections
So far we opened a new Varlink connection for every mountfsd/nsresourced
method call. Given each tool only does a very small number of calls
(usually 1…5) on them and the connections are cheap this is not too
wasteful. Nonetheless, let's do something about it, and allow reusing
the connection for multiple calls.

This not only makes things a bit more efficient, but has one more
important benefit: Varlink connections pin the security context of the
client when connecting. This means that varlink method calls done with a
connection established while some code was privileged will still operate
as privieged once privs are dropped, until the connection is closed.
This pinning effect is really nice, as it gives us behaviour in a
"capability system" like scheme. Later code is going to use that to
continue doing certain priv userns ops even after unsharing userns and
becoming fully unpriv.
2026-02-19 15:08:19 +01:00
Lennart Poettering 051dfed9b6 private 2026-02-19 15:07:18 +01:00
Lennart Poettering 6b22ac31af core: add PrivateUsers=managed 2026-02-19 15:05:15 +01:00
Lennart Poettering 087f2ec344 core: introduce exec_context_with_rootfs_strict() as a stricter version of exec_context_with_rootfs()
We have two very similar checks in place: in some contexts we want to
know if *any* RootDirectory= is configured, in the other we want to
suppress if it is configured to our regular root. Let's add a helper for
both (even if we only need it once), to make the mirrored behaviour
clear.
2026-02-19 15:05:15 +01:00
Mike Yuan bae58ceff7 core/exec-credential: only pass needed bits of ExecParameters down in exec_setup_credentials()
No functional change, preparation for credential reloading support,
where we'd operate on Unit rather than ExecParameters.
2026-02-10 21:54:11 +01:00
Lennart Poettering 8d55f319fb exec-invoke: remove one level of indentation 2026-01-25 20:29:05 +01:00
Lennart Poettering c28aeab184 exec-invoke: handle PRIVATE_USERS_SELF cases together
And moving things to a switch/case sttement.
2026-01-25 20:29:05 +01:00
Mike Yuan 24c73c7920 core/exec-invoke: switch PRIVATE_USERS_FULL to direct "0 0 UINT32_MAX" mapping
This was intended for v259. Let's get it done now, in v260.
2026-01-23 19:29:48 +01:00
Mike Yuan 6ed05d6414 core/exec-invoke: group setup_private_users*() together 2026-01-23 18:48:31 +01:00
Mike Yuan a91bb7459b core/exec-invoke: dedup error handling
Also, do not log about errno if it's suffciently encoded
in the log text already.
2026-01-18 16:42:22 +01:00
Daan De Meyer 3fa3a4fd15 vpick: Fix pick_filter_image_any
Currently, pick_filter_image_any matches any image
with any suffix, which is way more than it should
be doing. It should only be matching images with
the .raw suffix.

Let's address this shortcoming by allowing to pass
multiple filters to path_pick(), and define
pick_filter_image_any as the combination of the
raw and directory image filters.

Fixes #40083
2026-01-16 13:07:47 +01:00
Usama Arif 32614b9aab core: introduce MemoryTHP= unit file setting
Transparent Hugepages (THP) is a Linux kernel feature that manages
memory using larger pages (2MB on x86, compared to the default 4KB).
The main goal is to improve memory management efficiency and system
performance, especially for memory-intensive applications.
However, it can cause drawbacks in some scenarios, such as memory
regression and latency spikes. THP policy is governed for the entire
system via /sys/kernel/mm/transparent_hugepage/enabled.
However, it can be overridden for individual workloads via prctl(2)
call.
MemoryTHP= is used to disable THPs at exec-invoke to stop
providing THPs for workloads where the drawbacks outweigh the advantages.
When set to "disable", MemoryTHP= disables THPs completely for the
process, irrespecitive of global THP controls.
When set to "madvise", MemoryTHP= disables THPs for the process except
when specifically madvised by the process with MADV_HUGEPAGE or MADV_COLLAPSE.
2026-01-06 03:26:14 -08:00
Yu Watanabe 3a1231f4c7 core: several follow-ups (#40140)
Replaces #39925
Closes #39925
2026-01-05 06:31:48 +09:00
Daan De Meyer 52ecf376fa tree-wide: Migrate to pidref_safe_fork()
Let's migrate all remaining callers of safe_fork()
to pidref_safe_fork() and get rid of safe_fork().
2026-01-02 20:08:41 +01:00
Daan De Meyer 944ae1286b tree-wide: Use pamh as pam_handle_t parameter name
libpam uses pamh in its function declarations for
the plugin API so let's use the same name in our
tree as well.

Making sure the plugin function definitions match
the plugin function declarations is required to
enable clang-tidy's
readability-inconsistent-declaration-parameter-name
check, but to keep things consistent everywhere we
opt to use pamh tree-wide.
2026-01-02 09:21:43 +01:00
Yu Watanabe 431fc656bc Bump required minimum version of libseccomp to 2.4.0
Major distributions already have libseccomp 2.5.x or newer.
Let's bump to the required minimum version to 2.4.0, which provides
SCMP_ACT_KILL_PROCESS, SCMP_ACT_LOG, SCMP_ARCH_PARISC, and
SCMP_ARCH_PARISC64.

Note, libseccomp 2.4.0 was released on 2019-03-15.

See also #38608.
2026-01-02 12:54:18 +09:00
Mike Yuan d7bc1e3be9 core/exec-invoke: use RET_NERRNO to avoid clobbering errno
Follow-up for 72ce1046e8

string_table_lookup_to_string_fallback() might interfere
with errno, hence store it in r first.
2025-12-31 19:32:58 +01:00
Mike Yuan 72ce1046e8 core/exec-invoke: log about name of CPU sched policy
Follow-up for 4dcbfbb1ad

Also, do not encode errno in log if we know the precise cause,
i.e. unsupported.
2025-12-20 21:40:56 +01:00
Matt Fleming 4dcbfbb1ad process-util: Add support SCHED_EXT scheduling policy
Allow CPUSchedulingPolicy to be set to "ext". SCHED_EXT is a new
scheduling policy in Linux v6.12 that allows processes to be scheduled
using custom BPF schedulers instead of the default in-kernel ones.

Selectively setting the SCHED_EXT policy is useful for systems running
in "partial mode" where not all processes are run using a custom
scheduler.

Fallback to SCHED_OTHER and print an error message for systems where
SCHED_EXT isn't available.
2025-12-20 18:31:55 +01:00
Daan De Meyer fbd276cb86 tree-wide: Use pidref_wait_for_terminate_and_check()
Let's use the pidref variants for waiting and
checking a process everywhere and get rid of the
non pidref variants.
2025-12-20 15:50:47 +01:00
Mike Yuan 7498c391ec core/exec-invoke: remove redundant accmode validation on stderr
Follow-up for 171ceb4a00

In setup_output() we assume stdout has been set up properly
before stderr, hence the stdout we're inheriting from must
be writable (or more precisely, would have been adjusted to be).
Hence no need to duplicate it.
2025-12-17 23:23:22 +00:00
Mike Yuan a8e1796b09 core/exec-invoke: split out maybe_inherit_stdout_from_stdin(), use exec_input_is_inheritable()
Note that exec_input_is_inheritable() rightfully refuses EXEC_INPUT_FILE,
in which case std_output would have been reset in service_fix_stdio()
already.

While at it, use the generic fallback logic of first trying user manager
stdout when stdin is not writable.
2025-12-17 23:23:22 +00:00
Mike Yuan b34aee0440 core/exec-invoke: socket_fd must be set if any of stdio requests it
This is checked as one of the very first things in exec_invoke(),
hence remove the condition in fixup_input() and the whole
fixup_output().
2025-12-17 23:23:22 +00:00
Mike Yuan c8a6c42e53 core/exec-invoke: use path_equal() on for stdio files 2025-12-17 23:23:22 +00:00
Mike Yuan eac3867764 core/exec-invoke: fix stdout and stderr sharing the same named fd
Previously such usage would be refused by exec_context_named_iofds()
with -ENOENT, however setup_output() carried relevant logic.
2025-12-17 23:23:22 +00:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Lennart Poettering 81e79ee499 exec-invoke: fix type for gid 2025-12-02 13:34:05 +09:00
Daan De Meyer 9a6a8f35eb tree-wide: Small fixes for various clang-tidy warnings 2025-11-26 16:22:00 +09:00
Lennart Poettering efaf5a763d execute: load a bunch of libs before we disable dlopen() 2025-11-24 11:56:35 +01:00
Lennart Poettering 2c7bdaf9f1 dlfcn-util: let's make our dlopen() code fail if we enter a container namespace
Now that we dlopen() so many deps, it might happen by accident that we
end up dlopen()ening stuff when we entered a container, which we should
really avoid, to not mix host and container libraries.

Let's add a global variable we can set when we want to block dlopen() to
ever succeed. This is then checked primarily in
dlopen_many_sym_or_warn(), where we'll generate EPERM plus a log
message.

There are a couple of other places we invoke dlopen(), without going
through dlopen_many_sym_or_warn(). This adds the same check there.
2025-11-24 09:19:33 +01:00
Mike Yuan 32b7a07b8c core/exec-invoke: deduplicate needs_setuid with needs_sandboxing 2025-11-22 19:07:28 +01:00
Daan De Meyer 87fbd33372 clang-tidy: Fix all remaining misc-include-cleaner violations
- Remove unused includes
- Add common false positive headers to misc-include-cleaner.IgnoreHeaders
- Add IWYU pragma keep for uncommon false positive headers
2025-11-22 10:19:41 +01:00