repart: prefix LUKS superblock label with "luks-" by default, and add explicit VolumeLabel= setting to control it (#39713)

Alternative-to: #39536
This commit is contained in:
Luca Boccassi
2025-11-17 17:46:39 +00:00
committed by GitHub
6 changed files with 86 additions and 21 deletions

9
NEWS
View File

@@ -74,6 +74,15 @@ CHANGES WITH 259 in spe:
image. Hence, effectively they were read-only already, and this is
now official.
* The LUKS volume label string set by systemd-repart no longer defaults
to the literal same as the partition and file system label, but is
prefixed with "luks-". This is done so that on LUKS enabled images a
conflict between /dev/disk/by-label/ symlinks is removed, as this
symlink is generated both for file system and LUKS superblock
labels. There's a new VolumeLabel= setting for partitions that can be
used to expicitly choose a LUKS superblock label, which can be used
to explicitly revert to the old naming, if required.
Service manager/PID1:
* The service manager's Varlink IPC has been extended considerably. It

View File

@@ -578,8 +578,8 @@ disk images with `--image=` or similar:
environment variable to the build directory and you are set. This variable
is only supported when systemd is compiled in developer mode.
Various tools that read passwords from the TTY, such as `systemd-cryptenroll`
and `homectl`:
Various tools that read passwords from the TTY, such as `systemd-cryptenroll`,
`systemd-dissect` and `homectl`:
* `$PASSWORD` — takes a string: the literal password to use. If this
environment variable is set it is used as password instead of prompting the

View File

@@ -256,6 +256,17 @@
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>VolumeLabel=</varname></term>
<listitem><para>The textual label to assign to the LUKS superblock if applicable. If not specified
defaults to the same string as the partition label (see <varname>Label=</varname> above), however
prefixed with <literal>luks-</literal>. This setting has no effect if encryption is not enabled for
this partition.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>UUID=</varname></term>

View File

@@ -2152,8 +2152,15 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to guess verity root hash: %m");
if (arg_action != ACTION_DISSECT) {
_cleanup_(erase_and_freep) char *envpw = NULL;
r = getenv_steal_erase("PASSWORD", &envpw);
if (r < 0)
return log_error_errno(r, "Failed to acquire password from environment: %m");
r = dissected_image_decrypt_interactively(
m, NULL,
m,
envpw,
&arg_verity_settings,
arg_image_policy,
arg_flags);

View File

@@ -398,7 +398,8 @@ typedef struct Partition {
GptPartitionType type;
sd_id128_t current_uuid, new_uuid;
bool new_uuid_is_set;
char *current_label, *new_label;
char *current_label, *new_label; /* Used for the GPT partition label + fs superblock label */
char *new_volume_label; /* used for LUKS superblock */
sd_id128_t fs_uuid, luks_uuid, verity_uuid;
uint8_t verity_salt[SHA256_DIGEST_SIZE];
@@ -714,6 +715,7 @@ static Partition* partition_free(Partition *p) {
free(p->current_label);
free(p->new_label);
free(p->new_volume_label);
free(p->definition_path);
strv_free(p->drop_in_files);
@@ -2750,6 +2752,7 @@ static int partition_read_definition(
ConfigTableItem table[] = {
{ "Partition", "Type", config_parse_type, 0, &p->type },
{ "Partition", "Label", config_parse_label, 0, &p->new_label },
{ "Partition", "VolumeLabel", config_parse_label, 0, &p->new_volume_label },
{ "Partition", "UUID", config_parse_uuid, 0, p },
{ "Partition", "Priority", config_parse_int32, 0, &p->priority },
{ "Partition", "Weight", config_parse_weight, 0, &p->weight },
@@ -3976,6 +3979,27 @@ static const char *partition_label(const Partition *p) {
return gpt_partition_type_uuid_to_string(p->type.uuid);
}
static int volume_label(const Partition *p, char **ret) {
assert(p);
assert(ret);
if (p->new_volume_label)
return strdup_to(ret, p->new_volume_label);
const char *e = partition_label(p);
if (!e)
return -ENODATA;
/* Let's prefix "luks-" for the label string used for LUKS superblocks. We do this so that the
* /dev/disk/by-label/ symlink to the LUKS volume and the file system inside it do not clash */
char *j = strjoin("luks-", e);
if (!j)
return -ENOMEM;
*ret = j;
return 0;
}
static int context_dump_partitions(Context *context) {
_cleanup_(table_unrefp) Table *t = NULL;
uint64_t sum_padding = 0, sum_size = 0;
@@ -4966,21 +4990,6 @@ static int partition_target_sync(Context *context, Partition *p, PartitionTarget
static int partition_encrypt(Context *context, Partition *p, PartitionTarget *target, bool offline) {
#if HAVE_LIBCRYPTSETUP
const char *node = partition_target_path(target);
struct crypt_params_luks2 luks_params = {
.label = strempty(ASSERT_PTR(p)->new_label),
.sector_size = partition_fs_sector_size(context, p),
.data_device = offline ? node : NULL,
};
struct crypt_params_reencrypt reencrypt_params = {
.mode = CRYPT_REENCRYPT_ENCRYPT,
.direction = CRYPT_REENCRYPT_BACKWARD,
.resilience = "datashift",
.data_shift = LUKS2_METADATA_SIZE / 512,
.luks2 = &luks_params,
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY|CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT,
};
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
#if HAVE_TPM2
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
#endif
@@ -5001,6 +5010,26 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
log_info("Encrypting future partition %" PRIu64 "...", p->partno);
_cleanup_free_ char *vl = NULL;
r = volume_label(p, &vl);
if (r < 0)
return log_error_errno(r, "Failed to generate volume label: %m");
const char *node = partition_target_path(target);
struct crypt_params_luks2 luks_params = {
.label = vl,
.sector_size = partition_fs_sector_size(context, p),
.data_device = offline ? node : NULL,
};
struct crypt_params_reencrypt reencrypt_params = {
.mode = CRYPT_REENCRYPT_ENCRYPT,
.direction = CRYPT_REENCRYPT_BACKWARD,
.resilience = "datashift",
.data_shift = LUKS2_METADATA_SIZE / 512,
.luks2 = &luks_params,
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY|CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT,
};
if (offline) {
r = var_tmp_dir(&vt);
if (r < 0)
@@ -5023,6 +5052,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
return log_oom();
}
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
r = sym_crypt_init(&cd, offline ? hp : node);
if (r < 0)
return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", hp);

View File

@@ -123,6 +123,7 @@ last-lba: 2097118"
tee "$defs/root.conf" <<EOF
[Partition]
Type=root
Format=vfat
EOF
ln -s root.conf "$defs/root2.conf"
@@ -132,6 +133,7 @@ EOF
Type=home
Label=home-first
Label=home-always-too-long-xxxxxxxxxxxxxx-%v
Format=vfat
EOF
tee "$defs/swap.conf" <<EOF
@@ -341,13 +343,14 @@ $imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79
tee "$defs/extra3.conf" <<EOF
[Partition]
Type=linux-generic
Type=srv
Label=luks-format-copy
UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
Format=ext4
Encrypt=yes
CopyFiles=$defs:/def
SizeMinBytes=48M
VolumeLabel=schrupfel
EOF
systemd-repart --offline="$OFFLINE" \
@@ -371,7 +374,7 @@ $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${ro
$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\"
$imgs/zzz7 : start= 6291416, size= 131072, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\""
$imgs/zzz7 : start= 6291416, size= 131072, type=3B8F8425-20E0-4F3B-907F-1A25A76F98E8, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\", attrs=\"GUID:59\""
if systemd-detect-virt --quiet --container; then
echo "Skipping encrypt mount tests in container."
@@ -392,6 +395,11 @@ $imgs/zzz7 : start= 6291416, size= 131072, type=0FC63DAF-8483-4772-8E79
losetup -d "$loop"
diff -r "$imgs/mount/def" "$defs" >/dev/null
umount "$imgs/mount"
# Validate that the VolumeLabel= had the desired effect
PASSWORD="" systemd-dissect "$imgs/zzz" -M "$imgs/mount"
udevadm info /dev/disk/by-label/schrupfel | grep -q ID_FS_TYPE=crypto_LUKS
systemd-dissect -U "$imgs/mount"
}
testcase_dropin() {