To properly detect how much space we have to distribute we need to take
into account that both the partition offset and the partition size
aren't aligned.
If we operate on a disk that has a pre-existing unaligned partition
(i.e. one that doesn't start on multiple of 4K, or doesn't have a size
of multiple 4K), then the amount of space after it to distribute among
partitions isn't a multiple of 4K either. So far we might end up
passing the remaining fraction to any partition that wanted it, which
was usually the first one after it that is newly defined. This then
confused the later placement algorithm, since it assumed all partitions
we newly allocate were properly aligned but by being extended by the
fractional space they wouldn't be anymore.
Let's hence fix that by ensuring we never pass space to later partitions
so that things wouldn't be aligned anymore.
Anything that is left-over then at the very end (i.e. typically exactly
the remaining fraction) is added as padding to the existing, unaligned
partition, so that it can't confuse anyone.
Fixes: #20622
These functions are used pretty much independently of locale, i.e. the
only info relevant is whether th locale is UTF-8 or not. Hence let's
give this its own pair of .c/.h files.
otherwise compilation with -Db_ndebug=true complains about a
set-but-not-used variable:
```
../src/partition/repart.c:907:33: error: variable 'left' set but not used [-Werror,-Wunused-but-set-variable]
uint64_t start, left;
^
1 error generated.
```
Previously, we hardcoded use of ECC as primary keys, since they are much
faster (i.e. saving multiple seconds) to do TPM2 operations with. Alas,
not all TPM2 chips appear to support ECC. Bummer.
Let's hence add a fallback logic: if we can't create an ECC primary key,
use an RSA key, and store that fact away.
AFIU the security guarantees should be roughly the same, it's just that
RSA primary keys is so much slower to work with than ECC.
The primary key algorithm is used is stored in the JSON header of LUKS
disks, in a new field. If the field is absent we assume to use ECC, to
provide full compatibility with old systemd versions.
The primary key algorithm is stored in a new field in the credentials
file format (in fact, a previously unused zero space is used), too.
Hopefully, this should ensure that TPM2 support will "just work" on more
systems.
Fixes: #20361
The automatic logic can't always find the original root partition (ex:
if the rootfs is copied to a ext4 fs backed by zram in the initramfs),
so we want to support "/run/systemd/volatile-root" which is a symlink to
the original root partition.
Fix#20610
When the flag COPY_ALL_XATTRS is set, it causes the complete set of xattrs
to be copied. If the flag is unset, only xattrs from the "user" namespace
are copied.
Fixes#17178.
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
Previously, we'd encode PCR policies strictly with the SHA256 PCR bank
set. However, as it appears not all hw implement those. Sad.
Let's add some minimal logic to auto-detect supported PCR banks: if
SHA256 is supported, use that. But if not, automatically fall back to
SHA1.
This then changes both the LUKS code, and the credentials code to
serialize the selected bank, along with the rest of the data in order to
make this robust.
This extends the LUK2 JSON metadata in a compatible way. The credentials
encryption format is modified in an incompatible way however, but given
that this is not part of any official release should be OK.
Fixes: #20134
This improves error output in repart if we can't fit the defined
partitions into the disk image. With this change we'll now show not only
the disk size we need (as before), but also the current one, as well as
the largest free area on disk.
This should make it a bit easier to debug disk space issues that repart
runs into.
For some reason I first commited
a73b2ad041 and then
8f47e32a3e. But the latter makes the
former obsolete and causes us to suffix paths twice.
Let's hence revert a73b2ad041 and stick to
8f47e32a3e as the latter is the ore
generic solution of the two.
This fixes repart's, systemctl's, sysusers' and tmpfiles' specifier
expansion to honour the root dir specified with --root=. This is
relevant for specifiers such as %m, %o, … which are directly sourced
from files on disk.
This doesn't try to be overly smart: specifiers referring to runtime
concepts (i.e. boot ID, architecture, hostname) rather than files on the
medium are left as is. There's certainly a point to be made that they
should fail in case --root= is specified, but I am not entirely convinced
about that, and it's certainly something we can look into later if
there's reason to.
I wondered for a while how to hook this up best, but given that quite a
large number of specifiers resolve to data from files on disks, and most
of our tools needs this, I ultimately decided to make the root dir a
first class parameter to specifier_printf().
Replaces: #16187Fixes: #16183
This is useful for provisioning initially empty secondary A/B root file
systems. We don't want those to ever be considered for automatic
mounting, for example in "systemd-nspawn --image=", hence we should
create them with the No-Auto flag turned on. Once a file system image is
dropped into the partition the flag may be turned off by the updater
tool, so that it is considered from then on.
Thew new option for this is called NoAuto. I dislike negated options
like this, but this is taken from the naming in the spec, which in turn
inherited the name from the same flag for Microsoft Data Partitions. To
minimize confusion, let's stick to the name hence.
Creating those string dynamically at runtime is slow and unnecessary.
Let's use static strings with a bit of macro magic and the let the compiler
coalesce as much as possible.
$ size build/src/shared/libsystemd-shared-248.so{.old,}
text data bss dec hex filename
2813453 94572 4584 2912609 2c7161 build/src/shared/libsystemd-shared-248.so.old
2812309 94564 4584 2911457 2c6ce1 build/src/shared/libsystemd-shared-248.so
A nice side-effect is that the same form is used everywhere, so it's easier to
figure out all variables that are used, and where each specific variable is
used.
C.f. 2b0445262a.
Note: 'const char *foo = alloca(…);' seems OK. Our coding style document and
alloca(3) only warn against using alloca() in function invocations. Declaring
both stack variable and alloca at the same time should be fine: no matter in
which order they happen, i.e. if the pointer variable is above the contents,
or the contents are above the pointer, or even if the pointer is elided by the
compiler, everything should be fine.
The previous string was "unknown", but that's wrong, because we *do*
know what we are going to do with those partitions: we leave them
unmodified, hence say "unchanged" in the output, to be clearer.
This might be useful for CopyFiles=, to reference some subdir of $TMP in
a generic way. This allows us to use the new common
system_and_tmp_specifier_table[].
Previously, we supported only "," as separator. This adds support for
"+" and makes it the documented choice.
This is to make specifying PCRs in crypttab easier, since commas are
already used there for separating volume options, and needless escaping
sucks.
"," continues to be supported, but in order to keep things minimal not
documented.
Fixe: #19205
We recently started making more use of malloc_usable_size() and rely on
it (see the string_erase() story). Given that we don't really support
sytems where malloc_usable_size() cannot be trusted beyond statistics
anyway, let's go fully in and rework GREEDY_REALLOC() on top of it:
instead of passing around and maintaining the currenly allocated size
everywhere, let's just derive it automatically from
malloc_usable_size().
I am mostly after this for the simplicity this brings. It also brings
minor efficiency improvements I guess, but things become so much nicer
to look at if we can avoid these allocation size variables everywhere.
Note that the malloc_usable_size() man page says relying on it wasn't
"good programming practice", but I think it does this for reasons that
don't apply here: the greedy realloc logic specifically doesn't rely on
the returned extra size, beyond the fact that it is equal or larger than
what was requested.
(This commit was supposed to be a quick patch btw, but apparently we use
the greedy realloc stuff quite a bit across the codebase, so this ends
up touching *a*lot* of code.)
We usually call specifier_printf() and then check the validity of
the result. In many cases, validity checkers, e.g. path_is_valid(),
refuse too long strings. This makes specifier_printf() refuse such
long results earlier.
Moreover, unit_full_string() and description field in sysuser now
refuse results longer than LONG_LINE_MAX. config_parse() already
refuses the line longer than LONG_LINE_MAX. Hence, it should be ok
to set the same value as the maximum length of the resolved string.
It's OK to specify the root dir as target directory when copying
directories. However, in that case path_extract_filename() is going to
fail, because the root dir simply has not filename.
Let's address that by moving the call further down into the loop, when
we made sure that the target dir doesn't exist yet (the root dir always
exists, hence this check is sufficient).
Moreover, in the branch for copying regular files, also move the calls
down, and generate friendly error messages in case people try to
overwrite dirs with regular files (and the root dir is just a special
case of a dir).
Altogether this makes CopyFiles=/some/place:/ work, i.e. copying some
dir on the host into the root dir of the newly created fs. Previously
this would fail with an error about the inability to extract a filename
from "/", needlessly.
When we copy files into the freshly formatted file system, the mount
point prefix must be prepended to the *target* path, not the *source*
path. Not just in code but in the log message about it, too.
This teaches repart to look for the root block device both as the
backing for /sysroot and for /sysusr/usr.
The latter is a new addition, and starts making more sense with the next
commit. It's about supporting systems that are shipped with only a /usr/
fs, but where a root fs is allocated and formatted on first boot via
systemd-repart (or a similar tool). In this case it's useful to be able
to mount the ultimate /usr/ early on without mounting the root fs
right-away (simple because the rootfs might not exist yet, and we need
the repart data encoded in /usr/ to actually format it). Hence, instead
of requiring that we mount /sysroot/ first and /sysroot/usr/ second as
we did so far, let's rearrange things slightly:
1. We mount the /usr/ file system we discover to /sysusr/usr/
2. We mount the root file system we discover to /sysroot/
3. Once both are established we bind mount /sysusr/usr/ to /sysroot/usr/
And that' it. The first two steps can happen in either order, and we can
access /usr/ with or without a rootfs being around.
This commit implements nothing of the above. Instead, it teaches
systemd-repart to check both /sysroot/ and /sysusr/ for repart drop-ins,
and use the first of these hierarchies it finds populated. This way
systemd-repart can be spawned once /usr is mounted and it will work
correctly without root fs having to exist, or we can invoke it when the
root fs is already mounted, where it also will work correctly.
Let's make the GPT partition flags configurable when creating new
partitions. This is primarily useful for the read-only flag (which we
want to set for verity enabled partitions).
This adds two settings for this: Flags= and ReadOnly=, which strictly
speaking are redundant. The main reason to have both is that usually the
ReadOnly= setting is the one wants to control, and it' more generic.
Moreover we might later on introduce inherting of flags from CopyBlocks=
partitions, where one might want to control most flags as is except for
the RO flag and similar, hence let's keep them separate.