So far, at the one place we sent a PID over Varlink we did so as a
simple numeric pid_t value. That's of course is racy, since classic PIDs
are recycled too eagerly.
Let's address that, by passing around JSON objects distantly resembling our
PidRef structure. Note that this JSON object does *not* contain the
pidfd, however, but just the pidfd inode number if known.
I originally planned to include the pidfd in some direct form, but I
figured that's not really the best idea, since we always need a
side-channel of some form for that (i.e. AF_UNIX/SCM_RIGHTS), but we
should be able to report about PIDs even without that.
Moreover, while sending the pid number and pidfd id around should always
be OK to do, it's a lot more problematic to always send a pidfd around,
since that implies that fd passing is on and it is OK to install fds
remotely in some IPC peers fd table. For example, when doing a wild dump
of service manager service state we really shouldn't end up with a bunch
of fds installed in our client's fd table.
Hence, all in all I think it is cleaner to define a structure carrying
pid number and pidfd inode id, wich is passed directly as JSON. And then
optionally, in a separate field also pass around a pidfd where it makes
sense.
Note that sending around pidfds is not that beneficial anymore if we
have the pidfd inode id, because we can always securely and reliably get
a pidfd back from a pair of pid + inode id: first we do pidfd_open() on
the pid, and then we check if it is really the right one by comparing
.st_ino after fstat().
This logic is implemented gracefully: if for some reason pidfd/pidfd
inode nrs are not available (too old kernel), we'll fall back to plain
PID numbers.
The dispatching logic knows two distinct levels of validation of the
provided PID data: if SD_JSON_STRICT is specified we'll acquire a pidfd
for the PID, thus verifying it currently exists and failing if it
doesn't. If the flag is not set, well just store the provided info
as-is, will try to acquire a pidfd for it, but not fail if we cannot.
Both modes are important in different contexts.
Also note that in addition to the pidfd inode nr we always store the
current boot ID of the system in the JSON object, since only the
combination of pidfd inode nr and boot ID of the system really is a
world-wide unique reference to a process.
When dispatching a JSON pid field we operate somewhat gracefully: we
either support the triplet structure of pid, pid inode nr, boot id, or
we accept a simple classic UNIX pid.
Catch up with the nice little toys the kernel fs developers have added
for us. Preferably, let's make use of the new F_DUPFD_QUERY fcntl() call
that checks whether two fds are just duplicates of each other
(duplicates as in dup(), not as in open() of the same inode, i.e.
whether they share a single file offset and so on).
This API is much nicer, since it is a core kernel feature, unlike the
kcmp() call we so far used, which is part of the (optional)
checkpoint/restore stuff.
F_DUPFD_QUERY is available since kernel 6.10.
Let's mark functions that accept the 'more' flag explicitly for that,
and validate for this explicitly.
This is preparation for
https://github.com/varlink/varlink.github.io/issues/26, if we get that
one day. Let's make sure that from day #1 we have this info available
even if we don't generate this in the IDL for now.
Also enables the two flags for all interfaces we export that use the
logic.
Let's systematically use RTL_NOW|RLTD_NODELETE as flags passed to
dlopen(), across our codebase.
Various distros build with "-z now" anyway, hence it's weird to specify
RTLD_LAZY trying to override that (which it doesn't). Hence, let's
follow suit, and just do what everybody else does.
Also set RTLD_NODELETE, which is apparently what distros will probably
end up implying sooner or later anyway. Given that for pretty much all
our dlopen() calls we never call dlclose() anyway, let's just set this
everywhere too, to make things systematic.
This way, the flags we use by default match what distros such as fedora
do, there are no surprises, and read-only relocations can be a thing.
Fixes: #34537
If we're running in a user namespace with a single user and without
the nobody user, we'll get EINVAL from these system calls so make
sure we handle those gracefully.
So far you had to pick:
1. Use a signed PCR TPM2 policy to lock your disk to (i.e. UKI vendor
blesses your setup via signature)
or
2. Use a pcrlock policy (i.e. local system blesses your setup via
dynamic local policy stored in NV index)
It was not possible combine these two, because TPM2 access policies do
not allow the combination of PolicyAuthorize (used to implement #1
above) and PolicyAuthorizeNV (used to implement #2) in a single policy,
unless one is "further upstream" (and can simply remove the other from
the policy freely).
This is quite limiting of course, since we actually do want to enforce
on each TPM object that both the OS vendor policy and the local policy
must be fulfilled, without the chance for the vendor or the local system
to disable the other.
This patch addresses this: instead of trying to find a way to come up
with some adventurous scheme to combine both policy into one TPM2
policy, we simply shard the symmetric LUKS decryption key: one half we
protect via the signed PCR policy, and the other we protect via the
pcrlock policy. Only if both halves can be acquired the disk can be
decrypted.
This means:
1. we simply double the unlock key in length in case both policies shall
be used.
2. We store two resulting TPM policy hashes in the LUKS token JSON, one
for each policy
3. We store two sealed TPM policy key blobs in the LUKS token JSON, for
both halves of the LUKS unlock key.
This patch keeps the "sharding" logic relatively generic (i.e. the low
level logic is actually fine with more than 2 shards), because I figure
sooner or later we might have to encode more shards, for example if we
add further TPM2-based access policies, for example when combining FIDO2
with TPM2, or implementing TOTP for this.
We typically want to deal in usec_t, hence let's change the prototype
accordingly, and do proper range checks. Also, make sure are not
confused by negative times.
Do something similar for mktime_or_timegm().
This is a more comprehensive alternative to #34065
Replaces: #34065
Now that mkfs.btrfs is adding support for compressing the generated
filesystem (https://github.com/kdave/btrfs-progs/pull/882), let's
add general support for specifying the compression algorithm and
compression level to use.
We opt to not parse the specified compression algorithm and instead
pass it on as is to the mkfs tool. This has a few benefits:
- We support every compression algorithm supported by every tool
automatically.
- Users don't need to modify systemd-repart if a mkfs tool learns a
new compression algorithm in the future
- We don't need to maintain a bunch of tables for filesystem to map
from our generic compression algorithm enum to the filesystem specific
names.
We don't add support for btrfs just yet until the corresponding PR
in btrfs-progs is merged.
Unprivileged users often make themselves root by unsharing a user namespace
and then mapping their current user to root which does not require privileges.
Let's make sure our tests don't fail in such an environment by adding checks
where required to see if we're not running in a user namespace with only a
single user.
When removing a cgroup, we always want to eliminate subcgroups
first, i.e. use cg_trim(). And cg_rmdir() (along with
CGROUP_REMOVE flag) is simply unused. Kill it.
Currently, IS_SYNTHETIC_ERRNO() evaluates to true for all negative errnos,
because of the two's-complement negative value representation.
Subsequently, ERRNO= is not logged for most of our own code.
Let's fix this, by formatting all synthetic errnos as positive.
Then, treat all negative values as non-synthetic.
While at it, mark the evaluation order explicitly, and remove
unneeded comment.
Fixes#33800