Commit Graph
286 Commits
Author SHA1 Message Date
felix h a11144d0a9 tree-wide: format man page references as foo(1) 2026-08-28 06:34:45 +09:00
Arian van Putten c7837840f5 firstboot: apply hostname via hostnamed varlink API
Previously we just wrote /etc/hostname and returned. The kernel hostname
was left at whatever PID 1 sethostname()'d very early in boot (before
/etc/hostname existed), which meant hostnamectl reported the transient
hostname instead of the static one until the next reboot.

Call io.systemd.Hostname.SetStaticHostname on the running system so
hostnamed writes /etc/hostname and updates the kernel hostname in one
step. If hostnamed is unreachable (masked or absent on minimal images)
fall back to writing /etc/hostname directly. --root=/--image= also keeps
writing the file directly, since hostnamed only manages the running
system.
2026-08-28 06:29:58 +09: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 ba76d38f37 firstboot: 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 changed to use the imperative
form ("Configure …" instead of "Configures …"), consistent with the
other commands.
2026-08-15 15:24:58 +02:00
Simon de Vlieger d652f6dc44 selinux: wire up LabelContext in tmpfiles, firstboot, sysusers
These three one-shot tools operate on alternate roots via --root/--image
but until now created files with host SELinux labels, producing images
that fail to boot or run with enforcing mode because every file carries
the wrong security context.

Create a LabelContext from arg_root at startup and thread it through all
labeling call sites so the target image gets labeled according to its own
policy.

Signed-off-by: Simon de Vlieger <cmdr@supakeen.com>
2026-07-31 10:06:14 +02:00
Simon de Vlieger 6b0e3ea222 label: plumb label_context through LabelOps
SELinux labeling with --root/--image needs per-call context to carry an
alternate policy database and root prefix. The current LabelOps interface
has no way to pass this, forcing any solution to rely on global state.

Add a LabelContext *label_context to the label_ops callbacks and all
intermediate layers. Generic filesystem functions that most callers use
(xopenat_full, write_string_file_full, etc.) get a _label variant
carrying the extra parameter, with inline wrappers preserving the
original signatures so the vast majority of call sites remain untouched.

Signed-off-by: Simon de Vlieger <cmdr@supakeen.com>
2026-07-31 09:49:41 +02:00
dongshengyuan 50eaa51ce1 firstboot: validate root shell credentials
Validate passwd.shell.root after reading the credential so it uses
the same target-root shell checks as --root-shell= and prompted input.

Reproducer: CREDENTIALS_DIRECTORY=... systemd-firstboot --root=...
with passwd.shell.root=/bin/nonexistentshell

Before: /etc/passwd was written with the nonexistent root shell and
the command exited successfully.

Follow-up: 416f7b3a11
2026-07-18 15:48:34 +08: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 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
Michael Vogt 896fd702ba firstboot: add new systemd.firstboot=headless mode
This adds a new systemd.firstboot=headless mode. It differs from the
existing systemd.firstboot=no mode in that it still performs the
non-interactive auto-configuration that requires no user input (such
as selecting the only installed locale, or applying settings provided
via credentials), and only skips the prompts that would otherwise
block waiting for user input. In contrast, =no disables that
auto-configuration along with the prompts.

The option is also honoured by homectls firstboot logic and
systemd-cryptenroll, where headless behaves the same as no
(because the is no auto-configuration).
2026-07-02 09:52:21 +01:00
Michael Vogt 513e8a3826 creds,firstboot: add support for ? and $ via credentials
Now that we support the `$` we want to also make this available
inside the system.hostname and firstboot.hostname credentials and
the firstboot --hostname option. This commit adds it (and also `?`).
2026-06-20 14:26:41 +02:00
Lennart Poettering b6d9a987f7 firstboot: allow configuring machine tags via firstboot 2026-05-21 18:30:16 +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
Lennart Poettering 85d47bfa92 firstboot: make clear where the full screen console wizards end
The three first boot screens are visually separated from the console
output before them via the "chome" and welcome strings and sufficient
whitespace. But so far they weren't from the output after them. This is
sometimes a big confusing. Let's add a bit of a separator between the
end and what comes next, too.

