Commit Graph
380 Commits
Author SHA1 Message Date
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
Michael Vogt bd141bd818 many: fix remaining check-pointer-deref issues
The updated parsing_hacks.h file uncovered a bunch of extra
things that the check-pointer-deref coccinelle script flags.

This commit fixes them to make the tree check-pointer-deref clean.
2026-04-12 15:27:15 +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
Frantisek Sumsal 44d0f273fa portablectl: fix swapped arguments for setns()
Follow-up for 824fcb95c9.
2026-04-09 20:43:42 +01:00
Zbigniew Jędrzejewski-Szmek 1008583c91 tree-wide: print error if table_print() fails
We generally want to print an error message if table_print()
fails. Add a helper function for this and use it consistently.
This does one of the three things depending on the call site:
- a no-change reformatting of the code
- change from a custom message to the generic one
- addition of the error message where previously none was printed

In the third case, the actual use impact is very small, since the
table formatting is very unlikely to fail. But if it did, we would
often return an error without any message whatsoever, which we
never want to do.
2026-04-03 13:05:03 +02:00
Zbigniew Jędrzejewski-Szmek 0ce5a8fb4e tree-wide: drop flush&check step after table printing
Almost all callers of table_print() specify stdout or NULL (equivalent
to stdout) as the output stream. Simplify things by not requiring the
the stream to be specified.

In almost all cases, the printing of the table is surrounded by normal
printfs() that don't do explicit flushing and for which we don't check
the output stream status. Let's simplify most callers and skip this
step. The reason is not so much to avoid the extra step itself, but
instead to avoid the _handling_ of the potential failure. We generally
only want to print an error message for ENOMEM and other "internal"
errors, so strictly speaking we should filter out the errors from the
stream. By skipping the flush&check step we implicitly do this.
2026-04-03 13:04:40 +02:00
Michael Vogt 777d9c10ad coccinelle: add checks for pointer access without NULL check
The fix in 8f1751a111 made me wonder if we could automatically detect
when pointers are accessed but when this might not be safe. Systemd
is already using a lot of `assert(dst)` and this change now forces
us to use them.

So this commit (ab)uses coccinelle to flag any pointer parameter
dereference not preceded by assert(param), ASSERT_PTR(param), or an
explicit NULL check. It adds integration into meson as a new "coccinelle"
test suite (just like clang-tidy) and is run in CI. The check is not
perfect but seems a reasonable heuristic.

For this RFC commit it is scoped to a subset, it excludes 25 dirs right
now and includes around 100. About 300 warnings left. Busywork that I am
happy to do if there is agreement that it is worth it.

With this in place we would have caught the bug from 8f1751a111 in CI:
```
FAIL: check-pointer-deref.cocci found issues in systemd/src/boot:
diff -u -p systemd/src/boot/measure.c /tmp/nothing/measure.c
--- systemd/src/boot/measure.c
+++ /tmp/nothing/measure.c
@@ -312,7 +312,6 @@ EFI_STATUS tpm_log_tagged_event(
         if (err != EFI_SUCCESS)
                 return err;

-        *ret_measured = true;
         return EFI_SUCCESS;
 }
```

This also adds a new POINTER_MAY_BE_NULL() for the cases when the
called function will do the NULL check (like `iovec_is_set()`).
2026-03-26 18:13:17 +01:00
Lennart Poettering 7876bd5cfc env-file: add parse_env_data() helper 2026-03-20 16:34:58 +01:00
Zbigniew Jędrzejewski-Szmek 31ddd87da0 tree-wide: extend verbs functions with extra per-verb data parameter
We often have a pattern where the same verb function is used for
multiple actions. This leads to an antipattern where we figure out what
action needs to be taken from argv[0] multiple times: often once in
parse_argv() to figure out what options are allowed, then once again
implicitly in dispatch_verb(), and then again in the action verb itself.
Let's allow passing a parameter into the verb to simplify this.

This matches a pattern we have in conf-parser.h, where we have both
void *userdata (more global) and void *data (per-config item). Here,
I opted for uintptr_t userdata. It seems that most of the time we'll
want to just pass an enum value. This works OK with no casts. I also
tried a void* and union. In both cases, much more boilerplate is needed:
either a cast or a macro to help avoid compiler warnings. uintptr_t
seems generic enough to cover foreseeable usecases with no fuss.

This is a noop refactoring. See next commit for an example.
2026-03-18 10:28:47 +00:00
Zbigniew Jędrzejewski-Szmek 89e3ed81b1 portablectl: call all verb functions verb_* 2026-03-18 10:28:47 +00:00
Luca Boccassi cbea0e34c4 portable: avoid passing through ID/version fields to LogExtraFields= when they contain control characters
Found by Claude Code Review.

