1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-06 13:17:44 +03:00

Merge pull request #25823 from poettering/dissect-diskseq

gpt-auto: reference dissected partitions to mount via diskseq block device symlinks
This commit is contained in:
Yu Watanabe 2022-12-23 22:11:59 +09:00 committed by GitHub
commit 2b22355075
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 31 deletions

3
TODO
View File

@ -167,9 +167,6 @@ Features:
* systemd-dissect: maybe add "--attach" and "--detach" verbs which
synchronously attach a DDI to a loopback device but not actually mount them.
* gpt-auto-generator: generate device names via /dev/disk/by-diskseq/ to pin
the medium
* pam_systemd_home: add module parameter to control whether to only accept
only password or only pcks11/fido2 auth, and then use this to hook nicely
into two of the three PAM stacks gdm provides.

View File

@ -137,5 +137,6 @@ ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/
# the diskseq number from the path, then issue BLKGETDISKSEQ to verify they really got
# the right device, to access specific disks in a race-free fashion)
ENV{DISKSEQ}=="?*", ENV{DEVTYPE}!="partition", ENV{DISKSEQ}=="?*", ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"
ENV{DISKSEQ}=="?*", ENV{DEVTYPE}=="partition", ENV{DISKSEQ}=="?*", ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}-part%n"
LABEL="persistent_storage_end"

View File

