1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2016 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/mount.h>
22 #include <sys/prctl.h>
25 #include "architecture.h"
26 #include "ask-password-api.h"
27 #include "blkid-util.h"
29 #include "crypt-util.h"
31 #include "device-nodes.h"
32 #include "dissect-image.h"
37 #include "hexdecoct.h"
38 #include "hostname-util.h"
39 #include "id128-util.h"
40 #include "linux-3.13/dm-ioctl.h"
41 #include "mount-util.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "raw-clone.h"
45 #include "signal-util.h"
46 #include "stat-util.h"
47 #include "stdio-util.h"
48 #include "string-table.h"
49 #include "string-util.h"
51 #include "udev-util.h"
52 #include "user-util.h"
53 #include "xattr-util.h"
55 int probe_filesystem(const char *node
, char **ret_fstype
) {
56 /* Try to find device content type and return it in *ret_fstype. If nothing is found,
57 * 0/NULL will be returned. -EUCLEAN will be returned for ambigous results, and an
58 * different error otherwise. */
61 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
66 b
= blkid_new_probe_from_filename(node
);
68 return -errno
?: -ENOMEM
;
70 blkid_probe_enable_superblocks(b
, 1);
71 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
74 r
= blkid_do_safeprobe(b
);
76 log_debug("No type detected on partition %s", node
);
80 log_debug("Results ambiguous for partition %s", node
);
84 return -errno
?: -EIO
;
86 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
107 int dissect_image(int fd
, const void *root_hash
, size_t root_hash_size
, DissectImageFlags flags
, DissectedImage
**ret
) {
110 sd_id128_t root_uuid
= SD_ID128_NULL
, verity_uuid
= SD_ID128_NULL
;
111 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
112 bool is_gpt
, is_mbr
, generic_rw
, multiple_generic
= false;
113 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
114 _cleanup_(dissected_image_unrefp
) DissectedImage
*m
= NULL
;
115 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
116 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
117 _cleanup_free_
char *generic_node
= NULL
;
118 sd_id128_t generic_uuid
= SD_ID128_NULL
;
119 const char *pttype
= NULL
;
120 struct udev_list_entry
*first
, *item
;
128 assert(root_hash
|| root_hash_size
== 0);
130 /* Probes a disk image, and returns information about what it found in *ret.
132 * Returns -ENOPKG if no suitable partition table or file system could be found.
133 * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
136 /* If a root hash is supplied, then we use the root partition that has a UUID that match the first
137 * 128bit of the root hash. And we use the verity partition that has a UUID that match the final
140 if (root_hash_size
< sizeof(sd_id128_t
))
143 memcpy(&root_uuid
, root_hash
, sizeof(sd_id128_t
));
144 memcpy(&verity_uuid
, (const uint8_t*) root_hash
+ root_hash_size
- sizeof(sd_id128_t
), sizeof(sd_id128_t
));
146 if (sd_id128_is_null(root_uuid
))
148 if (sd_id128_is_null(verity_uuid
))
152 if (fstat(fd
, &st
) < 0)
155 if (!S_ISBLK(st
.st_mode
))
158 b
= blkid_new_probe();
163 r
= blkid_probe_set_device(b
, fd
, 0, 0);
165 return -errno
?: -ENOMEM
;
167 if ((flags
& DISSECT_IMAGE_GPT_ONLY
) == 0) {
168 /* Look for file system superblocks, unless we only shall look for GPT partition tables */
169 blkid_probe_enable_superblocks(b
, 1);
170 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
|BLKID_SUBLKS_USAGE
);
173 blkid_probe_enable_partitions(b
, 1);
174 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
177 r
= blkid_do_safeprobe(b
);
178 if (IN_SET(r
, -2, 1)) {
179 log_debug("Failed to identify any partition table.");
183 return -errno
?: -EIO
;
185 m
= new0(DissectedImage
, 1);
189 if (!(flags
& DISSECT_IMAGE_GPT_ONLY
) &&
190 (flags
& DISSECT_IMAGE_REQUIRE_ROOT
)) {
191 const char *usage
= NULL
;
193 (void) blkid_probe_lookup_value(b
, "USAGE", &usage
, NULL
);
194 if (STRPTR_IN_SET(usage
, "filesystem", "crypto")) {
195 _cleanup_free_
char *t
= NULL
, *n
= NULL
;
196 const char *fstype
= NULL
;
198 /* OK, we have found a file system, that's our root partition then. */
199 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
207 if (asprintf(&n
, "/dev/block/%u:%u", major(st
.st_rdev
), minor(st
.st_rdev
)) < 0)
210 m
->partitions
[PARTITION_ROOT
] = (DissectedPartition
) {
214 .architecture
= _ARCHITECTURE_INVALID
,
221 m
->encrypted
= streq(fstype
, "crypto_LUKS");
230 (void) blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
234 is_gpt
= streq_ptr(pttype
, "gpt");
235 is_mbr
= streq_ptr(pttype
, "dos");
237 if (!is_gpt
&& ((flags
& DISSECT_IMAGE_GPT_ONLY
) || !is_mbr
))
241 pl
= blkid_probe_get_partitions(b
);
243 return -errno
?: -ENOMEM
;
249 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
257 log_debug("Kernel partitions never appeared.");
261 e
= udev_enumerate_new(udev
);
265 r
= udev_enumerate_add_match_parent(e
, d
);
269 r
= udev_enumerate_scan_devices(e
);
273 /* Count the partitions enumerated by the kernel */
275 first
= udev_enumerate_get_list_entry(e
);
276 udev_list_entry_foreach(item
, first
)
279 /* Count the partitions enumerated by blkid */
280 z
= blkid_partlist_numof_partitions(pl
);
284 log_debug("blkid and kernel partition list do not match.");
290 /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running
291 * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a
292 * synchronous call that waits until probing is complete. */
298 if (ioctl(fd
, BLKRRPART
, 0) < 0) {
302 struct loop_info64 info
;
304 /* If we are running on a loop device that has partition scanning off,
305 * return an explicit recognizable error about this, so that callers
306 * can generate a proper message explaining the situation. */
308 if (ioctl(fd
, LOOP_GET_STATUS64
, &info
) >= 0 && (info
.lo_flags
& LO_FLAGS_PARTSCAN
) == 0) {
309 log_debug("Device is loop device and partition scanning is off!");
310 return -EPROTONOSUPPORT
;
318 /* If something else has the device open, such as an udev rule, the ioctl will return
319 * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a
320 * bit, and try again.
322 * This is really something they should fix in the kernel! */
324 (void) usleep(50 * USEC_PER_MSEC
);
328 e
= udev_enumerate_unref(e
);
331 first
= udev_enumerate_get_list_entry(e
);
332 udev_list_entry_foreach(item
, first
) {
333 _cleanup_udev_device_unref_
struct udev_device
*q
;
334 unsigned long long pflags
;
336 const char *node
, *sysname
;
340 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
344 qn
= udev_device_get_devnum(q
);
348 if (st
.st_rdev
== qn
)
351 /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see
352 * https://github.com/systemd/systemd/issues/5806 */
353 sysname
= udev_device_get_sysname(q
);
354 if (sysname
&& startswith(sysname
, "mmcblk") && endswith(sysname
, "rpmb"))
357 node
= udev_device_get_devnode(q
);
361 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
365 pflags
= blkid_partition_get_flags(pp
);
367 nr
= blkid_partition_get_partno(pp
);
372 int designator
= _PARTITION_DESIGNATOR_INVALID
, architecture
= _ARCHITECTURE_INVALID
;
373 const char *stype
, *sid
, *fstype
= NULL
;
374 sd_id128_t type_id
, id
;
377 sid
= blkid_partition_get_uuid(pp
);
380 if (sd_id128_from_string(sid
, &id
) < 0)
383 stype
= blkid_partition_get_type_string(pp
);
386 if (sd_id128_from_string(stype
, &type_id
) < 0)
389 if (sd_id128_equal(type_id
, GPT_HOME
)) {
391 if (pflags
& GPT_FLAG_NO_AUTO
)
394 designator
= PARTITION_HOME
;
395 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
396 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
398 if (pflags
& GPT_FLAG_NO_AUTO
)
401 designator
= PARTITION_SRV
;
402 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
403 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
405 /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined
406 * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the
407 * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */
409 if (pflags
& GPT_FLAG_NO_BLOCK_IO_PROTOCOL
)
412 designator
= PARTITION_ESP
;
415 #ifdef GPT_ROOT_NATIVE
416 else if (sd_id128_equal(type_id
, GPT_ROOT_NATIVE
)) {
418 if (pflags
& GPT_FLAG_NO_AUTO
)
421 /* If a root ID is specified, ignore everything but the root id */
422 if (!sd_id128_is_null(root_uuid
) && !sd_id128_equal(root_uuid
, id
))
425 designator
= PARTITION_ROOT
;
426 architecture
= native_architecture();
427 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
428 } else if (sd_id128_equal(type_id
, GPT_ROOT_NATIVE_VERITY
)) {
430 if (pflags
& GPT_FLAG_NO_AUTO
)
433 m
->can_verity
= true;
435 /* Ignore verity unless a root hash is specified */
436 if (sd_id128_is_null(verity_uuid
) || !sd_id128_equal(verity_uuid
, id
))
439 designator
= PARTITION_ROOT_VERITY
;
440 fstype
= "DM_verity_hash";
441 architecture
= native_architecture();
445 #ifdef GPT_ROOT_SECONDARY
446 else if (sd_id128_equal(type_id
, GPT_ROOT_SECONDARY
)) {
448 if (pflags
& GPT_FLAG_NO_AUTO
)
451 /* If a root ID is specified, ignore everything but the root id */
452 if (!sd_id128_is_null(root_uuid
) && !sd_id128_equal(root_uuid
, id
))
455 designator
= PARTITION_ROOT_SECONDARY
;
456 architecture
= SECONDARY_ARCHITECTURE
;
457 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
458 } else if (sd_id128_equal(type_id
, GPT_ROOT_SECONDARY_VERITY
)) {
460 if (pflags
& GPT_FLAG_NO_AUTO
)
463 m
->can_verity
= true;
465 /* Ignore verity unless root has is specified */
466 if (sd_id128_is_null(verity_uuid
) || !sd_id128_equal(verity_uuid
, id
))
469 designator
= PARTITION_ROOT_SECONDARY_VERITY
;
470 fstype
= "DM_verity_hash";
471 architecture
= SECONDARY_ARCHITECTURE
;
475 else if (sd_id128_equal(type_id
, GPT_SWAP
)) {
477 if (pflags
& GPT_FLAG_NO_AUTO
)
480 designator
= PARTITION_SWAP
;
482 } else if (sd_id128_equal(type_id
, GPT_LINUX_GENERIC
)) {
484 if (pflags
& GPT_FLAG_NO_AUTO
)
488 multiple_generic
= true;
491 generic_rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
493 generic_node
= strdup(node
);
499 if (designator
!= _PARTITION_DESIGNATOR_INVALID
) {
500 _cleanup_free_
char *t
= NULL
, *n
= NULL
;
503 if (m
->partitions
[designator
].found
)
516 m
->partitions
[designator
] = (DissectedPartition
) {
520 .architecture
= architecture
,
531 if (pflags
!= 0x80) /* Bootable flag */
534 if (blkid_partition_get_type(pp
) != 0x83) /* Linux partition */
538 multiple_generic
= true;
542 generic_node
= strdup(node
);
549 if (!m
->partitions
[PARTITION_ROOT
].found
) {
550 /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
551 * either, then check if there's a single generic one, and use that. */
553 if (m
->partitions
[PARTITION_ROOT_VERITY
].found
)
554 return -EADDRNOTAVAIL
;
556 if (m
->partitions
[PARTITION_ROOT_SECONDARY
].found
) {
557 m
->partitions
[PARTITION_ROOT
] = m
->partitions
[PARTITION_ROOT_SECONDARY
];
558 zero(m
->partitions
[PARTITION_ROOT_SECONDARY
]);
560 m
->partitions
[PARTITION_ROOT_VERITY
] = m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
];
561 zero(m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
]);
563 } else if (flags
& DISSECT_IMAGE_REQUIRE_ROOT
) {
565 /* If the root has was set, then we won't fallback to a generic node, because the root hash
568 return -EADDRNOTAVAIL
;
570 /* If we didn't find a generic node, then we can't fix this up either */
574 /* If we didn't find a properly marked root partition, but we did find a single suitable
575 * generic Linux partition, then use this as root partition, if the caller asked for it. */
576 if (multiple_generic
)
579 m
->partitions
[PARTITION_ROOT
] = (DissectedPartition
) {
582 .partno
= generic_nr
,
583 .architecture
= _ARCHITECTURE_INVALID
,
584 .node
= generic_node
,
585 .uuid
= generic_uuid
,
593 if (!m
->partitions
[PARTITION_ROOT_VERITY
].found
|| !m
->partitions
[PARTITION_ROOT
].found
)
594 return -EADDRNOTAVAIL
;
596 /* If we found the primary root with the hash, then we definitely want to suppress any secondary root
597 * (which would be weird, after all the root hash should only be assigned to one pair of
599 m
->partitions
[PARTITION_ROOT_SECONDARY
].found
= false;
600 m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
].found
= false;
602 /* If we found a verity setup, then the root partition is necessarily read-only. */
603 m
->partitions
[PARTITION_ROOT
].rw
= false;
611 /* Fill in file system types if we don't know them yet. */
612 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
613 DissectedPartition
*p
= m
->partitions
+ i
;
618 if (!p
->fstype
&& p
->node
) {
619 r
= probe_filesystem(p
->node
, &p
->fstype
);
620 if (r
< 0 && r
!= -EUCLEAN
)
624 if (streq_ptr(p
->fstype
, "crypto_LUKS"))
627 if (p
->fstype
&& fstype_is_ro(p
->fstype
))
640 DissectedImage
* dissected_image_unref(DissectedImage
*m
) {
646 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
647 free(m
->partitions
[i
].fstype
);
648 free(m
->partitions
[i
].node
);
649 free(m
->partitions
[i
].decrypted_fstype
);
650 free(m
->partitions
[i
].decrypted_node
);
654 strv_free(m
->machine_info
);
655 strv_free(m
->os_release
);
660 static int is_loop_device(const char *path
) {
661 char s
[SYS_BLOCK_PATH_MAX("/../loop/")];
666 if (stat(path
, &st
) < 0)
669 if (!S_ISBLK(st
.st_mode
))
672 xsprintf_sys_block_path(s
, "/loop/", st
.st_dev
);
673 if (access(s
, F_OK
) < 0) {
677 /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */
678 xsprintf_sys_block_path(s
, "/../loop/", st
.st_dev
);
679 if (access(s
, F_OK
) < 0)
680 return errno
== ENOENT
? false : -errno
;
686 static int mount_partition(
687 DissectedPartition
*m
,
689 const char *directory
,
691 DissectImageFlags flags
) {
693 _cleanup_free_
char *chased
= NULL
, *options
= NULL
;
694 const char *p
, *node
, *fstype
;
701 node
= m
->decrypted_node
?: m
->node
;
702 fstype
= m
->decrypted_fstype
?: m
->fstype
;
704 if (!m
->found
|| !node
|| !fstype
)
707 /* Stacked encryption? Yuck */
708 if (streq_ptr(fstype
, "crypto_LUKS"))
711 rw
= m
->rw
&& !(flags
& DISSECT_IMAGE_READ_ONLY
);
714 r
= chase_symlinks(directory
, where
, CHASE_PREFIX_ROOT
, &chased
);
722 /* If requested, turn on discard support. */
723 if (fstype_can_discard(fstype
) &&
724 ((flags
& DISSECT_IMAGE_DISCARD
) ||
725 ((flags
& DISSECT_IMAGE_DISCARD_ON_LOOP
) && is_loop_device(m
->node
)))) {
726 options
= strdup("discard");
731 if (uid_is_valid(uid_shift
) && uid_shift
!= 0 && fstype_can_uid_gid(fstype
)) {
732 _cleanup_free_
char *uid_option
= NULL
;
734 if (asprintf(&uid_option
, "uid=" UID_FMT
",gid=" GID_FMT
, uid_shift
, (gid_t
) uid_shift
) < 0)
737 if (!strextend_with_separator(&options
, ",", uid_option
, NULL
))
741 return mount_verbose(LOG_DEBUG
, node
, p
, fstype
, MS_NODEV
|(rw
? 0 : MS_RDONLY
), options
);
744 int dissected_image_mount(DissectedImage
*m
, const char *where
, uid_t uid_shift
, DissectImageFlags flags
) {
750 if (!m
->partitions
[PARTITION_ROOT
].found
)
753 if ((flags
& DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY
) == 0) {
754 r
= mount_partition(m
->partitions
+ PARTITION_ROOT
, where
, NULL
, uid_shift
, flags
);
759 if ((flags
& DISSECT_IMAGE_MOUNT_ROOT_ONLY
))
762 r
= mount_partition(m
->partitions
+ PARTITION_HOME
, where
, "/home", uid_shift
, flags
);
766 r
= mount_partition(m
->partitions
+ PARTITION_SRV
, where
, "/srv", uid_shift
, flags
);
770 if (m
->partitions
[PARTITION_ESP
].found
) {
773 /* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */
775 FOREACH_STRING(mp
, "/efi", "/boot") {
776 _cleanup_free_
char *p
= NULL
;
778 r
= chase_symlinks(mp
, where
, CHASE_PREFIX_ROOT
, &p
);
784 r
= mount_partition(m
->partitions
+ PARTITION_ESP
, where
, mp
, uid_shift
, flags
);
794 #if HAVE_LIBCRYPTSETUP
795 typedef struct DecryptedPartition
{
796 struct crypt_device
*device
;
799 } DecryptedPartition
;
801 struct DecryptedImage
{
802 DecryptedPartition
*decrypted
;
808 DecryptedImage
* decrypted_image_unref(DecryptedImage
* d
) {
809 #if HAVE_LIBCRYPTSETUP
816 for (i
= 0; i
< d
->n_decrypted
; i
++) {
817 DecryptedPartition
*p
= d
->decrypted
+ i
;
819 if (p
->device
&& p
->name
&& !p
->relinquished
) {
820 r
= crypt_deactivate(p
->device
, p
->name
);
822 log_debug_errno(r
, "Failed to deactivate encrypted partition %s", p
->name
);
826 crypt_free(p
->device
);
835 #if HAVE_LIBCRYPTSETUP
837 static int make_dm_name_and_node(const void *original_node
, const char *suffix
, char **ret_name
, char **ret_node
) {
838 _cleanup_free_
char *name
= NULL
, *node
= NULL
;
841 assert(original_node
);
846 base
= strrchr(original_node
, '/');
853 name
= strjoin(base
, suffix
);
856 if (!filename_is_valid(name
))
859 node
= strjoin(crypt_get_dir(), "/", name
);
870 static int decrypt_partition(
871 DissectedPartition
*m
,
872 const char *passphrase
,
873 DissectImageFlags flags
,
876 _cleanup_free_
char *node
= NULL
, *name
= NULL
;
877 _cleanup_(crypt_freep
) struct crypt_device
*cd
= NULL
;
883 if (!m
->found
|| !m
->node
|| !m
->fstype
)
886 if (!streq(m
->fstype
, "crypto_LUKS"))
892 r
= make_dm_name_and_node(m
->node
, "-decrypted", &name
, &node
);
896 if (!GREEDY_REALLOC0(d
->decrypted
, d
->n_allocated
, d
->n_decrypted
+ 1))
899 r
= crypt_init(&cd
, m
->node
);
901 return log_debug_errno(r
, "Failed to initialize dm-crypt: %m");
903 r
= crypt_load(cd
, CRYPT_LUKS
, NULL
);
905 return log_debug_errno(r
, "Failed to load LUKS metadata: %m");
907 r
= crypt_activate_by_passphrase(cd
, name
, CRYPT_ANY_SLOT
, passphrase
, strlen(passphrase
),
908 ((flags
& DISSECT_IMAGE_READ_ONLY
) ? CRYPT_ACTIVATE_READONLY
: 0) |
909 ((flags
& DISSECT_IMAGE_DISCARD_ON_CRYPTO
) ? CRYPT_ACTIVATE_ALLOW_DISCARDS
: 0));
911 log_debug_errno(r
, "Failed to activate LUKS device: %m");
912 return r
== -EPERM
? -EKEYREJECTED
: r
;
915 d
->decrypted
[d
->n_decrypted
].name
= name
;
918 d
->decrypted
[d
->n_decrypted
].device
= cd
;
922 m
->decrypted_node
= node
;
928 static int verity_partition(
929 DissectedPartition
*m
,
930 DissectedPartition
*v
,
931 const void *root_hash
,
932 size_t root_hash_size
,
933 DissectImageFlags flags
,
936 _cleanup_free_
char *node
= NULL
, *name
= NULL
;
937 _cleanup_(crypt_freep
) struct crypt_device
*cd
= NULL
;
946 if (!m
->found
|| !m
->node
|| !m
->fstype
)
948 if (!v
->found
|| !v
->node
|| !v
->fstype
)
951 if (!streq(v
->fstype
, "DM_verity_hash"))
954 r
= make_dm_name_and_node(m
->node
, "-verity", &name
, &node
);
958 if (!GREEDY_REALLOC0(d
->decrypted
, d
->n_allocated
, d
->n_decrypted
+ 1))
961 r
= crypt_init(&cd
, v
->node
);
965 r
= crypt_load(cd
, CRYPT_VERITY
, NULL
);
969 r
= crypt_set_data_device(cd
, m
->node
);
973 r
= crypt_activate_by_volume_key(cd
, name
, root_hash
, root_hash_size
, CRYPT_ACTIVATE_READONLY
);
977 d
->decrypted
[d
->n_decrypted
].name
= name
;
980 d
->decrypted
[d
->n_decrypted
].device
= cd
;
984 m
->decrypted_node
= node
;
991 int dissected_image_decrypt(
993 const char *passphrase
,
994 const void *root_hash
,
995 size_t root_hash_size
,
996 DissectImageFlags flags
,
997 DecryptedImage
**ret
) {
999 #if HAVE_LIBCRYPTSETUP
1000 _cleanup_(decrypted_image_unrefp
) DecryptedImage
*d
= NULL
;
1006 assert(root_hash
|| root_hash_size
== 0);
1010 * = 0 → There was nothing to decrypt
1011 * > 0 → Decrypted successfully
1012 * -ENOKEY → There's something to decrypt but no key was supplied
1013 * -EKEYREJECTED → Passed key was not correct
1016 if (root_hash
&& root_hash_size
< sizeof(sd_id128_t
))
1019 if (!m
->encrypted
&& !m
->verity
) {
1024 #if HAVE_LIBCRYPTSETUP
1025 d
= new0(DecryptedImage
, 1);
1029 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
1030 DissectedPartition
*p
= m
->partitions
+ i
;
1036 r
= decrypt_partition(p
, passphrase
, flags
, d
);
1040 k
= PARTITION_VERITY_OF(i
);
1042 r
= verity_partition(p
, m
->partitions
+ k
, root_hash
, root_hash_size
, flags
, d
);
1047 if (!p
->decrypted_fstype
&& p
->decrypted_node
) {
1048 r
= probe_filesystem(p
->decrypted_node
, &p
->decrypted_fstype
);
1049 if (r
< 0 && r
!= -EUCLEAN
)
1063 int dissected_image_decrypt_interactively(
1065 const char *passphrase
,
1066 const void *root_hash
,
1067 size_t root_hash_size
,
1068 DissectImageFlags flags
,
1069 DecryptedImage
**ret
) {
1071 _cleanup_strv_free_erase_
char **z
= NULL
;
1078 r
= dissected_image_decrypt(m
, passphrase
, root_hash
, root_hash_size
, flags
, ret
);
1081 if (r
== -EKEYREJECTED
)
1082 log_error_errno(r
, "Incorrect passphrase, try again!");
1083 else if (r
!= -ENOKEY
) {
1084 log_error_errno(r
, "Failed to decrypt image: %m");
1089 log_error("Too many retries.");
1090 return -EKEYREJECTED
;
1095 r
= ask_password_auto("Please enter image passphrase!", NULL
, "dissect", "dissect", USEC_INFINITY
, 0, &z
);
1097 return log_error_errno(r
, "Failed to query for passphrase: %m");
1103 #if HAVE_LIBCRYPTSETUP
1104 static int deferred_remove(DecryptedPartition
*p
) {
1106 struct dm_ioctl dm
= {
1110 DM_VERSION_PATCHLEVEL
1112 .data_size
= sizeof(dm
),
1113 .flags
= DM_DEFERRED_REMOVE
,
1116 _cleanup_close_
int fd
= -1;
1120 /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
1122 fd
= open("/dev/mapper/control", O_RDWR
|O_CLOEXEC
);
1126 strncpy(dm
.name
, p
->name
, sizeof(dm
.name
));
1128 if (ioctl(fd
, DM_DEV_REMOVE
, &dm
))
1135 int decrypted_image_relinquish(DecryptedImage
*d
) {
1137 #if HAVE_LIBCRYPTSETUP
1144 /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
1145 * that we don't clean it up ourselves either anymore */
1147 #if HAVE_LIBCRYPTSETUP
1148 for (i
= 0; i
< d
->n_decrypted
; i
++) {
1149 DecryptedPartition
*p
= d
->decrypted
+ i
;
1151 if (p
->relinquished
)
1154 r
= deferred_remove(p
);
1156 return log_debug_errno(r
, "Failed to mark %s for auto-removal: %m", p
->name
);
1158 p
->relinquished
= true;
1165 int root_hash_load(const char *image
, void **ret
, size_t *ret_size
) {
1166 _cleanup_free_
char *text
= NULL
;
1167 _cleanup_free_
void *k
= NULL
;
1175 if (is_device_path(image
)) {
1176 /* If we are asked to load the root hash for a device node, exit early */
1182 r
= getxattr_malloc(image
, "user.verity.roothash", &text
, true);
1186 if (!IN_SET(r
, -ENODATA
, -EOPNOTSUPP
, -ENOENT
))
1189 fn
= newa(char, strlen(image
) + STRLEN(".roothash") + 1);
1190 n
= stpcpy(fn
, image
);
1191 e
= endswith(fn
, ".raw");
1195 strcpy(n
, ".roothash");
1197 r
= read_one_line_file(fn
, &text
);
1207 r
= unhexmem(text
, strlen(text
), &k
, &l
);
1210 if (l
< sizeof(sd_id128_t
))
1221 int dissected_image_acquire_metadata(DissectedImage
*m
) {
1231 static const char *const paths
[_META_MAX
] = {
1232 [META_HOSTNAME
] = "/etc/hostname\0",
1233 [META_MACHINE_ID
] = "/etc/machine-id\0",
1234 [META_MACHINE_INFO
] = "/etc/machine-info\0",
1235 [META_OS_RELEASE
] = "/etc/os-release\0/usr/lib/os-release\0",
1238 _cleanup_strv_free_
char **machine_info
= NULL
, **os_release
= NULL
;
1239 _cleanup_(rmdir_and_freep
) char *t
= NULL
;
1240 _cleanup_(sigkill_waitp
) pid_t child
= 0;
1241 sd_id128_t machine_id
= SD_ID128_NULL
;
1242 _cleanup_free_
char *hostname
= NULL
;
1243 unsigned n_meta_initialized
= 0, k
;
1244 int fds
[2 * _META_MAX
], r
;
1247 BLOCK_SIGNALS(SIGCHLD
);
1251 for (; n_meta_initialized
< _META_MAX
; n_meta_initialized
++)
1252 if (pipe2(fds
+ 2*n_meta_initialized
, O_CLOEXEC
) < 0) {
1257 r
= mkdtemp_malloc("/tmp/dissect-XXXXXX", &t
);
1261 child
= raw_clone(SIGCHLD
|CLONE_NEWNS
);
1269 (void) reset_all_signal_handlers();
1270 (void) reset_signal_mask();
1271 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
1273 /* Make sure we never propagate to the host */
1274 if (mount(NULL
, "/", NULL
, MS_SLAVE
| MS_REC
, NULL
) < 0)
1275 _exit(EXIT_FAILURE
);
1277 r
= dissected_image_mount(m
, t
, UID_INVALID
, DISSECT_IMAGE_READ_ONLY
);
1279 _exit(EXIT_FAILURE
);
1281 for (k
= 0; k
< _META_MAX
; k
++) {
1282 _cleanup_close_
int fd
= -1;
1285 fds
[2*k
] = safe_close(fds
[2*k
]);
1287 NULSTR_FOREACH(p
, paths
[k
]) {
1288 _cleanup_free_
char *q
= NULL
;
1290 r
= chase_symlinks(p
, t
, CHASE_PREFIX_ROOT
, &q
);
1294 fd
= open(q
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1301 r
= copy_bytes(fd
, fds
[2*k
+1], (uint64_t) -1, 0);
1303 _exit(EXIT_FAILURE
);
1305 fds
[2*k
+1] = safe_close(fds
[2*k
+1]);
1308 _exit(EXIT_SUCCESS
);
1311 for (k
= 0; k
< _META_MAX
; k
++) {
1312 _cleanup_fclose_
FILE *f
= NULL
;
1314 fds
[2*k
+1] = safe_close(fds
[2*k
+1]);
1316 f
= fdopen(fds
[2*k
], "re");
1327 r
= read_etc_hostname_stream(f
, &hostname
);
1329 log_debug_errno(r
, "Failed to read /etc/hostname: %m");
1333 case META_MACHINE_ID
: {
1334 _cleanup_free_
char *line
= NULL
;
1336 r
= read_line(f
, LONG_LINE_MAX
, &line
);
1338 log_debug_errno(r
, "Failed to read /etc/machine-id: %m");
1340 r
= sd_id128_from_string(line
, &machine_id
);
1342 log_debug_errno(r
, "Image contains invalid /etc/machine-id: %s", line
);
1344 log_debug("/etc/machine-id file is empty.");
1346 log_debug("/etc/machine-id has unexpected length %i.", r
);
1351 case META_MACHINE_INFO
:
1352 r
= load_env_file_pairs(f
, "machine-info", NULL
, &machine_info
);
1354 log_debug_errno(r
, "Failed to read /etc/machine-info: %m");
1358 case META_OS_RELEASE
:
1359 r
= load_env_file_pairs(f
, "os-release", NULL
, &os_release
);
1361 log_debug_errno(r
, "Failed to read OS release file: %m");
1367 r
= wait_for_terminate(child
, &si
);
1372 if (si
.si_code
!= CLD_EXITED
|| si
.si_status
!= EXIT_SUCCESS
) {
1377 free_and_replace(m
->hostname
, hostname
);
1378 m
->machine_id
= machine_id
;
1379 strv_free_and_replace(m
->machine_info
, machine_info
);
1380 strv_free_and_replace(m
->os_release
, os_release
);
1383 for (k
= 0; k
< n_meta_initialized
; k
++)
1384 safe_close_pair(fds
+ 2*k
);
1389 static const char *const partition_designator_table
[] = {
1390 [PARTITION_ROOT
] = "root",
1391 [PARTITION_ROOT_SECONDARY
] = "root-secondary",
1392 [PARTITION_HOME
] = "home",
1393 [PARTITION_SRV
] = "srv",
1394 [PARTITION_ESP
] = "esp",
1395 [PARTITION_SWAP
] = "swap",
1396 [PARTITION_ROOT_VERITY
] = "root-verity",
1397 [PARTITION_ROOT_SECONDARY_VERITY
] = "root-secondary-verity",
1400 DEFINE_STRING_TABLE_LOOKUP(partition_designator
, int);