While we typically just use /dev/tpmrm0 for accessing the TPM chip (i.e
via the kernel's own resource manager), some sysfs properties that
matter are on /dev/tpm0 only (i.e. the version without the kernel TPM
resource manager). Hence, wait for both to show up in tpm2.target, so
that we can be sure the full API is available.
This matters because we want to access /sys/class/tpm/tpm0/ppi/request
in the next commit.
This introduces a bunch of facilities:
1. The factory-reset.target unit that requests a factory reset is now
complemented by factory-reset-now.target that executes it at next
boot.
2. This latter is added to the initial transaction via the new trivial
systemd-factory-reset-generator.
3. A tool systemd-factory-reset has been added to query, request,
cancel, complete factory reset operations (via EFI variables). Two of
these are wrapped into units that are plugged into
factory-reset.target and factory-reset-now.target respectively. The
tool also provides a simple Varlink API.
This should make things a lot cleaner, and both be useful as explicit
implementation on UEFI, and as template + hookpoints for alternative
implementations on non-UEFI.
Let's provide a generic implementation of the systemd.factory_reset
kernel cmdline checking repart implements. Moreover add support for
leaving the factory reset state again.
This only establishes the basic APIs, it does not hook them up with
anything.
It's sometimes very useful to be able to terminate a container quickly
but cleanly while talking to it. Introduce a hotkey for that: ^]^]p for
powering it off. In similar style add ^]^]r for rebooting it.
Let's add the ability that ptyfwd tools can register additional hotkeys
that they then can handle.
So far the only hotkey we support is ^]^]^] to exit the ptyfwd session
abruptly. Staying close to this let's add ^]^]<char> for additional
commands.
We'll add another type of handler callback in the next commit, hence
rename the existing handler to be more precise what it is about:
handling hangups (either inline via tty, or explicit via user request)
We currently don't support invoking a per-area service manager instance,
hence don't try to pull in one if we log into an area.
Once we add support for per-area service managers we can relax this
again.
We always validate that the target value is below _LOG_TARGET_SINGLE_MAX
before acessing it, but we don't actually size the array like that.
let's fix that.
This doesn#t effectively change anything, but it makes things more
explicit what the limit here is.
If we use TCP fastopen to connect to a DNS server via TCP, and it
responds really quickly between our connection attempt and our immediate
check back, then we have not identified the peer yet, and will not be
able to use the peer metadata to fill in our packet info.
Let's fix that, and simply not read from the socket until identification
is complete.
Fixes: #34956
I noticed that systemd-tty-password-agent would time out when asked to
stop via SIGTERM, and eventually be killed, under some circumstances. It
took me a while but i figured out what was going on:
systemd-ask-pw-agent blocks SIGTERM because it wants async notifications
on SIGTERM via signalfd() to listen on. That mostly works great: except
for one case: if we actually get a pw query request, and hence need to
acquire the terminal: we issue open_terminal() in that case, but if the
terminal is used otherwsie we'll hang, and because SIGTERM is blocked
we'll hang and cannot exit cleanly.
Address that: optionally, in open_terminal() look for SIGTERM by
unblcking the signal mask via ppoll() while we wait.
If a non-zero timeout is specified we should not bypass ppoll() even if
no fds are specified, since it will still act as a time based sleep in
that case.
Terminating the plymouth/console agents when the wall agent takes over
can happen asynchronously, after all the pw queries are async anyway and
hence can be seen by both the plymouth/console agents and the wall
agent.
By stopping the two agents with "--no-block" we add a bit of robustness,
since trouble of them exiting won't block the wall agent to start.
This addresses the issue the previous commit fixes in a different way.
I noticed that systemd-tty-password-agent would time out when asked to
stop via SIGTERM, and eventually be killed, under some circumstances.
It took me a while but i figured out what was going on:
systemd-ask-pw-agent blocks SIGTERM because it wants async notifications
on SIGTERM via signalfd() to listen on. That mostly works great: except
for one case: if we actually get a pw query request, and hence need to
acquire the terminal: we issue open_terminal() in that case, but if the
terminal is used otherwsie we'll hang, and because SIGTERM is blocked
we'll hang and cannot exit cleanly.
Address that: optionally, in acquire_terminal() look for SIGTERM by
unblcking the signal mask via ppoll() while we wait.
In various scenarios we invoke containers with access to the kernel
keyring blocked. Let's make sure we can handle this properly: when the
invocation ID is stored in in the kernel keyring and we try to read it
and get EPERM we should handle it gracefully, like EOPNOTSUPP.
This reverts commit b6a2df6307.
The functionality is entirely redundant, we already have
sd_json_variant_filter() which does the same, and is in fact even more
powerful, since it takes a list instead of a single field to remove.
This is mostly a strawman to get a discussion going regarding how to
communicate to terminal emulators such as ptyxis about run0 (and nspawn,
and vmspawn, and moe) and what it does.
It's hierarchical and I think still relatively simple.
/cc @chergert
Let's "spoil" access to TPM secrets when we boot into these two modes.
This matters in particular for storagetm: if the host gets exploited
while booted into storage target mode any secrets kept by the TPM might
remain accessible otherwise. By measuring a new "phase" word into PCR 11
we "blow the fuse" however on this boot.
(Note: we also change TEST-13-NSPAWN.machined.sh minimally here, because
it checks for byte precise output of a pty allocated for a service
invocation - which it's not going to get if it claims that the pty is an
all-powerful one. After all this PR ensures that we'll generate the new
OSC sequence on non-dumb terminals associated with services. Hence, set
TERM=dumb explicitly to ensure no ANSI sequences are generated, ever.
Which is a nice test btw that TERM=dumb really does its thing here.)
So far we conditioned the logic that issues ansi sequences for resetting
the TTY based on whether something is a pty is not (under the assumption
we need no reset on ptys, since they are shortlived).
This is simply wrong though. The pty that a container getty is invoked
on is generally long-lived: as long as the container is up, and it will
be reused between getty instances/sessions all the time. In such a case
we really should reset properly.
Let's instead make the logic dependent on whether TERM is set to
anything other than "dumb". The previous commit made sure we always set
TERM in a sensible way in systemd-run, hence this
*explicit* logic sounds like a much better choice now, as it mea
let's convert the 2nd argumeng form a boolean to a proper flags
parameter. Doesn't change behaviour in anyway, but is more readable, and
prepares ground for adding more flags soon.
There are two cases when we invoke a service on a TTY:
1. We ourselves are connected to a TTY and would intend to enable PTY
forwarding.
2. We are allocating a TTY but are not ourselves connected to a TTY and
just want to input/output to pipe or other non-TTY fd.
Let's propagate $TERM only as-is in the first case. In the 2nd case,
let's explicitly set $TERM to "dumb", so that invoked progams do not
issue needless ansi sequences, since we are not propagating them to a
terminal either.
This should be a much safer result, for cases where people include
invocations of systemd-nspawn with full TTY allocation in a shell
pipeline or so.
(of course, the user can always explicitly override this)
note: this also adds making a copy of the session type string after
registering the session. That's because we need to check the session
type we settled on later to condition out the OSC sequence (because it
should only be issued on TTY sessions). However, the session type string
originally quite likely points into the PAM environment block, which we
update in the meantime, invalidating that pointer. hence, make an
explicit copy first, and use that.
Let's make sure that the moment where factory reset is requested is
visible in the TPM PCR state, so that access to secrets is terminated.
This is particulary interesting when the system is booted with
systemd.unit=factory-reset.target on the kernel command line, requesting
a factory reset on the following boot. The preparations done in
userspace should already lose access to the TPM in that case.
storagetm mode means we we are network accessible. let's lock down
access to TPM secrets in this case: let's measure a pcr "phase" string
into PCR 11.
This is good as it means that if we are exploited in this state FDE
secrets protected by TPM are likely to remain protected, since the PCR
values wouldn't allow access.
In 2cc58b6c8a and related we established
rules on naming certs/public-keys/private-keys:
*-public-key.pem
*-private-key.pem
*-certificate.pem
Let's follow that naming in repart's man page too.
When a user logs into a non-default area we give them a private
$HOME for that area (that's what 'area' is supposed to be after all). We
so far left $XDG_RUNTIME_DIRECTORY as it was. Let's change that and
mirror the subdirectory logic there too.
Why? $XDG_RUNTIME_DIR is generally the place where AF_UNIX sockets are
bound that can be used to connect to per-user services. (in particular
all those which are behind D-Bus.) If we don't patch $XDG_RUNTIME_DIR
like this then this means all the backing services will use the main
area, which is problematic (since clients and services will disagree on
$HOME), and makes it impossible to support the area concept for
graphical logins properly.
This does not actually make graphical logins work, but it at least makes
them fail cleanly. That's because this patch alone won't make sure a
per-area service manager/dbus instance is invoked automatically. That
however can be added later, in a patch to logind.
Let's tweak update_environment() a bit: instead of being a NOP when no
value is specified, let's actively unset the specified environment
variable if it is set.
This shouldn't change much, since for the cases we call the function so
far the env vars in question should not be set before us in a way we'd
set them differently. However, this is nice preparation for later, as we
can make use of this for XDG_AREA which we might want to unset if we
consider the area dir invalid.
Let's move pam_systemd_home before pam_unix in the authentication hook.
Since a while we are exposing shadow entries for homed log entries via
NSS. This means that pam_unix now potentially has enough data for
authenticating a user on its own, without letting pam_systemd_home do
that. This is superficially OK, but also means that authentication will
always go via password, even if pkcs11/fido2 is registered.
Let's move this around, but be careful about it: let's list the precise
errors which we think are enough to terminating further PAM processing,
so that pam_unix comes into control in all cases where it's not clear
that pam_systemd_home owns the user record.
This previously wasn't visible to me, because on Fedora until authselect
1.5.1 (released earleir this year) the NSS shadow stuff was not enabled.
This does the same also for the "account" stack, except that the order
there already was as we want it.
Finally, shorten the account stack, by just requiring pam_unix.so and
dropping pam_permit.so, because it doesn't really serve much purpose
(and Fedora doesn't use it by default either.)
This has been depracted since v254 (2023). Let's kill it for
good now, it has been long enough with 2y. Noone has shown up who wants
to keep it. And given it doesn't work in SB world anyway, and is not
measured is quite problematic security wise.
Let's in particular log an even if a device name is too long for the
btrfs ioctl structure, instead of truncating it (which could
theoretically reference a different device).
The immediately following flink_tmpfile() does that anyway, hence no
need to do so explicitly beforehand.
(Also the log message was wrong: it says "sync" but here we "flush",
which is a much weaker operation)
Clean up systemd-boot a bit. Mostly makes handling of some menu entry
types less magic and more uniform. Doesn't really change behaviour in
any ways, except that we now condition things such as boot counting,
random seed management and entry selection saving carefully on the entry
type.
Let's make the three subsystems more alike, and add remote-*setup.traget
for all three, enable them all three in the presets, and make them
behave in a similar fashion.
Let's make cryptsetup and veritysetup more symmetric, and enable the
remote target for the latter the same way we enable the remote target
for the former by default.
This is the last entry type that has special handling: with this in
place we now always invoke entry handlers the very same way. via the
.call() method of the BootEntry structure.
Similar to the previous commits, let's carefully condition random seed
management (which might be slow, and simply pointless for various entry
types) on the entry type.
Let's pass some context information to the .call() methods so that it's
sufficient to implement the handlers for all entry types with them.
(This commit doesn't port the various entry types over though, that
happens in later commits.)
I ran into the limit with ParticleOS, with 6 profiles, hence I think the
current default value is a bit low. let's bump it 4x, to 120. This is
still a lot lower than 500 or so which Debian uses downstream.
We can look into raising this further should we collide with this again,
but for now, let's try 120 and see how it goes in practice.
This extends systemd-import-generator to not only download a disk image
at boot, but also attach it to a loopback device, so that we can boot
from it.
We have most of the pieces already in place, this just polishes some
things, to make this round.
The topmost commit contains example command lines that just work to make
`systemd-vmspawn` boot from a `mkosi serve` call.
Note that this does not address how to get the UKI running on the target
system, this only deals with the later boot phase once the UKI is
already running.
This is WIP, because it lacks docs, and I want to do some more
polishing. But it works great.
Ultimate goal, provide a complete solution so that we also can do uefi
http boot for ukis
With this we can now do:
systemd-vmspawn -n -i foobar.raw -s io.systemd.boot.entries-extra:particleos-current.conf=$'title ParticleOS Current\nuki-url http://example.com/somedir/uki.efi'
Assuming sd-boot is available inside the ESP of foobar.raw a new item
will show up in the boot menu that allows booting directly into the
specified UKI.
This one is between "efi" and "linux": we'll recognize such entries as
linux, but we'll just invoke them as EFI binaries.
This creates a high-level concept for invoking UKIs via indirection of a
bls type #1 entry, for example to permit invocation from a non-standard
path or for giving entries a different name.
Companion BLS spec PR:
https://github.com/uapi-group/specifications/pull/135
(Let's rename LOADER_UNIFIED_LINUX to LOADER_TYPE2_UKI at the same time
to reduce confusion what is what)