@ -674,7 +674,8 @@ static int enumerate_partitions(dev_t devnum) {
loop,
NULL, NULL,
DISSECT_IMAGE_GPT_ONLY|
DISSECT_IMAGE_USR_NO_ROOT,
DISSECT_IMAGE_USR_NO_ROOT|
DISSECT_IMAGE_DISKSEQ_DEVNODE,
/* NB! Unlike most other places where we dissect block devices we do not use
* DISSECT_IMAGE_ADD_PARTITION_DEVICES here: we want that the kernel finds the
* devices, and udev probes them before we mount them via .mount units much later

View File

@ -322,28 +322,57 @@ static void dissected_partition_done(DissectedPartition *p) {
#if HAVE_BLKID
static int make_partition_devname(
const char *whole_devname,
uint64_t diskseq,
int nr,
DissectImageFlags flags,
char **ret) {
bool need_p;
_cleanup_free_ char *s = NULL;
int r;
assert(whole_devname);
assert(nr > 0);
assert(nr != 0); /* zero is not a valid partition nr */
assert(ret);
/* Given a whole block device node name (e.g. /dev/sda or /dev/loop7) generate a partition device
* name (e.g. /dev/sda7 or /dev/loop7p5). The rule the kernel uses is simple: if whole block device
* node name ends in a digit, then suffix a 'p', followed by the partition number. Otherwise, just
* suffix the partition number without any 'p'. */
if (!FLAGS_SET(flags, DISSECT_IMAGE_DISKSEQ_DEVNODE) || diskseq == UINT64_MAX) {
if (isempty(whole_devname)) /* Make sure there *is* a last char */
return -EINVAL;
/* Given a whole block device node name (e.g. /dev/sda or /dev/loop7) generate a partition
* device name (e.g. /dev/sda7 or /dev/loop7p5). The rule the kernel uses is simple: if whole
* block device node name ends in a digit, then suffix a 'p', followed by the partition
* number. Otherwise, just suffix the partition number without any 'p'. */
need_p = ascii_isdigit(whole_devname[strlen(whole_devname)-1]); /* Last char a digit? */
if (nr < 0) { /* whole disk? */
s = strdup(whole_devname);
if (!s)
return -ENOMEM;
} else {
size_t l = strlen(whole_devname);
if (l < 1) /* underflow check for the subtraction below */
return -EINVAL;
return asprintf(ret, "%s%s%i", whole_devname, need_p ? "p" : "", nr);
bool need_p = ascii_isdigit(whole_devname[l-1]); /* Last char a digit? */
if (asprintf(&s, "%s%s%i", whole_devname, need_p ? "p" : "", nr) < 0)
return -ENOMEM;
}
} else {
if (nr < 0) /* whole disk? */
r = asprintf(&s, "/dev/disk/by-diskseq/%" PRIu64, diskseq);
else
r = asprintf(&s, "/dev/disk/by-diskseq/%" PRIu64 "-part%i", diskseq, nr);
if (r < 0)
return -ENOMEM;
}
*ret = TAKE_PTR(s);
return 0;
}
static int open_partition(const char *node, bool is_partition, const LoopDevice *loop) {
static int open_partition(
const char *node,
bool is_partition,
const LoopDevice *loop) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_close_ int fd = -EBADF;
dev_t devnum;
@ -442,6 +471,8 @@ static int dissect_image(
* Returns -ENXIO if we couldn't find any partition suitable as root or /usr partition
* Returns -ENOTUNIQ if we only found multiple generic partitions and thus don't know what to do with that */
uint64_t diskseq = m->loop ? m->loop->diskseq : UINT64_MAX;
if (verity && verity->root_hash) {
sd_id128_t fsuuid, vuuid;
@ -537,9 +568,9 @@ static int dissect_image(
log_debug_errno(r, "Failed to parse file system UUID '%s', ignoring: %m", suuid);
}
n = strdup(devname);
if (!n)
return -ENOMEM;
r = make_partition_devname(devname, diskseq, -1, flags, &n);
if (r < 0)
return r;
m->single_file_system = true;
m->encrypted = streq_ptr(fstype, "crypto_LUKS");
@ -650,7 +681,9 @@ static int dissect_image(
assert((uint64_t) size < UINT64_MAX/512);
r = make_partition_devname(devname, nr, &node);
/* While probing we need the non-diskseq device node name to access the thing, hence mask off
* DISSECT_IMAGE_DISKSEQ_DEVNODE. */
r = make_partition_devname(devname, diskseq, nr, flags & ~DISSECT_IMAGE_DISKSEQ_DEVNODE, &node);
if (r < 0)
return r;
@ -862,9 +895,7 @@ static int dissect_image(
generic_rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
generic_growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
generic_uuid = id;
generic_node = strdup(node);
if (!generic_node)
return -ENOMEM;
generic_node = TAKE_PTR(node);
}
} else if (type.designator == PARTITION_VAR) {
@ -903,7 +934,7 @@ static int dissect_image(
}
if (type.designator != _PARTITION_DESIGNATOR_INVALID) {
_cleanup_free_ char *t = NULL, *o = NULL, *l = NULL;
_cleanup_free_ char *t = NULL, *o = NULL, *l = NULL, *n = NULL;
_cleanup_close_ int mount_node_fd = -EBADF;
const char *options = NULL;
@ -930,6 +961,10 @@ static int dissect_image(
return mount_node_fd;
}
r = make_partition_devname(devname, diskseq, nr, flags, &n);
if (r < 0)
return r;
if (fstype) {
t = strdup(fstype);
if (!t)
@ -955,7 +990,7 @@ static int dissect_image(
.rw = rw,
.growfs = growfs,
.architecture = type.arch,
.node = TAKE_PTR(node),
.node = TAKE_PTR(n),
.fstype = TAKE_PTR(t),
.label = TAKE_PTR(l),
.uuid = id,
@ -982,16 +1017,14 @@ static int dissect_image(
generic_nr = nr;
generic_rw = true;
generic_growfs = false;
generic_node = strdup(node);
if (!generic_node)
return -ENOMEM;
generic_node = TAKE_PTR(node);
}
break;
case 0xEA: { /* Boot Loader Spec extended $BOOT partition */
_cleanup_close_ int mount_node_fd = -EBADF;
_cleanup_free_ char *o = NULL;
_cleanup_free_ char *o = NULL, *n = NULL;
sd_id128_t id = SD_ID128_NULL;
const char *options = NULL;
@ -1007,6 +1040,10 @@ static int dissect_image(
(void) blkid_partition_get_uuid_id128(pp, &id);
r = make_partition_devname(devname, diskseq, nr, flags, &n);
if (r < 0)
return r;
options = mount_options_from_designator(mount_options, PARTITION_XBOOTLDR);
if (options) {
o = strdup(options);
@ -1020,7 +1057,7 @@ static int dissect_image(
.rw = true,
.growfs = false,
.architecture = _ARCHITECTURE_INVALID,
.node = TAKE_PTR(node),
.node = TAKE_PTR(n),
.uuid = id,
.mount_options = TAKE_PTR(o),
.mount_node_fd = TAKE_FD(mount_node_fd),
@ -1076,7 +1113,7 @@ static int dissect_image(
/* If we didn't find a generic node, then we can't fix this up either */
if (generic_node) {
_cleanup_close_ int mount_node_fd = -EBADF;
_cleanup_free_ char *o = NULL;
_cleanup_free_ char *o = NULL, *n = NULL;
const char *options;
if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
@ -1085,6 +1122,10 @@ static int dissect_image(
return mount_node_fd;
}
r = make_partition_devname(devname, diskseq, generic_nr, flags, &n);
if (r < 0)
return r;
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) {
o = strdup(options);
@ -1099,7 +1140,7 @@ static int dissect_image(
.growfs = generic_growfs,
.partno = generic_nr,
.architecture = _ARCHITECTURE_INVALID,
.node = TAKE_PTR(generic_node),
.node = TAKE_PTR(n),
.uuid = generic_uuid,
.mount_options = TAKE_PTR(o),
.mount_node_fd = TAKE_FD(mount_node_fd),

View File

@ -78,6 +78,7 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_ADD_PARTITION_DEVICES = 1 << 20, /* Create partition devices via BLKPG_ADD_PARTITION */
DISSECT_IMAGE_PIN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions and pin them by fd */
DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
DISSECT_IMAGE_DISKSEQ_DEVNODE = 1 << 23, /* Prefer /dev/disk/by-diskseq/… device nodes */
} DissectImageFlags;
struct DissectedImage {