Commit Graph
1124 Commits
Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 68e1f67b36 Another batch of conversions to COMMAND structures and additions of --introspect-cli (#43503)
This time, various commands with non-trivial requirements are handled.
So the series is shorter, but has a pattern of feature additions and
then those new features being used. The way that --help output is
formatted is changed a bit in various places. Those changes are
described in individual commits.

22 'static int help()' functions left after this.
2026-08-25 11:04:22 +02:00
Nick Rosbrook 0420097525 varlink: introduce io.systemd.service.GetLogLevel
We already have io.systemd.service.SetLogLevel. Add a getter so that
CLI tools with `log-level` subcommands can be more easily implemented
with varlink.

Bind this method to all services that already bind io.systemd.service.SetLogLevel.
2026-08-24 11:54:44 -04:00
Zbigniew Jędrzejewski-Szmek 1cf40c9c72 shared/verbs: stop requiring an explicit program name
Almost all programs are simple and have only a single command. When
printing options, let's just use the first COMMAND block found by default.
This means we can drop the explicit program-name argument and reduce
copy&paste boilerplate.
2026-08-24 13:45:07 +02:00
Zbigniew Jędrzejewski-Szmek facaf8ba45 machinectl: convert to VERB_COMMAND and add --introspect-cli
The custom help() is replaced by a COMMAND() description, and
--introspect-cli is added. The abstract is now wrapped automatically.
2026-08-18 16:54:09 +02:00
dongshengyuan 8a5c8b751b machined: refresh resolve hook addresses per machine
Track which machine the cached address list belongs to and refresh it
when ResolveRecord() advances to another machine. This keeps A/AAAA
reuse for the same machine while avoiding mixed name/address records.

Reproducer: register two machines with private addresses 10.88.1.1
and 10.88.2.1, then call io.systemd.Resolve.Hook.ResolveRecord
with both A questions in one request.

Before: the answer for the second machine used its own name but
reused the first machine's address, e.g. resolve-bug-m2 returned
10.88.1.1 instead of 10.88.2.1.

Follow-up: 3cd929f837
2026-07-23 13:19:11 +09:00
cidkidnix 93212e2910 machined: Allow user ids in open_shell for machine-dbus
Previously "machinectl shell --uid=1000 <container>" resulted in a
sucessful drop into a shell in the respective target machine. After
commit a9e9288288 this is no longer the
case.

This fixes the above breaking change brought in commit a9e9288288
2026-07-16 11:58:15 +01:00
Daan De Meyer 5a12005c83 copy: drop COPY_REFLINK
Reflinking is a safe optimization whenever the source and destination are
regular, seekable files on a filesystem that supports cloning. Requiring each
caller to opt in through COPY_REFLINK adds flag plumbing without changing the
necessary fallback behavior.

Drop COPY_REFLINK, renumber the remaining flags, and have copy_bytes_full()
unconditionally try FICLONE or FICLONERANGE before entering its normal copy
loop. Isolate the clone attempt and its file-offset bookkeeping in a helper so
copy_bytes_full() only has to handle its cloned, unavailable, and error results.
A successful clone therefore completes in one operation, while an unsupported
or rejected clone falls back to progress-limited copy_file_range(), sendfile(),
or buffered copying. Keep the public reflink helpers for operations that
specifically require clone semantics.

Existing test-copy coverage exercises both bounded and unbounded regular-file
copies through copy_bytes_full().

Signed-off-by: Daan De Meyer <daan@amutable.com>
2026-07-15 12:12:40 +02:00
Yu Watanabe 01e1303f9c Rename basic-forward.h, sd-forward.h, and shared-forward.h to forward.h
Follow-up for 74d392ed1b.
2026-07-15 02:18:05 +09:00
Lennart Poettering 33b2db3c8f machined: set user.userdb.* xattrs on machined socket 2026-07-12 23:09:01 +02:00
Yu Watanabe 05bdf4bfa9 compress: split compress_blob() and friends to minimize dlopen dependencies
Previously, even though sd-journal does not support bzip2 and gzip
compression, the dlopen ELF notes for those libraries were still being
attached to libsystemd.so and various journal-handling executables.
This occurred because the unified compression/decompression interfaces
handled all formats unconditionally, causing the compiler and linker to
pull in all associated dlopen notes across the board.

To resolve this, split these functions into generic and journal-specific
variants (e.g., introducing compress_blob_journal() and decompress_blob_journal()).
The journal-specific variants only handle formats actually supported by
the journal (LZ4, XZ, and ZSTD).

By updating sd-journal, journald, journalctl, and related utilities to
use these new `_journal` interfaces and switching them to the narrower
COMPRESS_JOURNAL_NOTE macro, we ensure that unnecessary dlopen notes
(for bzip2 and gzip) are no longer embedded into these binaries.
2026-07-10 16:35:19 +09:00
Yu Watanabe 4c0d8d9673 tree-wide: embed dlopen notes into individual executables
Previously, when a library was dynamically loaded via a helper function
inside libsystemd-shared.so, the resulting dlopen ELF note was not
propagated to the invoking executable's ELF metadata.

This commit explicitly annotates each executable with the relevant
dlopen ELF notes for any optional dependencies it might potentially
load. This ensures that package managers and build systems can properly
discover runtime dependencies that are triggered indirectly.
2026-07-10 16:35:19 +09:00
Zbigniew Jędrzejewski-Szmek aad1e61010 meson: adjust naming of '*extract*' variables 2026-07-07 13:40:13 +02:00
Zbigniew Jędrzejewski-Szmek f00ccf93b7 meson: rename extract+objects to export+import
We have two concepts: a list of files that should be extracted from an
intermediate build artifact to be used in a later build artifact, and for a
given artifact, a list "donors". The first list was called "extract", because
it is passed to the .extract_objects() meson function, and the second was
called "objects", because that is the meson parameter to specify pre-built
objects files (6350d2dbd9). But this naming is
confusing: we don't care about the 'extract' step, this is something internal
to the build machinery. And 'objects' is a very generic term.

Let's use 'export' for the stuff that is "exported" for other binaries to use,
and 'import' to say where to import from. Those terms are symmetrical and the
association between them should be intuitive. (If you think the terms are
actually assymetrical, there are precedents for confusing the import with the
import sources. E.g. in modern English, turkeys are called so because they were
imported from the Americas and guineafowls were imported from Africa via
Türkiye and all that foreign stuff is alike.)
2026-07-07 13:40:13 +02:00
Luca Boccassi b7769aa34e machined: drop superfluos 'supervisor' varlink input parameter for register method
The supervisor is derived from the caller's socket in D-Bus, and it is
not an input parameter. Do the same in varlink.

Follow-up for 97754cd14d
2026-07-03 10:07:05 +02:00
Luca Boccassi 6815a48f08 machined: allow privileged users to register other users machines
If a user is authenticated by polkit as admin then it should be
able to manage any resource on the system.

Follow-up for 119d332d9c
2026-06-25 10:39:11 +01:00
Luca Boccassi 5ce1786227 polkit: check if user authenticated as admin
The new polkit will return a new detail regarding a successful
authentication: the actual result type, which we can use to
see whether the user authenticated as admin. This can be used
to grant additional privileges.
2026-06-25 10:39:11 +01:00
Chitoku 85afe8e82d vsock-util: allow VMADDR_CID_ANY as local CID if enabled in hwdb
On Hyper-V guests, `VMADDR_CID_ANY` is valid as per implementation in
kernel driver: net/vmw_vsock/hyperv_transport.c.

Fixes https://github.com/systemd/systemd/issues/42496

Follow-up for 83359c4da0
2026-06-13 15:54:50 +02:00
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 a14adac423 meson: drop libdl, threads, and librt dependencies
Our baseline glibc is 2.34, which merged libdl, libpthread (the
dependency('threads') target), and librt into libc. Empty .so/.a stubs
remain for backward compatibility with old binaries, but new builds
resolve dl_*, pthread_*, mq_*, timer_*, etc. directly from libc.
On musl the same libraries are likewise empty stubs.

Drop the libdl, threads, and librt entries from every meson.build, and
remove the now-stale 'Libs.private: -lrt -pthread' from libudev.pc.in
since both flags resolve to empty link-time stubs on glibc 2.34+ and
musl.

Verified with readelf -d that libsystemd.so, libudev.so, and systemd no
longer carry DT_NEEDED entries for libdl/libpthread/librt.
2026-05-18 21:17:38 +00:00
Zbigniew Jędrzejewski-Szmek 39a3647539 tree-wide: get rid of old dispatch_verb
Also rename dispatch_verb_with_args to dispatch_verb.
2026-05-16 18:37:10 +02:00
Zbigniew Jędrzejewski-Szmek 3b37439afb machinectl: convert to OPTION and VERB macros
For the shell verb we want switches specified after the program name to
be passed to the program to execute, not processed by us. Mirror the
approach in 'userdbctl ssh-authorized-keys': start with
OPTION_PARSER_RETURN_POSITIONAL_ARGS, then lates switch to
STOP_AT_FIRST_NONOPTION for "shell" or NORMAL otherwise.

VERB declarations are placed directly above each function; functions
that dispatch multiple verb names get stacked VERB() declarations.
chainload_importctl() now takes the args strv instead of relying on the
global optind.

--help output is mostly the same.
--no-pager/--no-legend/--no-ask-password/-q/--quiet are now at the end.
bind-volume/unbind-volume are documented.

Fixes c9f461a806.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:59:15 +02:00
Zbigniew Jędrzejewski-Szmek 6b8c3af359 machinectl: reorder cases in parse_argv() to match order in --help
--no-pager, --no-legend, --no-ask-password, --quiet are shifted to
the end.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 21:49:05 +02:00
Zbigniew Jędrzejewski-Szmek 3f96c89a52 machinectl: reorder verb functions to match --help
The net diff is negative because some spurious whitespace and forward
declarations were dropped. One new forward declaration was added. (For
verb_poweroff_machine. The func could be moved, but I think it's better
to keep it adjacent to verb_reboot_machine which is very similar.)
2026-05-15 21:49:05 +02:00
Frantisek Sumsal 480449db85 machine: require normalized paths in Copy* D-Bus/Varlink methods
Also, do the same for the Varlink BindMount method, since its D-Bus
counterpart already does it.
2026-05-08 17:20:37 +02:00
Christian Brauner c9f461a806 machinectl: add bind-volume / unbind-volume verbs
machinectl bind-volume MACHINE PROVIDER:VOLUME[:CONFIG][:K=V,...]
  machinectl unbind-volume MACHINE PROVIDER:VOLUME

For bind-volume, machinectl parses the SPEC with the shared
bind_volume_parse(), Acquires the storage volume from the named
provider on the machinectl side, locates the target machine's
io.systemd.MachineInstance control socket via
machine_get_control_address(), pushes the fd across, and calls
io.systemd.MachineInstance.AddStorage with name='<provider>:<volume>'
and the user-supplied config string.

For unbind-volume, machinectl just forwards the name string to
io.systemd.MachineInstance.RemoveStorage.

Volumes attached at machine startup (e.g. via systemd-vmspawn's
--bind-volume=) are rejected with StorageImmutable when the user
attempts to unbind them at runtime.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-06 10:30:17 +02:00
Frantisek Sumsal 49c1e1bcf2 dbus: limit the number of env variables to something reasonable, vol. 2
Turns out we can utilize this limit at a couple more places, so let's
move the previously defined limit constant to env-util.h and use it to
guard a couple more D-Bus methods. Also, bump it a bit, given it's meant
to be a safety cap that can't be hit in valid scenarios.

Follow-up for 7671b43cb8.
2026-05-01 20:11:53 +02:00
Kai Lüke 70d75c22d7 machine-register: don't unref borrowed varlink reply
ASAN showed a use-after-free error for systemd-vmspawn's
machine_register call because the reply got accessed and freed again
through _cleanup. The same problem exists in two
verb_machine_control_one/unregister_machine.
Fix these call sites to not set up _cleanup.
2026-04-27 22:14:05 +09:00
Luca Boccassi 3e716178cc machined: gate metadata querying behind inspect-machines/images action
Ensure only privileged users can call the system scope machined's
APIs that get data out of a machine

Follow-up for 1bd979dddb
Follow-up for 9153b02bb5
2026-04-16 13:29:33 +02:00
Christian Brauner f26199631c machinectl: add VM control commands
Add new verbs for controlling vmspawn VMs:

  machinectl poweroff <machine>
  machinectl pause <machine>
  machinectl resume <machine>

Each verb discovers the machine's varlinkAddress via machined's
Machine.List, connects directly to vmspawn's varlink socket, and
calls the corresponding io.systemd.MachineInstance method.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-04-15 10:14:48 +02:00
Christian Brauner fb12d9c555 machined: add controlAddress field to Machine.Register and Machine.List
Follow the existing sshAddress pattern to add a controlAddress field
that allows machine registrants (like vmspawn) to advertise a varlink
socket address for direct VM control. machined stores and exposes
the address but never connects to it itself.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-04-15 10:14:47 +02:00
Lennart Poettering 03ee08d1d7 tree-wide: convert remaining varlink string fields to enum types (#41615)
Follow-up to #40972. Convert remaining plain string fields to proper
varlink enum types across all interfaces, per the policy that
user-controlled/API fields should be declared as proper enums in the
IDL.

Interfaces converted:
- io.systemd.Manager — LogTarget, DefaultStandardOutput/Error,
DefaultMemory/CPU/IOPressureWatch, DefaultOOMPolicy,
CtrlAltDelBurstAction (8 fields)
- io.systemd.Unit — CPUSchedulingPolicy, IOSchedulingClass, NUMAPolicy,
MountFlags (4 fields)
- io.systemd.Machine — class, whom (2 fields, input dispatch converted
to JSON_DISPATCH_ENUM_DEFINE for automatic dashify fallback)
- io.systemd.oom / io.systemd.ManagedOOM — mode in ControlGroup (1
field)

Shared types moved to varlink-idl-common: ExecOutputType,
CGroupPressureWatch, EmergencyAction, ManagedOOMMode — these are reused
across multiple interfaces.

Each interface change includes a corresponding enum sync test to catch
future drift between C string tables and varlink IDL definitions.
2026-04-14 14:04:13 +02:00
Ivan Kruglov 5d0ac2c23c varlink: add enum types for class and whom fields in io.systemd.Machine
Convert the class field (Register input, List output) from plain string
to MachineClass enum type, and the whom field (Kill input) to KillWhom
enum type.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 02:10:52 -07:00
Luca Boccassi a9e9288288 machined: pass user as positional argument in machine_default_shell_args()
Instead of interpolating the user name directly into the sh -c script
body via asprintf %s, pass it as a positional parameter ($1) in a
separate argv entry. This avoids the user string being parsed as part
of the shell script syntax.

Also validate the user name in bus_machine_method_open_shell() with
valid_user_group_name(), matching the validation already done on the
Varlink path via json_dispatch_const_user_group_name().

Follow-up for 49af9e1368
2026-04-13 22:11:50 +01: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
Daan De Meyer 0e231729fd machined: skip leader ownership check for user scope
When registering a machine, machined verifies that the leader process
is owned by the calling user via process_is_owned_by_uid(). This
check fails for user scope machined when the leader is inside a user
namespace: after the leader calls setns(CLONE_NEWUSER), it becomes
non-dumpable, and the subsequent ptrace_may_access() check in the
kernel denies access to the process's user namespace, since the
calling user lacks CAP_SYS_PTRACE in the mm's user namespace (the
host namespace), even though the user owns the child user namespace.

Skip this check when running in user scope. For system scope, the
check is important because multiple users share the same machined
instance, so one user must not be able to claim another user's process
as a machine leader. For user scope this is unnecessary: the varlink
socket lives under $XDG_RUNTIME_DIR (mode 0700), so only the owning
user can connect, and the user machined instance can only perform
operations bounded by that user's own privileges. Registering a
foreign PID does not escalate capabilities.
2026-04-06 17:13:40 +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
Zbigniew Jędrzejewski-Szmek ab3a2f375f sd-varlink: export sd_varlink_set_sentinel
I tried to implement a varlink service using sd-varlink, and
not being able to use the approach with sentinel is exteremely
painful. This is useful internally and likewise externally.
2026-03-29 20:32:15 +02:00
Mike Yuan 771800a403 machine: never ever allow non-root-owned host machine
We really should lock this down _hard_, as evidenced by recent
security fallouts.
2026-03-27 11:47:42 +01:00
Mike Yuan 90cc5b0159 machine: introduce MACHINE_CLASS_CAN_REGISTER
Follow-up for 6df5f80bd3

Similar to SESSION_CAN_* macros in logind-session.h
2026-03-27 11:47:42 +01: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
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 3d72ffc415 machinectl: call all verb functions verb_* 2026-03-18 10:28:47 +00:00
Luca Boccassi 6df5f80bd3 machined: reject invalid class types when registering machines
Follow-up for fbe550738d
2026-03-12 00:24:01 +00:00
Frantisek Sumsal 90f5d2a202 tree-wide: various fixlets suggested by Coccinelle 2026-03-05 10:27:58 +01:00
Frantisek Sumsal a8335fb91f tree-wide: use typed SD_JSON_BUILD_PAIR_* macros more 2026-03-05 10:27:58 +01:00
Mike Yuan ab7d40ff0c machine-varlink: reference the right struct in VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS
This practically shouldn't matter, as the layout for name
and pidref fields are identical for all the structs. But
let's get things right.
2026-03-05 08:56:34 +01:00
Mike Yuan e8c542981b machine-dbus: do not check for overlapping condition
Follow-up for c5e48e3a66

This also makes things in line with the varlink method.
2026-03-04 14:32:46 +01:00
Mike Yuan a521abbf27 machined: move declaration of manager_object to machined-dbus.h 2026-03-04 14:32:16 +01:00
Mike Yuan 08e4cf491a various: make bus objects static 2026-03-04 14:32:16 +01:00
Luca Boccassi e5a5656b55 machined: do not allow unprivileged users to shell into the root namespace via varlink
Forbid non-root from shelling into a machine that is running in
the root user namespace.

Follow-up for adaff8eb35
2026-03-04 13:03:44 +00:00