Follow-up for e8114a4f86
2026-03-12 21:53:28 +00:00
Zbigniew Jędrzejewski-Szmek a22ad0efcc portable: Add ExtensionImages drop-in for any extension (#40911)
The diff seems big, but it's just removing and if and deleting the
indentation. With `git show -w` you can see clearly that is just one
line. In the files tab, in github, you can click "hide whitespaces" and
it is clear too.

I don't know if there is some better way, but when using a portable
service with an extension image that just overlays files I need to
manually add the `ExtensionImages=`. And that is added automatically for
other extension images that provide a service unit.

So, this patch just makes sure we add the `ExtensionImages=` for any
extension.

Any thoughts?

Below the commit msg for more details:

---

    Before this patch, when running:
    
            portablectl attach --extension ext.raw ./base.raw
    
No drop-in is added for the "ExtensionImages" if there aren't units from
    the extension loaded.
    
But the extension can just overlay files, as in my case. So before this
patch, I also need to manually add a drop-in with "ExtensionImages=" for
    it to really be loaded.
    
Let's just always add the drop-in for extensions. This way, it works for
    extensions that just overlay files too.
    
Please note this commit just removes the if (simpler to view the diff
    with git show -w). Also, the if checked for m->image_path being not
NULL, but removing it shouldn't cause a NULL pointer dereference.
Because
m->image_path is not used inside the if (it was needed just for the if
itself) and image_path is asserted at the beginning of the function to
    be non-NULL too.
    
    This was like this since the beginning of time in 907952bbc9
    ("portabled: add --extension parameter for layered images support")
2026-03-04 11:44:00 +01:00
Mike Yuan 085f92730a tree-wide: use ALPHANUMERICAL where appropriate
Prompted by 43116c5662
2026-03-04 07:36:10 +09:00
Rodrigo Campos 5a04e542c2 portable: Add ExtensionImage drop-in for any extension
Before this patch, when running:

	portablectl attach --extension ext.raw ./base.raw

No drop-in is added for the "ExtensionImages" if there aren't units from
the extension loaded.

But the extension can just overlay files, as in my case. So before this
patch, I also need to manually add a drop-in with "ExtensionImages=" for
it to really be loaded.

Let's just always add the drop-in for extensions. This way, it works for
extensions that just overlay files too.

Please note this commit just removes the if (simpler to view the diff
with git show -w). Also, the if checked for m->image_path being not
NULL, but removing it shouldn't cause a NULL pointer dereference.
Because m->image_path is not used inside the if (it was needed just for
the if itself) and image_path is asserted at the beginning of the
function to be non-NULL too.

This was like this since the beginning of time in 907952bbc9
("portabled: add --extension parameter for layered images support")
2026-03-03 09:38:28 +01:00
Yu Watanabe 4b4eba1666 tree-wide: use _contains() rather than _get()/_find() 2026-03-02 23:10:22 +09:00
Lennart Poettering 6ebaea6990 portable: fix log levels
portable_extract_by_path() and install_image() can't agree whether to be
of the "logging" or "non-logging" kind
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 38e65b6e4c portable: support .mstack images 2026-02-19 15:05:15 +01:00
Lennart Poettering 116394f7ce tree-wide: move logging from varlink clients in nsresource.c/dissect-image.c into callers
These calls are "library-like", hence better should only debug log on
their own, not more.
2026-02-19 15:05:15 +01:00
Daan De Meyer aca8ed4af1 portable: /run/systemd/portables => /run/portables 2026-02-13 11:40:11 +01:00
Luca Boccassi 03f6a8b9d9 portable: do not apply extension image policy if not attaching image
Image policy is only for images, so skip for other types

Follow-up for d059615492
2026-02-12 23:20:47 +00:00
Luca Boccassi d07aa23c87 portable: fix --force flag combination with directory extension
The check for image type uses the wrong variable, so it's applied
when it shouldn't.

Follow-up for 06768b90a3
2026-02-12 23:20:47 +00:00
Louis Stagg 23c6ab3971 portablectl: Strip .v or .raw.v when extracting prefix
This allows a plain "portablectl attach foobar.raw.v" without needing to
specify a prefix.
2026-02-05 23:12:18 +01:00
Daan De Meyer ae6dcaff0d portable: Don't refuse copying out instance of template that exists
There's no reason to refuse copying out capsule@abc.service even if
capsule@.service already exists on the host, so let's optionally not
search for templates if we can't find an instance when looking up
units and use it in portabled.
2026-02-03 15:03:51 +01:00
Daan De Meyer 824fcb95c9 portable: Enable unpriv operation
This does not yet support directory images properly
as systemd itself does not support unpriv directory
images properly yet.

The user profiles are a copy of the system profiles but without
DynamicUser=yes (can't be used by user managers) and without
ProtectHome=yes (this masks /home which breaks StateDirectory= which
is lcoated inside /home)
2026-01-21 15:09:46 +01:00
Daan De Meyer 1a239eae8e portable: Split out receive_portable_metadata() 2026-01-21 12:03:08 +01:00
Daan De Meyer e4058c584f portable: Make extract_now() operate on a dirfd
Preparation for making portabled support unpriv
operation.
2026-01-21 12:03:08 +01:00
Daan De Meyer 05f672c782 portable: Use report_errno_and_exit() 2026-01-21 12:03:08 +01:00
Luca Boccassi d059615492 portable: pin attached image via image-policy
When attaching images generate a policy in the portable drop-in
that matches the partition types and content found while dissecting,
so that it can no longer be changed later without a reattach.
2026-01-19 15:54:12 +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
Kai Lueke fd8a1deb0b sysext: Get verity user certs from given --root=
The verity user certs weren't looked up in the given --root= for
systemd-sysext which made it fail to set up extensions with a strict
image policy.
Look up verity user certs from inside the --root= when we operate on
images in it. The main use case where this matters is when the initrd
sets up the extensions for the final system and thus systemd-sysext
should do the same thing as it would do in the final system.
2026-01-05 06:53:50 +09:00
Daan De Meyer aec52c1e6e string-table: Introduce DECLARE_STRING_TABLE_LOOKUP() and friends
Let's introduce these for the following two reasons:
- Using them makes sure the parameter names match between declaration
  and definition (if both use the corresponding macros).
- They make sure developers can't forget the _const_ and _pure_
  attributes for the declarations.

This commit also includes some include sorting fixes
2026-01-02 04:05:45 +09:00
Daan De Meyer f9708c53aa Follow ups for #39806
We drop the optimization for verify_sigchld as the
check differs based on the options passed and the
extra syscalls are certainly not going to matter
compared to the cost of forking a child process.

Fixes #40166
2025-12-21 08:16:03 +01:00
Daan De Meyer 29d1df4b03 tree-wide: Remove unnecessary SIGCHLD blocking
Now that sd-event doesn't insist on blocking
SIGCHLD anymore when watching for process exit,
let's stop blocking SIGCHLD tree-wide where not
required anymore.
2025-12-20 15:50:47 +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
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Luca Boccassi 28c68dbea0 portabled: list new methods in D-Bus policy
Access to these methods is also managed via polkit,
but they were never added to the access list in the
D-Bus policy.

Follow-up for 907952bbc9
2025-12-09 12:00:59 +09:00
Daan De Meyer 6a9f0641cd tree-wide: Fix declaration/definition parameter name mismatches 2025-11-26 19:02:31 +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 c746488537 block dlopen() once we transition into some foreign namespace (#39824)
Let's make sure we never accidentally end up loading code from a foreign
namespace.
2025-11-24 14:14:16 +01:00
Yu Watanabe f866ff3df8 tree-wide: replace tab with space, adjust missing or duplicated space 2025-11-24 12:45:06 +01:00
Lennart Poettering e683dce1f1 portabled: load a bunch of libs before we fork off a dissector child processes 2025-11-24 11:56:47 +01:00
Yu Watanabe 7829c9cc48 discover-image: introduce bus_property_get_image_is_read_only() with BUS_DEFINE_PROPERTY_GET() macro
This also makes image_is_read_only() return bool.

Follow-up for ee327e086e.
2025-11-01 18:11:18 +09:00
Lennart Poettering ee327e086e discover-image: imply that hidden images are read-only
Marking a whole directory tree OS image as read-only is difficult
privilege-wise, because so far we rely on the FS_IMMUTABLE_FL which is
not accessible to unpriv clients.

One fundamental place where we currently rely on marking images
read-only is for keeping pristine copies of the originally downloaded
image around, which we place in "hidden" image directories. This is
probably the most relevant usecase for the read-only flag. And moreover,
the only usecase for the hidden images are these read-only pristine
copies.

Hence, let's make this work reasonably in the unpriv case, and simply
imply the read-only flag for hidden images. This is strictly speaking a
change in behaviour, but effectively it shouldn't be, because for nspawn
containers that are executed we insist on names that are hostname
compatible, and hidden names aren't (because they start with a dot).
2025-10-24 17:51:00 +02:00
Daan De Meyer b8ee7c2206 tree-wide: Various forward header cleanups
- Make sure forward headers have the iwyu pragma to always keep them
- Make sure we always include the daemon specific forward header
  instead of shared-forward.h
- Remove shared-forward.h include where the daemon specific forward
  header is already included
2025-10-17 21:11:23 +09:00
Daan De Meyer f102bc3e5f tree-wide: Introduce sd-forward.h and shared-forward.h headers
Let's not leak details from src/shared and src/libsystemd into
src/basic, even though you can't actually do anything useful with
just forward declarations from src/shared.

The sd-forward.h header is put in src/libsystemd/sd-common as we
don't have a directory for shared internal headers for libsystemd
yet.

Let's also rename forward.h to basic-forward.h to keep things
self-explanatory.
2025-10-16 17:00:29 +02:00
Lennart Poettering 83b6ef9b62 libselinux: turn into dlopen() dep 2025-09-26 11:12:04 +02:00