Just cosmetics, nothing else.
2026-05-21 09:09:38 +09:00
Lennart Poettering ec1f40c89d firstboot: port help() to help-util.[ch] APIs 2026-05-20 16:39:04 +02:00
Lennart Poettering 460dab3936 firstboot: prefill language prompt with firmware language if it makes
sense
2026-05-20 16:38:19 +02:00
Lennart Poettering 1d646aed65 firstboot: prefill keymap question with EFI provided info 2026-05-20 16:38:18 +02:00
Lennart Poettering a80024e96d ask-string: support prefilling a string query with an explicit string 2026-05-20 16:34:21 +02:00
Lennart Poettering 324fab7ed6 firstboot,sysinstall,hostnamed: always show FANCY_NAME=
This makes sure that whenever we want to show the OS name we can show
the fancy name. Thus this moves the escaping/validation of the fancy
name out of hostnamed into generic code, and then makes use of it in
sysinstall,firstboot,prompt-util.
2026-05-12 00:07:42 +01:00
Lennart Poettering 99ce7a0770 options: get rid of "on_error" parameter to FOREACH_OPTION
I am really not a fan of full code lines passed to macros as parameters.
Let's get rid of the 3rd parameter of FOREACH_OPTION() hence:

1. Let's return errors just as a regular value (though a negative one),
   that can be handled via a OPTION_ERROR case statement for the switch.
   This normalizes handling of the error, just like any other event
   returned by the option parser.

2. In order to avoid exploding the amount of boilerplate in each use
   (that just propagates the error on OPTION_ERROR), let's then
   introduce an explicit FOREACH_OPTION_OR_RETURN(), that returns from
   the calling function on its own (and makes that clear in the name).

Together this cleans up, normalizes the logic and shortens the code.
2026-04-30 11:12:33 +01:00
Zbigniew Jędrzejewski-Szmek 5ff0ccaf8b tree-wide: change option_parse() to return option and arg via internal state
It was requested to make the 'c', 'opt', and 'arg' params the same, i.e.
defined through the FOREACH_OPTION macro. But we can't do that easily,
because 'c' was defined in the for loop definition, and we can only
define variables of the same type in that way. Also, in some cases we
need only 'c', in other cases with need 'c' and 'arg, in some cases 'c'
and 'opt', and in other cases all three. We'd need to either
conditionalize or mark those variables with _unused_ to deal with
compiler warnings. But a different approach works quite nicely: add
state.opt and state.arg to show the current option and it's argument.
(The short names are picked on purpose to reduce verbosity since those
are used a lot.)
2026-04-27 11:33:10 +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 086daddfdf firstboot: use parse_boolean_argument in one more place
This was pointed out in review.
2026-04-16 16:55:17 +02:00
Zbigniew Jędrzejewski-Szmek 30863f491b firstboot: use free_and_strdup_warn in parse_argv
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:55:15 +02:00
Zbigniew Jędrzejewski-Szmek 5a2777c93e firstboot: convert to the new option parser
The descriptions for boolean options are adjusted to work better
with BOOL as the metavar.

Description of --copy is fixed, fixup for
f649325ba7.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:55:14 +02:00
Zbigniew Jędrzejewski-Szmek edc8e93830 firstboot: reorder option cases to match --help output
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:55:12 +02:00
Lennart Poettering 4c49e864b0 firstboot: permit setting the static hostname via a system credential
For the IMDS case there's value in being able to set the static
hostname, instead of just the transient one. Let's introduce
firstboot.hostname, which only applies to first boot, and write the
static hostname. This is different from system.hostname which applies to
any boot, and writes the transient hostname.
2026-03-20 12:39:44 +01:00
Lennart Poettering 4460a4ba21 firstboot: harden credential handling a bit
Credentials are highly privileged things, but still, let's do some
validation, because we can.
2026-03-20 12:39:44 +01:00
Luca Boccassi 75cb25c0b9 firstboot/homectl: hide plymouth splashscreen when asking questions
When plymouth is enabled, the screen gets all garbled when firstboot
runs and asks questions. Disable the splash screen, but only when
actually asking questions.
2026-02-03 13:21:03 +01:00
Yu Watanabe d0b224f845 libcrypt-util: turn into dlopen() dependency
Note, this drops logging only test case for crypt_preferred_method(),
as that requires explicitly dlopen() the library. But, we should test
that make_salt() and friends automatically dlopen() it.
2026-01-02 13:06:14 +09:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Yu Watanabe 19deb47ade firstboot: drop redundant and spurious errno check
Follow-up for 2319154a6b.
2025-11-23 22:36:50 +09: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
Lennart Poettering 372f3159fd firstboot: don't talk about any 'new' installation
The firstboot interface might pop-up also during live mode (because it's
just very useful to have the right kbd mapping applied), and that's
hardly a "new installation". Hence use more generic terms
2025-09-26 16:40:14 +02:00
Lennart Poettering aa27bec194 firstboot: optionally, don't query for keymap unless connected to a real VT
The keymap only really matters if there's local access to a system, i.e.
if there's actually a physical kbd directly connected to it, to apply it
to. If during firstboot we are not talked to via a VT (but via SSH,
container, or hypervisor console or so instead), then it's very unlikely
we ever are. Hence, don't ask for a keymap, and let#s shortcut the
questions asked at boot.
2025-09-26 16:40:14 +02:00
Lennart Poettering bedcce1a1f firstboot: drop waiting for key when starting
We only show this blurb on the first question, but the first question is
interactive anyway, hence no need to wait for input first explicitly, we
won't progress anyway without user input.

