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>
27 #include "architecture.h"
28 #include "ask-password-api.h"
29 #include "blkid-util.h"
30 #include "blockdev-util.h"
32 #include "crypt-util.h"
34 #include "device-nodes.h"
35 #include "dissect-image.h"
40 #include "hexdecoct.h"
41 #include "hostname-util.h"
42 #include "id128-util.h"
43 #include "linux-3.13/dm-ioctl.h"
45 #include "mount-util.h"
46 #include "path-util.h"
47 #include "process-util.h"
48 #include "raw-clone.h"
49 #include "signal-util.h"
50 #include "stat-util.h"
51 #include "stdio-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
55 #include "udev-util.h"
56 #include "user-util.h"
57 #include "xattr-util.h"
59 int probe_filesystem(const char *node
, char **ret_fstype
) {
60 /* Try to find device content type and return it in *ret_fstype. If nothing is found,
61 * 0/NULL will be returned. -EUCLEAN will be returned for ambigous results, and an
62 * different error otherwise. */
65 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
70 b
= blkid_new_probe_from_filename(node
);
72 return -errno
?: -ENOMEM
;
74 blkid_probe_enable_superblocks(b
, 1);
75 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
78 r
= blkid_do_safeprobe(b
);
80 log_debug("No type detected on partition %s", node
);
84 log_debug("Results ambiguous for partition %s", node
);
88 return -errno
?: -EIO
;
90 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
111 int dissect_image(int fd
, const void *root_hash
, size_t root_hash_size
, DissectImageFlags flags
, DissectedImage
**ret
) {
114 sd_id128_t root_uuid
= SD_ID128_NULL
, verity_uuid
= SD_ID128_NULL
;
115 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
116 bool is_gpt
, is_mbr
, generic_rw
, multiple_generic
= false;
117 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
118 _cleanup_(dissected_image_unrefp
) DissectedImage
*m
= NULL
;
119 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
120 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
121 _cleanup_free_
char *generic_node
= NULL
;
122 sd_id128_t generic_uuid
= SD_ID128_NULL
;
123 const char *pttype
= NULL
;
124 struct udev_list_entry
*first
, *item
;
132 assert(root_hash
|| root_hash_size
== 0);
134 /* Probes a disk image, and returns information about what it found in *ret.
136 * Returns -ENOPKG if no suitable partition table or file system could be found.
137 * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
140 /* If a root hash is supplied, then we use the root partition that has a UUID that match the first
141 * 128bit of the root hash. And we use the verity partition that has a UUID that match the final
144 if (root_hash_size
< sizeof(sd_id128_t
))
147 memcpy(&root_uuid
, root_hash
, sizeof(sd_id128_t
));
148 memcpy(&verity_uuid
, (const uint8_t*) root_hash
+ root_hash_size
- sizeof(sd_id128_t
), sizeof(sd_id128_t
));
150 if (sd_id128_is_null(root_uuid
))
152 if (sd_id128_is_null(verity_uuid
))
156 if (fstat(fd
, &st
) < 0)
159 if (!S_ISBLK(st
.st_mode
))
162 b
= blkid_new_probe();
167 r
= blkid_probe_set_device(b
, fd
, 0, 0);
169 return -errno
?: -ENOMEM
;
171 if ((flags
& DISSECT_IMAGE_GPT_ONLY
) == 0) {
172 /* Look for file system superblocks, unless we only shall look for GPT partition tables */
173 blkid_probe_enable_superblocks(b
, 1);
174 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
|BLKID_SUBLKS_USAGE
);
177 blkid_probe_enable_partitions(b
, 1);
178 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
181 r
= blkid_do_safeprobe(b
);
182 if (IN_SET(r
, -2, 1)) {
183 log_debug("Failed to identify any partition table.");
187 return -errno
?: -EIO
;
189 m
= new0(DissectedImage
, 1);
193 if (!(flags
& DISSECT_IMAGE_GPT_ONLY
) &&
194 (flags
& DISSECT_IMAGE_REQUIRE_ROOT
)) {
195 const char *usage
= NULL
;
197 (void) blkid_probe_lookup_value(b
, "USAGE", &usage
, NULL
);
198 if (STRPTR_IN_SET(usage
, "filesystem", "crypto")) {
199 _cleanup_free_
char *t
= NULL
, *n
= NULL
;
200 const char *fstype
= NULL
;
202 /* OK, we have found a file system, that's our root partition then. */
203 (void) blkid_probe_lookup_value(b
, "TYPE", &fstype
, NULL
);
211 if (asprintf(&n
, "/dev/block/%u:%u", major(st
.st_rdev
), minor(st
.st_rdev
)) < 0)
214 m
->partitions
[PARTITION_ROOT
] = (DissectedPartition
) {
218 .architecture
= _ARCHITECTURE_INVALID
,
225 m
->encrypted
= streq(fstype
, "crypto_LUKS");
234 (void) blkid_probe_lookup_value(b
, "PTTYPE", &pttype
, NULL
);
238 is_gpt
= streq_ptr(pttype
, "gpt");
239 is_mbr
= streq_ptr(pttype
, "dos");
241 if (!is_gpt
&& ((flags
& DISSECT_IMAGE_GPT_ONLY
) || !is_mbr
))
245 pl
= blkid_probe_get_partitions(b
);
247 return -errno
?: -ENOMEM
;
253 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
261 log_debug("Kernel partitions never appeared.");
265 e
= udev_enumerate_new(udev
);
269 r
= udev_enumerate_add_match_parent(e
, d
);
273 r
= udev_enumerate_scan_devices(e
);
277 /* Count the partitions enumerated by the kernel */
279 first
= udev_enumerate_get_list_entry(e
);
280 udev_list_entry_foreach(item
, first
)
283 /* Count the partitions enumerated by blkid */
284 z
= blkid_partlist_numof_partitions(pl
);
288 log_debug("blkid and kernel partition list do not match.");
294 /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running
295 * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a
296 * synchronous call that waits until probing is complete. */
302 if (ioctl(fd
, BLKRRPART
, 0) < 0) {
306 struct loop_info64 info
;
308 /* If we are running on a loop device that has partition scanning off,
309 * return an explicit recognizable error about this, so that callers
310 * can generate a proper message explaining the situation. */
312 if (ioctl(fd
, LOOP_GET_STATUS64
, &info
) >= 0 && (info
.lo_flags
& LO_FLAGS_PARTSCAN
) == 0) {
313 log_debug("Device is loop device and partition scanning is off!");
314 return -EPROTONOSUPPORT
;
322 /* If something else has the device open, such as an udev rule, the ioctl will return
323 * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a
324 * bit, and try again.
326 * This is really something they should fix in the kernel! */
328 (void) usleep(50 * USEC_PER_MSEC
);
332 e
= udev_enumerate_unref(e
);
335 first
= udev_enumerate_get_list_entry(e
);
336 udev_list_entry_foreach(item
, first
) {
337 _cleanup_udev_device_unref_
struct udev_device
*q
;
338 unsigned long long pflags
;
340 const char *node
, *sysname
;
344 q
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
348 qn
= udev_device_get_devnum(q
);
352 if (st
.st_rdev
== qn
)
355 /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see
356 * https://github.com/systemd/systemd/issues/5806 */
357 sysname
= udev_device_get_sysname(q
);
358 if (sysname
&& startswith(sysname
, "mmcblk") && endswith(sysname
, "rpmb"))
361 node
= udev_device_get_devnode(q
);
365 pp
= blkid_partlist_devno_to_partition(pl
, qn
);
369 pflags
= blkid_partition_get_flags(pp
);
371 nr
= blkid_partition_get_partno(pp
);
376 int designator
= _PARTITION_DESIGNATOR_INVALID
, architecture
= _ARCHITECTURE_INVALID
;
377 const char *stype
, *sid
, *fstype
= NULL
;
378 sd_id128_t type_id
, id
;
381 sid
= blkid_partition_get_uuid(pp
);
384 if (sd_id128_from_string(sid
, &id
) < 0)
387 stype
= blkid_partition_get_type_string(pp
);
390 if (sd_id128_from_string(stype
, &type_id
) < 0)
393 if (sd_id128_equal(type_id
, GPT_HOME
)) {
395 if (pflags
& GPT_FLAG_NO_AUTO
)
398 designator
= PARTITION_HOME
;
399 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
400 } else if (sd_id128_equal(type_id
, GPT_SRV
)) {
402 if (pflags
& GPT_FLAG_NO_AUTO
)
405 designator
= PARTITION_SRV
;
406 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
407 } else if (sd_id128_equal(type_id
, GPT_ESP
)) {
409 /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined
410 * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the
411 * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */
413 if (pflags
& GPT_FLAG_NO_BLOCK_IO_PROTOCOL
)
416 designator
= PARTITION_ESP
;
419 #ifdef GPT_ROOT_NATIVE
420 else if (sd_id128_equal(type_id
, GPT_ROOT_NATIVE
)) {
422 if (pflags
& GPT_FLAG_NO_AUTO
)
425 /* If a root ID is specified, ignore everything but the root id */
426 if (!sd_id128_is_null(root_uuid
) && !sd_id128_equal(root_uuid
, id
))
429 designator
= PARTITION_ROOT
;
430 architecture
= native_architecture();
431 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
432 } else if (sd_id128_equal(type_id
, GPT_ROOT_NATIVE_VERITY
)) {
434 if (pflags
& GPT_FLAG_NO_AUTO
)
437 m
->can_verity
= true;
439 /* Ignore verity unless a root hash is specified */
440 if (sd_id128_is_null(verity_uuid
) || !sd_id128_equal(verity_uuid
, id
))
443 designator
= PARTITION_ROOT_VERITY
;
444 fstype
= "DM_verity_hash";
445 architecture
= native_architecture();
449 #ifdef GPT_ROOT_SECONDARY
450 else if (sd_id128_equal(type_id
, GPT_ROOT_SECONDARY
)) {
452 if (pflags
& GPT_FLAG_NO_AUTO
)
455 /* If a root ID is specified, ignore everything but the root id */
456 if (!sd_id128_is_null(root_uuid
) && !sd_id128_equal(root_uuid
, id
))
459 designator
= PARTITION_ROOT_SECONDARY
;
460 architecture
= SECONDARY_ARCHITECTURE
;
461 rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
462 } else if (sd_id128_equal(type_id
, GPT_ROOT_SECONDARY_VERITY
)) {
464 if (pflags
& GPT_FLAG_NO_AUTO
)
467 m
->can_verity
= true;
469 /* Ignore verity unless root has is specified */
470 if (sd_id128_is_null(verity_uuid
) || !sd_id128_equal(verity_uuid
, id
))
473 designator
= PARTITION_ROOT_SECONDARY_VERITY
;
474 fstype
= "DM_verity_hash";
475 architecture
= SECONDARY_ARCHITECTURE
;
479 else if (sd_id128_equal(type_id
, GPT_SWAP
)) {
481 if (pflags
& GPT_FLAG_NO_AUTO
)
484 designator
= PARTITION_SWAP
;
486 } else if (sd_id128_equal(type_id
, GPT_LINUX_GENERIC
)) {
488 if (pflags
& GPT_FLAG_NO_AUTO
)
492 multiple_generic
= true;
495 generic_rw
= !(pflags
& GPT_FLAG_READ_ONLY
);
497 generic_node
= strdup(node
);
503 if (designator
!= _PARTITION_DESIGNATOR_INVALID
) {
504 _cleanup_free_
char *t
= NULL
, *n
= NULL
;
507 if (m
->partitions
[designator
].found
)
520 m
->partitions
[designator
] = (DissectedPartition
) {
524 .architecture
= architecture
,
535 if (pflags
!= 0x80) /* Bootable flag */
538 if (blkid_partition_get_type(pp
) != 0x83) /* Linux partition */
542 multiple_generic
= true;
546 generic_node
= strdup(node
);
553 if (!m
->partitions
[PARTITION_ROOT
].found
) {
554 /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
555 * either, then check if there's a single generic one, and use that. */
557 if (m
->partitions
[PARTITION_ROOT_VERITY
].found
)
558 return -EADDRNOTAVAIL
;
560 if (m
->partitions
[PARTITION_ROOT_SECONDARY
].found
) {
561 m
->partitions
[PARTITION_ROOT
] = m
->partitions
[PARTITION_ROOT_SECONDARY
];
562 zero(m
->partitions
[PARTITION_ROOT_SECONDARY
]);
564 m
->partitions
[PARTITION_ROOT_VERITY
] = m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
];
565 zero(m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
]);
567 } else if (flags
& DISSECT_IMAGE_REQUIRE_ROOT
) {
569 /* If the root has was set, then we won't fallback to a generic node, because the root hash
572 return -EADDRNOTAVAIL
;
574 /* If we didn't find a generic node, then we can't fix this up either */
578 /* If we didn't find a properly marked root partition, but we did find a single suitable
579 * generic Linux partition, then use this as root partition, if the caller asked for it. */
580 if (multiple_generic
)
583 m
->partitions
[PARTITION_ROOT
] = (DissectedPartition
) {
586 .partno
= generic_nr
,
587 .architecture
= _ARCHITECTURE_INVALID
,
588 .node
= generic_node
,
589 .uuid
= generic_uuid
,
597 if (!m
->partitions
[PARTITION_ROOT_VERITY
].found
|| !m
->partitions
[PARTITION_ROOT
].found
)
598 return -EADDRNOTAVAIL
;
600 /* If we found the primary root with the hash, then we definitely want to suppress any secondary root
601 * (which would be weird, after all the root hash should only be assigned to one pair of
603 m
->partitions
[PARTITION_ROOT_SECONDARY
].found
= false;
604 m
->partitions
[PARTITION_ROOT_SECONDARY_VERITY
].found
= false;
606 /* If we found a verity setup, then the root partition is necessarily read-only. */
607 m
->partitions
[PARTITION_ROOT
].rw
= false;
615 /* Fill in file system types if we don't know them yet. */
616 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
617 DissectedPartition
*p
= m
->partitions
+ i
;
622 if (!p
->fstype
&& p
->node
) {
623 r
= probe_filesystem(p
->node
, &p
->fstype
);
624 if (r
< 0 && r
!= -EUCLEAN
)
628 if (streq_ptr(p
->fstype
, "crypto_LUKS"))
631 if (p
->fstype
&& fstype_is_ro(p
->fstype
))
644 DissectedImage
* dissected_image_unref(DissectedImage
*m
) {
650 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
651 free(m
->partitions
[i
].fstype
);
652 free(m
->partitions
[i
].node
);
653 free(m
->partitions
[i
].decrypted_fstype
);
654 free(m
->partitions
[i
].decrypted_node
);
658 strv_free(m
->machine_info
);
659 strv_free(m
->os_release
);
664 static int is_loop_device(const char *path
) {
665 char s
[SYS_BLOCK_PATH_MAX("/../loop/")];
670 if (stat(path
, &st
) < 0)
673 if (!S_ISBLK(st
.st_mode
))
676 xsprintf_sys_block_path(s
, "/loop/", st
.st_dev
);
677 if (access(s
, F_OK
) < 0) {
681 /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */
682 xsprintf_sys_block_path(s
, "/../loop/", st
.st_dev
);
683 if (access(s
, F_OK
) < 0)
684 return errno
== ENOENT
? false : -errno
;
690 static int mount_partition(
691 DissectedPartition
*m
,
693 const char *directory
,
695 DissectImageFlags flags
) {
697 _cleanup_free_
char *chased
= NULL
, *options
= NULL
;
698 const char *p
, *node
, *fstype
;
705 node
= m
->decrypted_node
?: m
->node
;
706 fstype
= m
->decrypted_fstype
?: m
->fstype
;
708 if (!m
->found
|| !node
|| !fstype
)
711 /* Stacked encryption? Yuck */
712 if (streq_ptr(fstype
, "crypto_LUKS"))
715 rw
= m
->rw
&& !(flags
& DISSECT_IMAGE_READ_ONLY
);
718 r
= chase_symlinks(directory
, where
, CHASE_PREFIX_ROOT
, &chased
);
726 /* If requested, turn on discard support. */
727 if (fstype_can_discard(fstype
) &&
728 ((flags
& DISSECT_IMAGE_DISCARD
) ||
729 ((flags
& DISSECT_IMAGE_DISCARD_ON_LOOP
) && is_loop_device(m
->node
)))) {
730 options
= strdup("discard");
735 if (uid_is_valid(uid_shift
) && uid_shift
!= 0 && fstype_can_uid_gid(fstype
)) {
736 _cleanup_free_
char *uid_option
= NULL
;
738 if (asprintf(&uid_option
, "uid=" UID_FMT
",gid=" GID_FMT
, uid_shift
, (gid_t
) uid_shift
) < 0)
741 if (!strextend_with_separator(&options
, ",", uid_option
, NULL
))
745 return mount_verbose(LOG_DEBUG
, node
, p
, fstype
, MS_NODEV
|(rw
? 0 : MS_RDONLY
), options
);
748 int dissected_image_mount(DissectedImage
*m
, const char *where
, uid_t uid_shift
, DissectImageFlags flags
) {
754 if (!m
->partitions
[PARTITION_ROOT
].found
)
757 if ((flags
& DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY
) == 0) {
758 r
= mount_partition(m
->partitions
+ PARTITION_ROOT
, where
, NULL
, uid_shift
, flags
);
763 if ((flags
& DISSECT_IMAGE_MOUNT_ROOT_ONLY
))
766 r
= mount_partition(m
->partitions
+ PARTITION_HOME
, where
, "/home", uid_shift
, flags
);
770 r
= mount_partition(m
->partitions
+ PARTITION_SRV
, where
, "/srv", uid_shift
, flags
);
774 if (m
->partitions
[PARTITION_ESP
].found
) {
777 /* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */
779 FOREACH_STRING(mp
, "/efi", "/boot") {
780 _cleanup_free_
char *p
= NULL
;
782 r
= chase_symlinks(mp
, where
, CHASE_PREFIX_ROOT
, &p
);
788 r
= mount_partition(m
->partitions
+ PARTITION_ESP
, where
, mp
, uid_shift
, flags
);
798 #if HAVE_LIBCRYPTSETUP
799 typedef struct DecryptedPartition
{
800 struct crypt_device
*device
;
803 } DecryptedPartition
;
805 struct DecryptedImage
{
806 DecryptedPartition
*decrypted
;
812 DecryptedImage
* decrypted_image_unref(DecryptedImage
* d
) {
813 #if HAVE_LIBCRYPTSETUP
820 for (i
= 0; i
< d
->n_decrypted
; i
++) {
821 DecryptedPartition
*p
= d
->decrypted
+ i
;
823 if (p
->device
&& p
->name
&& !p
->relinquished
) {
824 r
= crypt_deactivate(p
->device
, p
->name
);
826 log_debug_errno(r
, "Failed to deactivate encrypted partition %s", p
->name
);
830 crypt_free(p
->device
);
839 #if HAVE_LIBCRYPTSETUP
841 static int make_dm_name_and_node(const void *original_node
, const char *suffix
, char **ret_name
, char **ret_node
) {
842 _cleanup_free_
char *name
= NULL
, *node
= NULL
;
845 assert(original_node
);
850 base
= strrchr(original_node
, '/');
857 name
= strjoin(base
, suffix
);
860 if (!filename_is_valid(name
))
863 node
= strjoin(crypt_get_dir(), "/", name
);
874 static int decrypt_partition(
875 DissectedPartition
*m
,
876 const char *passphrase
,
877 DissectImageFlags flags
,
880 _cleanup_free_
char *node
= NULL
, *name
= NULL
;
881 _cleanup_(crypt_freep
) struct crypt_device
*cd
= NULL
;
887 if (!m
->found
|| !m
->node
|| !m
->fstype
)
890 if (!streq(m
->fstype
, "crypto_LUKS"))
896 r
= make_dm_name_and_node(m
->node
, "-decrypted", &name
, &node
);
900 if (!GREEDY_REALLOC0(d
->decrypted
, d
->n_allocated
, d
->n_decrypted
+ 1))
903 r
= crypt_init(&cd
, m
->node
);
905 return log_debug_errno(r
, "Failed to initialize dm-crypt: %m");
907 r
= crypt_load(cd
, CRYPT_LUKS
, NULL
);
909 return log_debug_errno(r
, "Failed to load LUKS metadata: %m");
911 r
= crypt_activate_by_passphrase(cd
, name
, CRYPT_ANY_SLOT
, passphrase
, strlen(passphrase
),
912 ((flags
& DISSECT_IMAGE_READ_ONLY
) ? CRYPT_ACTIVATE_READONLY
: 0) |
913 ((flags
& DISSECT_IMAGE_DISCARD_ON_CRYPTO
) ? CRYPT_ACTIVATE_ALLOW_DISCARDS
: 0));
915 log_debug_errno(r
, "Failed to activate LUKS device: %m");
916 return r
== -EPERM
? -EKEYREJECTED
: r
;
919 d
->decrypted
[d
->n_decrypted
].name
= name
;
922 d
->decrypted
[d
->n_decrypted
].device
= cd
;
926 m
->decrypted_node
= node
;
932 static int verity_partition(
933 DissectedPartition
*m
,
934 DissectedPartition
*v
,
935 const void *root_hash
,
936 size_t root_hash_size
,
937 DissectImageFlags flags
,
940 _cleanup_free_
char *node
= NULL
, *name
= NULL
;
941 _cleanup_(crypt_freep
) struct crypt_device
*cd
= NULL
;
950 if (!m
->found
|| !m
->node
|| !m
->fstype
)
952 if (!v
->found
|| !v
->node
|| !v
->fstype
)
955 if (!streq(v
->fstype
, "DM_verity_hash"))
958 r
= make_dm_name_and_node(m
->node
, "-verity", &name
, &node
);
962 if (!GREEDY_REALLOC0(d
->decrypted
, d
->n_allocated
, d
->n_decrypted
+ 1))
965 r
= crypt_init(&cd
, v
->node
);
969 r
= crypt_load(cd
, CRYPT_VERITY
, NULL
);
973 r
= crypt_set_data_device(cd
, m
->node
);
977 r
= crypt_activate_by_volume_key(cd
, name
, root_hash
, root_hash_size
, CRYPT_ACTIVATE_READONLY
);
981 d
->decrypted
[d
->n_decrypted
].name
= name
;
984 d
->decrypted
[d
->n_decrypted
].device
= cd
;
988 m
->decrypted_node
= node
;
995 int dissected_image_decrypt(
997 const char *passphrase
,
998 const void *root_hash
,
999 size_t root_hash_size
,
1000 DissectImageFlags flags
,
1001 DecryptedImage
**ret
) {
1003 #if HAVE_LIBCRYPTSETUP
1004 _cleanup_(decrypted_image_unrefp
) DecryptedImage
*d
= NULL
;
1010 assert(root_hash
|| root_hash_size
== 0);
1014 * = 0 → There was nothing to decrypt
1015 * > 0 → Decrypted successfully
1016 * -ENOKEY → There's something to decrypt but no key was supplied
1017 * -EKEYREJECTED → Passed key was not correct
1020 if (root_hash
&& root_hash_size
< sizeof(sd_id128_t
))
1023 if (!m
->encrypted
&& !m
->verity
) {
1028 #if HAVE_LIBCRYPTSETUP
1029 d
= new0(DecryptedImage
, 1);
1033 for (i
= 0; i
< _PARTITION_DESIGNATOR_MAX
; i
++) {
1034 DissectedPartition
*p
= m
->partitions
+ i
;
1040 r
= decrypt_partition(p
, passphrase
, flags
, d
);
1044 k
= PARTITION_VERITY_OF(i
);
1046 r
= verity_partition(p
, m
->partitions
+ k
, root_hash
, root_hash_size
, flags
, d
);
1051 if (!p
->decrypted_fstype
&& p
->decrypted_node
) {
1052 r
= probe_filesystem(p
->decrypted_node
, &p
->decrypted_fstype
);
1053 if (r
< 0 && r
!= -EUCLEAN
)
1067 int dissected_image_decrypt_interactively(
1069 const char *passphrase
,
1070 const void *root_hash
,
1071 size_t root_hash_size
,
1072 DissectImageFlags flags
,
1073 DecryptedImage
**ret
) {
1075 _cleanup_strv_free_erase_
char **z
= NULL
;
1082 r
= dissected_image_decrypt(m
, passphrase
, root_hash
, root_hash_size
, flags
, ret
);
1085 if (r
== -EKEYREJECTED
)
1086 log_error_errno(r
, "Incorrect passphrase, try again!");
1087 else if (r
!= -ENOKEY
) {
1088 log_error_errno(r
, "Failed to decrypt image: %m");
1093 log_error("Too many retries.");
1094 return -EKEYREJECTED
;
1099 r
= ask_password_auto("Please enter image passphrase!", NULL
, "dissect", "dissect", USEC_INFINITY
, 0, &z
);
1101 return log_error_errno(r
, "Failed to query for passphrase: %m");
1107 #if HAVE_LIBCRYPTSETUP
1108 static int deferred_remove(DecryptedPartition
*p
) {
1110 struct dm_ioctl dm
= {
1114 DM_VERSION_PATCHLEVEL
1116 .data_size
= sizeof(dm
),
1117 .flags
= DM_DEFERRED_REMOVE
,
1120 _cleanup_close_
int fd
= -1;
1124 /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
1126 fd
= open("/dev/mapper/control", O_RDWR
|O_CLOEXEC
);
1130 strncpy(dm
.name
, p
->name
, sizeof(dm
.name
));
1132 if (ioctl(fd
, DM_DEV_REMOVE
, &dm
))
1139 int decrypted_image_relinquish(DecryptedImage
*d
) {
1141 #if HAVE_LIBCRYPTSETUP
1148 /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
1149 * that we don't clean it up ourselves either anymore */
1151 #if HAVE_LIBCRYPTSETUP
1152 for (i
= 0; i
< d
->n_decrypted
; i
++) {
1153 DecryptedPartition
*p
= d
->decrypted
+ i
;
1155 if (p
->relinquished
)
1158 r
= deferred_remove(p
);
1160 return log_debug_errno(r
, "Failed to mark %s for auto-removal: %m", p
->name
);
1162 p
->relinquished
= true;
1169 int root_hash_load(const char *image
, void **ret
, size_t *ret_size
) {
1170 _cleanup_free_
char *text
= NULL
;
1171 _cleanup_free_
void *k
= NULL
;
1179 if (is_device_path(image
)) {
1180 /* If we are asked to load the root hash for a device node, exit early */
1186 r
= getxattr_malloc(image
, "user.verity.roothash", &text
, true);
1190 if (!IN_SET(r
, -ENODATA
, -EOPNOTSUPP
, -ENOENT
))
1193 fn
= newa(char, strlen(image
) + STRLEN(".roothash") + 1);
1194 n
= stpcpy(fn
, image
);
1195 e
= endswith(fn
, ".raw");
1199 strcpy(n
, ".roothash");
1201 r
= read_one_line_file(fn
, &text
);
1211 r
= unhexmem(text
, strlen(text
), &k
, &l
);
1214 if (l
< sizeof(sd_id128_t
))
1225 int dissected_image_acquire_metadata(DissectedImage
*m
) {
1235 static const char *const paths
[_META_MAX
] = {
1236 [META_HOSTNAME
] = "/etc/hostname\0",
1237 [META_MACHINE_ID
] = "/etc/machine-id\0",
1238 [META_MACHINE_INFO
] = "/etc/machine-info\0",
1239 [META_OS_RELEASE
] = "/etc/os-release\0/usr/lib/os-release\0",
1242 _cleanup_strv_free_
char **machine_info
= NULL
, **os_release
= NULL
;
1243 _cleanup_(rmdir_and_freep
) char *t
= NULL
;
1244 _cleanup_(sigkill_waitp
) pid_t child
= 0;
1245 sd_id128_t machine_id
= SD_ID128_NULL
;
1246 _cleanup_free_
char *hostname
= NULL
;
1247 unsigned n_meta_initialized
= 0, k
;
1248 int fds
[2 * _META_MAX
], r
;
1250 BLOCK_SIGNALS(SIGCHLD
);
1254 for (; n_meta_initialized
< _META_MAX
; n_meta_initialized
++)
1255 if (pipe2(fds
+ 2*n_meta_initialized
, O_CLOEXEC
) < 0) {
1260 r
= mkdtemp_malloc("/tmp/dissect-XXXXXX", &t
);
1264 r
= safe_fork("(sd-dissect)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_NEW_MOUNTNS
, &child
);
1268 /* Make sure we never propagate to the host */
1269 if (mount(NULL
, "/", NULL
, MS_SLAVE
| MS_REC
, NULL
) < 0)
1270 _exit(EXIT_FAILURE
);
1272 r
= dissected_image_mount(m
, t
, UID_INVALID
, DISSECT_IMAGE_READ_ONLY
);
1274 _exit(EXIT_FAILURE
);
1276 for (k
= 0; k
< _META_MAX
; k
++) {
1277 _cleanup_close_
int fd
= -1;
1280 fds
[2*k
] = safe_close(fds
[2*k
]);
1282 NULSTR_FOREACH(p
, paths
[k
]) {
1283 _cleanup_free_
char *q
= NULL
;
1285 r
= chase_symlinks(p
, t
, CHASE_PREFIX_ROOT
, &q
);
1289 fd
= open(q
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1296 r
= copy_bytes(fd
, fds
[2*k
+1], (uint64_t) -1, 0);
1298 _exit(EXIT_FAILURE
);
1300 fds
[2*k
+1] = safe_close(fds
[2*k
+1]);
1303 _exit(EXIT_SUCCESS
);
1306 for (k
= 0; k
< _META_MAX
; k
++) {
1307 _cleanup_fclose_
FILE *f
= NULL
;
1309 fds
[2*k
+1] = safe_close(fds
[2*k
+1]);
1311 f
= fdopen(fds
[2*k
], "re");
1322 r
= read_etc_hostname_stream(f
, &hostname
);
1324 log_debug_errno(r
, "Failed to read /etc/hostname: %m");
1328 case META_MACHINE_ID
: {
1329 _cleanup_free_
char *line
= NULL
;
1331 r
= read_line(f
, LONG_LINE_MAX
, &line
);
1333 log_debug_errno(r
, "Failed to read /etc/machine-id: %m");
1335 r
= sd_id128_from_string(line
, &machine_id
);
1337 log_debug_errno(r
, "Image contains invalid /etc/machine-id: %s", line
);
1339 log_debug("/etc/machine-id file is empty.");
1341 log_debug("/etc/machine-id has unexpected length %i.", r
);
1346 case META_MACHINE_INFO
:
1347 r
= load_env_file_pairs(f
, "machine-info", NULL
, &machine_info
);
1349 log_debug_errno(r
, "Failed to read /etc/machine-info: %m");
1353 case META_OS_RELEASE
:
1354 r
= load_env_file_pairs(f
, "os-release", NULL
, &os_release
);
1356 log_debug_errno(r
, "Failed to read OS release file: %m");
1362 r
= wait_for_terminate_and_check("(sd-dissect)", child
, 0);
1366 if (r
!= EXIT_SUCCESS
)
1369 free_and_replace(m
->hostname
, hostname
);
1370 m
->machine_id
= machine_id
;
1371 strv_free_and_replace(m
->machine_info
, machine_info
);
1372 strv_free_and_replace(m
->os_release
, os_release
);
1375 for (k
= 0; k
< n_meta_initialized
; k
++)
1376 safe_close_pair(fds
+ 2*k
);
1381 static const char *const partition_designator_table
[] = {
1382 [PARTITION_ROOT
] = "root",
1383 [PARTITION_ROOT_SECONDARY
] = "root-secondary",
1384 [PARTITION_HOME
] = "home",
1385 [PARTITION_SRV
] = "srv",
1386 [PARTITION_ESP
] = "esp",
1387 [PARTITION_SWAP
] = "swap",
1388 [PARTITION_ROOT_VERITY
] = "root-verity",
1389 [PARTITION_ROOT_SECONDARY_VERITY
] = "root-secondary-verity",
1392 DEFINE_STRING_TABLE_LOOKUP(partition_designator
, int);