(similar for homectl's firstboot)
2025-09-26 16:27:53 +02:00
Lennart Poettering 971637c47d firstboot: get rid of pointless strjoina() 2025-09-26 09:43:45 +02:00
Lennart Poettering 0d2cc656c8 firstboot: mute console while running on the console at boot
Fixes: #34448
2025-09-26 09:42:13 +02:00
Lennart Poettering 875a618ed3 firstboot: modernize --help output 2025-09-24 15:46:30 +02:00
Lennart Poettering 73ee723aa7 firstboot: show blue "chrome" bar at top 2025-09-24 15:46:30 +02:00
Lennart Poettering fa350969ab prompt-util: add generic prompt loop implementation
This is a generalization of the logic in systemd-firstboot. This also
ports over firstboot.c to make use of the new generalization.
2025-09-24 15:46:30 +02:00
Yu Watanabe de69562623 tree-wide: add missing '=' in short comments for function argument 2025-07-22 03:05:54 +09:00
Valentin David 0dc39dffbd Use paths specified from environment variables for /etc configuration files
Some configuration files that need updates are directly under in /etc. To
update them atomically, we need write access to /etc. For Ubuntu Core this is
an issue as /etc is not writable. Only a selection of subdirectories can be
writable. The general solution is symlinks or bind mounts to writable places.
But for atomic writes in /etc, that does not work. So Ubuntu has had a patch
for that that did not age well.

Instead we would like to introduce some environment variables for alternate
paths.

 * SYSTEMD_ETC_HOSTNAME: /etc/hostname
 * SYSTEMD_ETC_MACHINE_INFO: /etc/machine-info
 * SYSTEMD_ETC_LOCALTIME: /etc/localtime
 * SYSTEMD_ETC_LOCALE_CONF: /etc/locale.conf
 * SYSTEMD_ETC_VCONSOLE_CONF: /etc/vconsole.conf
 * SYSTEMD_ETC_ADJTIME: /etc/adjtime

While it is for now expected that there is a symlink from the standard, we
still try to read them from that alternate path. This is important for
`/etc/localtime`, which is a symlink, so we cannot have an indirect symlink or
bind mount for it.

Since machine-id is typically written only once and not updated. This commit
does not cover it. An initrd can properly create it and bind mount it.
2025-06-23 15:32:11 +02:00
Lennart Poettering 611bb28dc3 firstboot: make sure labelling is enabled
Preparation to address #37857.
2025-06-18 10:29:29 +02:00
Lennart Poettering f6e213e86a firstboot: use WRITE_STRING_FILE_LABEL more
Let's explicitly label 3 key files we generate in systemd-firstboot.

Addresses some more of #37857.
2025-06-18 10:21:26 +02:00
Lennart Poettering 3e5320e27d env-file: port write_env_file() to label_ops_pre()
Let's make more use of label_ops_pre()/label_ops_post(), and replace
write_env_file_label() by a flag to write_env_file().

This simplifies and normalizes the code.

This also makes one relevant change: it sets the new
WRITE_ENV_FILE_LABEL flag in firstboot.c when we write locale.conf,
where we previously did not (but should have). This should address one
detail of #37857.
2025-06-18 10:21:26 +02:00
Lennart Poettering 9ea5a6e7d6 fs-util: replace symlink_atomic_full_label() by a flag to symlinkat_atomic_full()
More porting work to label_ops_pre()/label_ops_post()

This also enables labelling of the /etc/localtime symlink in
systemd-firstboot, which should address one small facet of #37857
2025-06-18 10:21:25 +02:00
Daan De Meyer 86b9a3e31d tree-wide: Clean up includes
This removes more unused includes from the components already cleaned
up in #37467 and #37457.

Split out of #37344.
2025-05-21 10:49:42 +02:00
Daan De Meyer 8857aa74e5 tree-wide: Clean up includes
This commit cleans up the includes for all the small tools across
the tree.

A few cases of returning EXIT_SUCCESS are replaced with returning
0 to avoid including <stdlib.h>.

Split out of #37344.
2025-05-14 22:34:02 +02:00
Yu Watanabe 3a03b97d6f tree-wide: drop unnecessary inclusion of tmpfile-util.h 2025-04-30 05:38:48 +09:00