]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/dissect-image.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / dissect-image.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2016 Lennart Poettering
6
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.
11
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.
16
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/>.
19 ***/
20
21 #if HAVE_LIBCRYPTSETUP
22 #include <libcryptsetup.h>
23 #ifndef CRYPT_LUKS
24 #define CRYPT_LUKS NULL
25 #endif
26 #endif
27 #include <sys/mount.h>
28
29 #include "architecture.h"
30 #include "ask-password-api.h"
31 #include "blkid-util.h"
32 #include "dissect-image.h"
33 #include "fd-util.h"
34 #include "fileio.h"
35 #include "fs-util.h"
36 #include "gpt.h"
37 #include "hexdecoct.h"
38 #include "linux-3.13/dm-ioctl.h"
39 #include "mount-util.h"
40 #include "path-util.h"
41 #include "stat-util.h"
42 #include "stdio-util.h"
43 #include "string-table.h"
44 #include "string-util.h"
45 #include "strv.h"
46 #include "udev-util.h"
47 #include "xattr-util.h"
48
49 _unused_ static int probe_filesystem(const char *node, char **ret_fstype) {
50 #if HAVE_BLKID
51 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
52 const char *fstype;
53 int r;
54
55 b = blkid_new_probe_from_filename(node);
56 if (!b)
57 return -ENOMEM;
58
59 blkid_probe_enable_superblocks(b, 1);
60 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
61
62 errno = 0;
63 r = blkid_do_safeprobe(b);
64 if (IN_SET(r, -2, 1)) {
65 log_debug("Failed to identify any partition type on partition %s", node);
66 goto not_found;
67 }
68 if (r != 0)
69 return -errno ?: -EIO;
70
71 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
72
73 if (fstype) {
74 char *t;
75
76 t = strdup(fstype);
77 if (!t)
78 return -ENOMEM;
79
80 *ret_fstype = t;
81 return 1;
82 }
83
84 not_found:
85 *ret_fstype = NULL;
86 return 0;
87 #else
88 return -EOPNOTSUPP;
89 #endif
90 }
91
92 int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret) {
93
94 #if HAVE_BLKID
95 sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL;
96 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
97 bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
98 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
99 _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
100 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
101 _cleanup_udev_unref_ struct udev *udev = NULL;
102 _cleanup_free_ char *generic_node = NULL;
103 sd_id128_t generic_uuid = SD_ID128_NULL;
104 const char *pttype = NULL;
105 struct udev_list_entry *first, *item;
106 blkid_partlist pl;
107 int r, generic_nr;
108 struct stat st;
109 unsigned i;
110
111 assert(fd >= 0);
112 assert(ret);
113 assert(root_hash || root_hash_size == 0);
114
115 /* Probes a disk image, and returns information about what it found in *ret.
116 *
117 * Returns -ENOPKG if no suitable partition table or file system could be found.
118 * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
119
120 if (root_hash) {
121 /* If a root hash is supplied, then we use the root partition that has a UUID that match the first
122 * 128bit of the root hash. And we use the verity partition that has a UUID that match the final
123 * 128bit. */
124
125 if (root_hash_size < sizeof(sd_id128_t))
126 return -EINVAL;
127
128 memcpy(&root_uuid, root_hash, sizeof(sd_id128_t));
129 memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t));
130
131 if (sd_id128_is_null(root_uuid))
132 return -EINVAL;
133 if (sd_id128_is_null(verity_uuid))
134 return -EINVAL;
135 }
136
137 if (fstat(fd, &st) < 0)
138 return -errno;
139
140 if (!S_ISBLK(st.st_mode))
141 return -ENOTBLK;
142
143 b = blkid_new_probe();
144 if (!b)
145 return -ENOMEM;
146
147 errno = 0;
148 r = blkid_probe_set_device(b, fd, 0, 0);
149 if (r != 0)
150 return -errno ?: -ENOMEM;
151
152 if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) {
153 /* Look for file system superblocks, unless we only shall look for GPT partition tables */
154 blkid_probe_enable_superblocks(b, 1);
155 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE);
156 }
157
158 blkid_probe_enable_partitions(b, 1);
159 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
160
161 errno = 0;
162 r = blkid_do_safeprobe(b);
163 if (IN_SET(r, -2, 1)) {
164 log_debug("Failed to identify any partition table.");
165 return -ENOPKG;
166 }
167 if (r != 0)
168 return -errno ?: -EIO;
169
170 m = new0(DissectedImage, 1);
171 if (!m)
172 return -ENOMEM;
173
174 if (!(flags & DISSECT_IMAGE_GPT_ONLY) &&
175 (flags & DISSECT_IMAGE_REQUIRE_ROOT)) {
176 const char *usage = NULL;
177
178 (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
179 if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
180 _cleanup_free_ char *t = NULL, *n = NULL;
181 const char *fstype = NULL;
182
183 /* OK, we have found a file system, that's our root partition then. */
184 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
185
186 if (fstype) {
187 t = strdup(fstype);
188 if (!t)
189 return -ENOMEM;
190 }
191
192 if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
193 return -ENOMEM;
194
195 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
196 .found = true,
197 .rw = true,
198 .partno = -1,
199 .architecture = _ARCHITECTURE_INVALID,
200 .fstype = t,
201 .node = n,
202 };
203
204 t = n = NULL;
205
206 m->encrypted = streq(fstype, "crypto_LUKS");
207
208 *ret = m;
209 m = NULL;
210
211 return 0;
212 }
213 }
214
215 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
216 if (!pttype)
217 return -ENOPKG;
218
219 is_gpt = streq_ptr(pttype, "gpt");
220 is_mbr = streq_ptr(pttype, "dos");
221
222 if (!is_gpt && ((flags & DISSECT_IMAGE_GPT_ONLY) || !is_mbr))
223 return -ENOPKG;
224
225 errno = 0;
226 pl = blkid_probe_get_partitions(b);
227 if (!pl)
228 return -errno ?: -ENOMEM;
229
230 udev = udev_new();
231 if (!udev)
232 return -errno;
233
234 d = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
235 if (!d)
236 return -ENOMEM;
237
238 for (i = 0;; i++) {
239 int n, z;
240
241 if (i >= 10) {
242 log_debug("Kernel partitions never appeared.");
243 return -ENXIO;
244 }
245
246 e = udev_enumerate_new(udev);
247 if (!e)
248 return -errno;
249
250 r = udev_enumerate_add_match_parent(e, d);
251 if (r < 0)
252 return r;
253
254 r = udev_enumerate_scan_devices(e);
255 if (r < 0)
256 return r;
257
258 /* Count the partitions enumerated by the kernel */
259 n = 0;
260 first = udev_enumerate_get_list_entry(e);
261 udev_list_entry_foreach(item, first)
262 n++;
263
264 /* Count the partitions enumerated by blkid */
265 z = blkid_partlist_numof_partitions(pl);
266 if (n == z + 1)
267 break;
268 if (n > z + 1) {
269 log_debug("blkid and kernel partition list do not match.");
270 return -EIO;
271 }
272 if (n < z + 1) {
273 unsigned j = 0;
274
275 /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running
276 * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a
277 * synchronous call that waits until probing is complete. */
278
279 for (;;) {
280 if (j++ > 20)
281 return -EBUSY;
282
283 if (ioctl(fd, BLKRRPART, 0) < 0) {
284 r = -errno;
285
286 if (r == -EINVAL) {
287 struct loop_info64 info;
288
289 /* If we are running on a loop device that has partition scanning off,
290 * return an explicit recognizable error about this, so that callers
291 * can generate a proper message explaining the situation. */
292
293 if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0 && (info.lo_flags & LO_FLAGS_PARTSCAN) == 0) {
294 log_debug("Device is loop device and partition scanning is off!");
295 return -EPROTONOSUPPORT;
296 }
297 }
298 if (r != -EBUSY)
299 return r;
300 } else
301 break;
302
303 /* If something else has the device open, such as an udev rule, the ioctl will return
304 * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a
305 * bit, and try again.
306 *
307 * This is really something they should fix in the kernel! */
308
309 (void) usleep(50 * USEC_PER_MSEC);
310 }
311 }
312
313 e = udev_enumerate_unref(e);
314 }
315
316 first = udev_enumerate_get_list_entry(e);
317 udev_list_entry_foreach(item, first) {
318 _cleanup_udev_device_unref_ struct udev_device *q;
319 unsigned long long pflags;
320 blkid_partition pp;
321 const char *node, *sysname;
322 dev_t qn;
323 int nr;
324
325 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
326 if (!q)
327 return -errno;
328
329 qn = udev_device_get_devnum(q);
330 if (major(qn) == 0)
331 continue;
332
333 if (st.st_rdev == qn)
334 continue;
335
336 /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see
337 * https://github.com/systemd/systemd/issues/5806 */
338 sysname = udev_device_get_sysname(q);
339 if (sysname && startswith(sysname, "mmcblk") && endswith(sysname, "rpmb"))
340 continue;
341
342 node = udev_device_get_devnode(q);
343 if (!node)
344 continue;
345
346 pp = blkid_partlist_devno_to_partition(pl, qn);
347 if (!pp)
348 continue;
349
350 pflags = blkid_partition_get_flags(pp);
351
352 nr = blkid_partition_get_partno(pp);
353 if (nr < 0)
354 continue;
355
356 if (is_gpt) {
357 int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID;
358 const char *stype, *sid, *fstype = NULL;
359 sd_id128_t type_id, id;
360 bool rw = true;
361
362 sid = blkid_partition_get_uuid(pp);
363 if (!sid)
364 continue;
365 if (sd_id128_from_string(sid, &id) < 0)
366 continue;
367
368 stype = blkid_partition_get_type_string(pp);
369 if (!stype)
370 continue;
371 if (sd_id128_from_string(stype, &type_id) < 0)
372 continue;
373
374 if (sd_id128_equal(type_id, GPT_HOME)) {
375
376 if (pflags & GPT_FLAG_NO_AUTO)
377 continue;
378
379 designator = PARTITION_HOME;
380 rw = !(pflags & GPT_FLAG_READ_ONLY);
381 } else if (sd_id128_equal(type_id, GPT_SRV)) {
382
383 if (pflags & GPT_FLAG_NO_AUTO)
384 continue;
385
386 designator = PARTITION_SRV;
387 rw = !(pflags & GPT_FLAG_READ_ONLY);
388 } else if (sd_id128_equal(type_id, GPT_ESP)) {
389
390 /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined
391 * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the
392 * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */
393
394 if (pflags & GPT_FLAG_NO_BLOCK_IO_PROTOCOL)
395 continue;
396
397 designator = PARTITION_ESP;
398 fstype = "vfat";
399 }
400 #ifdef GPT_ROOT_NATIVE
401 else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
402
403 if (pflags & GPT_FLAG_NO_AUTO)
404 continue;
405
406 /* If a root ID is specified, ignore everything but the root id */
407 if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
408 continue;
409
410 designator = PARTITION_ROOT;
411 architecture = native_architecture();
412 rw = !(pflags & GPT_FLAG_READ_ONLY);
413 } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
414
415 if (pflags & GPT_FLAG_NO_AUTO)
416 continue;
417
418 m->can_verity = true;
419
420 /* Ignore verity unless a root hash is specified */
421 if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id))
422 continue;
423
424 designator = PARTITION_ROOT_VERITY;
425 fstype = "DM_verity_hash";
426 architecture = native_architecture();
427 rw = false;
428 }
429 #endif
430 #ifdef GPT_ROOT_SECONDARY
431 else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
432
433 if (pflags & GPT_FLAG_NO_AUTO)
434 continue;
435
436 /* If a root ID is specified, ignore everything but the root id */
437 if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
438 continue;
439
440 designator = PARTITION_ROOT_SECONDARY;
441 architecture = SECONDARY_ARCHITECTURE;
442 rw = !(pflags & GPT_FLAG_READ_ONLY);
443 } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
444
445 if (pflags & GPT_FLAG_NO_AUTO)
446 continue;
447
448 m->can_verity = true;
449
450 /* Ignore verity unless root has is specified */
451 if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id))
452 continue;
453
454 designator = PARTITION_ROOT_SECONDARY_VERITY;
455 fstype = "DM_verity_hash";
456 architecture = SECONDARY_ARCHITECTURE;
457 rw = false;
458 }
459 #endif
460 else if (sd_id128_equal(type_id, GPT_SWAP)) {
461
462 if (pflags & GPT_FLAG_NO_AUTO)
463 continue;
464
465 designator = PARTITION_SWAP;
466 fstype = "swap";
467 } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
468
469 if (pflags & GPT_FLAG_NO_AUTO)
470 continue;
471
472 if (generic_node)
473 multiple_generic = true;
474 else {
475 generic_nr = nr;
476 generic_rw = !(pflags & GPT_FLAG_READ_ONLY);
477 generic_uuid = id;
478 generic_node = strdup(node);
479 if (!generic_node)
480 return -ENOMEM;
481 }
482 }
483
484 if (designator != _PARTITION_DESIGNATOR_INVALID) {
485 _cleanup_free_ char *t = NULL, *n = NULL;
486
487 /* First one wins */
488 if (m->partitions[designator].found)
489 continue;
490
491 if (fstype) {
492 t = strdup(fstype);
493 if (!t)
494 return -ENOMEM;
495 }
496
497 n = strdup(node);
498 if (!n)
499 return -ENOMEM;
500
501 m->partitions[designator] = (DissectedPartition) {
502 .found = true,
503 .partno = nr,
504 .rw = rw,
505 .architecture = architecture,
506 .node = n,
507 .fstype = t,
508 .uuid = id,
509 };
510
511 n = t = NULL;
512 }
513
514 } else if (is_mbr) {
515
516 if (pflags != 0x80) /* Bootable flag */
517 continue;
518
519 if (blkid_partition_get_type(pp) != 0x83) /* Linux partition */
520 continue;
521
522 if (generic_node)
523 multiple_generic = true;
524 else {
525 generic_nr = nr;
526 generic_rw = true;
527 generic_node = strdup(node);
528 if (!generic_node)
529 return -ENOMEM;
530 }
531 }
532 }
533
534 if (!m->partitions[PARTITION_ROOT].found) {
535 /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
536 * either, then check if there's a single generic one, and use that. */
537
538 if (m->partitions[PARTITION_ROOT_VERITY].found)
539 return -EADDRNOTAVAIL;
540
541 if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
542 m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
543 zero(m->partitions[PARTITION_ROOT_SECONDARY]);
544
545 m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
546 zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
547
548 } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) {
549
550 /* If the root has was set, then we won't fallback to a generic node, because the root hash
551 * decides */
552 if (root_hash)
553 return -EADDRNOTAVAIL;
554
555 /* If we didn't find a generic node, then we can't fix this up either */
556 if (!generic_node)
557 return -ENXIO;
558
559 /* If we didn't find a properly marked root partition, but we did find a single suitable
560 * generic Linux partition, then use this as root partition, if the caller asked for it. */
561 if (multiple_generic)
562 return -ENOTUNIQ;
563
564 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
565 .found = true,
566 .rw = generic_rw,
567 .partno = generic_nr,
568 .architecture = _ARCHITECTURE_INVALID,
569 .node = generic_node,
570 .uuid = generic_uuid,
571 };
572
573 generic_node = NULL;
574 }
575 }
576
577 if (root_hash) {
578 if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
579 return -EADDRNOTAVAIL;
580
581 /* If we found the primary root with the hash, then we definitely want to suppress any secondary root
582 * (which would be weird, after all the root hash should only be assigned to one pair of
583 * partitions... */
584 m->partitions[PARTITION_ROOT_SECONDARY].found = false;
585 m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
586
587 /* If we found a verity setup, then the root partition is necessarily read-only. */
588 m->partitions[PARTITION_ROOT].rw = false;
589
590 m->verity = true;
591 }
592
593 blkid_free_probe(b);
594 b = NULL;
595
596 /* Fill in file system types if we don't know them yet. */
597 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
598 DissectedPartition *p = m->partitions + i;
599
600 if (!p->found)
601 continue;
602
603 if (!p->fstype && p->node) {
604 r = probe_filesystem(p->node, &p->fstype);
605 if (r < 0)
606 return r;
607 }
608
609 if (streq_ptr(p->fstype, "crypto_LUKS"))
610 m->encrypted = true;
611
612 if (p->fstype && fstype_is_ro(p->fstype))
613 p->rw = false;
614 }
615
616 *ret = m;
617 m = NULL;
618
619 return 0;
620 #else
621 return -EOPNOTSUPP;
622 #endif
623 }
624
625 DissectedImage* dissected_image_unref(DissectedImage *m) {
626 unsigned i;
627
628 if (!m)
629 return NULL;
630
631 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
632 free(m->partitions[i].fstype);
633 free(m->partitions[i].node);
634 free(m->partitions[i].decrypted_fstype);
635 free(m->partitions[i].decrypted_node);
636 }
637
638 free(m);
639 return NULL;
640 }
641
642 static int is_loop_device(const char *path) {
643 char s[strlen("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen("/../loop/")];
644 struct stat st;
645
646 assert(path);
647
648 if (stat(path, &st) < 0)
649 return -errno;
650
651 if (!S_ISBLK(st.st_mode))
652 return -ENOTBLK;
653
654 xsprintf(s, "/sys/dev/block/%u:%u/loop/", major(st.st_rdev), minor(st.st_rdev));
655 if (access(s, F_OK) < 0) {
656 if (errno != ENOENT)
657 return -errno;
658
659 /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */
660 xsprintf(s, "/sys/dev/block/%u:%u/../loop/", major(st.st_rdev), minor(st.st_rdev));
661 if (access(s, F_OK) < 0)
662 return errno == ENOENT ? false : -errno;
663 }
664
665 return true;
666 }
667
668 static int mount_partition(
669 DissectedPartition *m,
670 const char *where,
671 const char *directory,
672 DissectImageFlags flags) {
673
674 const char *p, *options = NULL, *node, *fstype;
675 _cleanup_free_ char *chased = NULL;
676 bool rw;
677 int r;
678
679 assert(m);
680 assert(where);
681
682 node = m->decrypted_node ?: m->node;
683 fstype = m->decrypted_fstype ?: m->fstype;
684
685 if (!m->found || !node || !fstype)
686 return 0;
687
688 /* Stacked encryption? Yuck */
689 if (streq_ptr(fstype, "crypto_LUKS"))
690 return -ELOOP;
691
692 rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
693
694 if (directory) {
695 r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased);
696 if (r < 0)
697 return r;
698
699 p = chased;
700 } else
701 p = where;
702
703 /* If requested, turn on discard support. */
704 if (fstype_can_discard(fstype) &&
705 ((flags & DISSECT_IMAGE_DISCARD) ||
706 ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node))))
707 options = "discard";
708
709 return mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
710 }
711
712 int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlags flags) {
713 int r;
714
715 assert(m);
716 assert(where);
717
718 if (!m->partitions[PARTITION_ROOT].found)
719 return -ENXIO;
720
721 r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, flags);
722 if (r < 0)
723 return r;
724
725 r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", flags);
726 if (r < 0)
727 return r;
728
729 r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", flags);
730 if (r < 0)
731 return r;
732
733 if (m->partitions[PARTITION_ESP].found) {
734 const char *mp;
735
736 /* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */
737
738 FOREACH_STRING(mp, "/efi", "/boot") {
739 _cleanup_free_ char *p = NULL;
740
741 r = chase_symlinks(mp, where, CHASE_PREFIX_ROOT, &p);
742 if (r < 0)
743 continue;
744
745 r = dir_is_empty(p);
746 if (r > 0) {
747 r = mount_partition(m->partitions + PARTITION_ESP, where, mp, flags);
748 if (r < 0)
749 return r;
750 }
751 }
752 }
753
754 return 0;
755 }
756
757 #if HAVE_LIBCRYPTSETUP
758 typedef struct DecryptedPartition {
759 struct crypt_device *device;
760 char *name;
761 bool relinquished;
762 } DecryptedPartition;
763
764 struct DecryptedImage {
765 DecryptedPartition *decrypted;
766 size_t n_decrypted;
767 size_t n_allocated;
768 };
769 #endif
770
771 DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
772 #if HAVE_LIBCRYPTSETUP
773 size_t i;
774 int r;
775
776 if (!d)
777 return NULL;
778
779 for (i = 0; i < d->n_decrypted; i++) {
780 DecryptedPartition *p = d->decrypted + i;
781
782 if (p->device && p->name && !p->relinquished) {
783 r = crypt_deactivate(p->device, p->name);
784 if (r < 0)
785 log_debug_errno(r, "Failed to deactivate encrypted partition %s", p->name);
786 }
787
788 if (p->device)
789 crypt_free(p->device);
790 free(p->name);
791 }
792
793 free(d);
794 #endif
795 return NULL;
796 }
797
798 #if HAVE_LIBCRYPTSETUP
799
800 static int make_dm_name_and_node(const void *original_node, const char *suffix, char **ret_name, char **ret_node) {
801 _cleanup_free_ char *name = NULL, *node = NULL;
802 const char *base;
803
804 assert(original_node);
805 assert(suffix);
806 assert(ret_name);
807 assert(ret_node);
808
809 base = strrchr(original_node, '/');
810 if (!base)
811 return -EINVAL;
812 base++;
813 if (isempty(base))
814 return -EINVAL;
815
816 name = strjoin(base, suffix);
817 if (!name)
818 return -ENOMEM;
819 if (!filename_is_valid(name))
820 return -EINVAL;
821
822 node = strjoin(crypt_get_dir(), "/", name);
823 if (!node)
824 return -ENOMEM;
825
826 *ret_name = name;
827 *ret_node = node;
828
829 name = node = NULL;
830 return 0;
831 }
832
833 static int decrypt_partition(
834 DissectedPartition *m,
835 const char *passphrase,
836 DissectImageFlags flags,
837 DecryptedImage *d) {
838
839 _cleanup_free_ char *node = NULL, *name = NULL;
840 struct crypt_device *cd;
841 int r;
842
843 assert(m);
844 assert(d);
845
846 if (!m->found || !m->node || !m->fstype)
847 return 0;
848
849 if (!streq(m->fstype, "crypto_LUKS"))
850 return 0;
851
852 r = make_dm_name_and_node(m->node, "-decrypted", &name, &node);
853 if (r < 0)
854 return r;
855
856 if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
857 return -ENOMEM;
858
859 r = crypt_init(&cd, m->node);
860 if (r < 0)
861 return log_debug_errno(r, "Failed to initialize dm-crypt: %m");
862
863 r = crypt_load(cd, CRYPT_LUKS, NULL);
864 if (r < 0) {
865 log_debug_errno(r, "Failed to load LUKS metadata: %m");
866 goto fail;
867 }
868
869 r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
870 ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
871 ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
872 if (r < 0)
873 log_debug_errno(r, "Failed to activate LUKS device: %m");
874 if (r == -EPERM) {
875 r = -EKEYREJECTED;
876 goto fail;
877 }
878 if (r < 0)
879 goto fail;
880
881 d->decrypted[d->n_decrypted].name = name;
882 name = NULL;
883
884 d->decrypted[d->n_decrypted].device = cd;
885 d->n_decrypted++;
886
887 m->decrypted_node = node;
888 node = NULL;
889
890 return 0;
891
892 fail:
893 crypt_free(cd);
894 return r;
895 }
896
897 static int verity_partition(
898 DissectedPartition *m,
899 DissectedPartition *v,
900 const void *root_hash,
901 size_t root_hash_size,
902 DissectImageFlags flags,
903 DecryptedImage *d) {
904
905 _cleanup_free_ char *node = NULL, *name = NULL;
906 struct crypt_device *cd;
907 int r;
908
909 assert(m);
910 assert(v);
911
912 if (!root_hash)
913 return 0;
914
915 if (!m->found || !m->node || !m->fstype)
916 return 0;
917 if (!v->found || !v->node || !v->fstype)
918 return 0;
919
920 if (!streq(v->fstype, "DM_verity_hash"))
921 return 0;
922
923 r = make_dm_name_and_node(m->node, "-verity", &name, &node);
924 if (r < 0)
925 return r;
926
927 if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
928 return -ENOMEM;
929
930 r = crypt_init(&cd, v->node);
931 if (r < 0)
932 return r;
933
934 r = crypt_load(cd, CRYPT_VERITY, NULL);
935 if (r < 0)
936 goto fail;
937
938 r = crypt_set_data_device(cd, m->node);
939 if (r < 0)
940 goto fail;
941
942 r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
943 if (r < 0)
944 goto fail;
945
946 d->decrypted[d->n_decrypted].name = name;
947 name = NULL;
948
949 d->decrypted[d->n_decrypted].device = cd;
950 d->n_decrypted++;
951
952 m->decrypted_node = node;
953 node = NULL;
954
955 return 0;
956
957 fail:
958 crypt_free(cd);
959 return r;
960 }
961 #endif
962
963 int dissected_image_decrypt(
964 DissectedImage *m,
965 const char *passphrase,
966 const void *root_hash,
967 size_t root_hash_size,
968 DissectImageFlags flags,
969 DecryptedImage **ret) {
970
971 _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
972 #if HAVE_LIBCRYPTSETUP
973 unsigned i;
974 int r;
975 #endif
976
977 assert(m);
978 assert(root_hash || root_hash_size == 0);
979
980 /* Returns:
981 *
982 * = 0 → There was nothing to decrypt
983 * > 0 → Decrypted successfully
984 * -ENOKEY → There's something to decrypt but no key was supplied
985 * -EKEYREJECTED → Passed key was not correct
986 */
987
988 if (root_hash && root_hash_size < sizeof(sd_id128_t))
989 return -EINVAL;
990
991 if (!m->encrypted && !m->verity) {
992 *ret = NULL;
993 return 0;
994 }
995
996 #if HAVE_LIBCRYPTSETUP
997 if (m->encrypted && !passphrase)
998 return -ENOKEY;
999
1000 d = new0(DecryptedImage, 1);
1001 if (!d)
1002 return -ENOMEM;
1003
1004 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
1005 DissectedPartition *p = m->partitions + i;
1006 int k;
1007
1008 if (!p->found)
1009 continue;
1010
1011 r = decrypt_partition(p, passphrase, flags, d);
1012 if (r < 0)
1013 return r;
1014
1015 k = PARTITION_VERITY_OF(i);
1016 if (k >= 0) {
1017 r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, flags, d);
1018 if (r < 0)
1019 return r;
1020 }
1021
1022 if (!p->decrypted_fstype && p->decrypted_node) {
1023 r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype);
1024 if (r < 0)
1025 return r;
1026 }
1027 }
1028
1029 *ret = d;
1030 d = NULL;
1031
1032 return 1;
1033 #else
1034 return -EOPNOTSUPP;
1035 #endif
1036 }
1037
1038 int dissected_image_decrypt_interactively(
1039 DissectedImage *m,
1040 const char *passphrase,
1041 const void *root_hash,
1042 size_t root_hash_size,
1043 DissectImageFlags flags,
1044 DecryptedImage **ret) {
1045
1046 _cleanup_strv_free_erase_ char **z = NULL;
1047 int n = 3, r;
1048
1049 if (passphrase)
1050 n--;
1051
1052 for (;;) {
1053 r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, flags, ret);
1054 if (r >= 0)
1055 return r;
1056 if (r == -EKEYREJECTED)
1057 log_error_errno(r, "Incorrect passphrase, try again!");
1058 else if (r != -ENOKEY) {
1059 log_error_errno(r, "Failed to decrypt image: %m");
1060 return r;
1061 }
1062
1063 if (--n < 0) {
1064 log_error("Too many retries.");
1065 return -EKEYREJECTED;
1066 }
1067
1068 z = strv_free(z);
1069
1070 r = ask_password_auto("Please enter image passphrase!", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
1071 if (r < 0)
1072 return log_error_errno(r, "Failed to query for passphrase: %m");
1073
1074 passphrase = z[0];
1075 }
1076 }
1077
1078 #if HAVE_LIBCRYPTSETUP
1079 static int deferred_remove(DecryptedPartition *p) {
1080
1081 struct dm_ioctl dm = {
1082 .version = {
1083 DM_VERSION_MAJOR,
1084 DM_VERSION_MINOR,
1085 DM_VERSION_PATCHLEVEL
1086 },
1087 .data_size = sizeof(dm),
1088 .flags = DM_DEFERRED_REMOVE,
1089 };
1090
1091 _cleanup_close_ int fd = -1;
1092
1093 assert(p);
1094
1095 /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
1096
1097 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
1098 if (fd < 0)
1099 return -errno;
1100
1101 strncpy(dm.name, p->name, sizeof(dm.name));
1102
1103 if (ioctl(fd, DM_DEV_REMOVE, &dm))
1104 return -errno;
1105
1106 return 0;
1107 }
1108 #endif
1109
1110 int decrypted_image_relinquish(DecryptedImage *d) {
1111
1112 #if HAVE_LIBCRYPTSETUP
1113 size_t i;
1114 int r;
1115 #endif
1116
1117 assert(d);
1118
1119 /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
1120 * that we don't clean it up ourselves either anymore */
1121
1122 #if HAVE_LIBCRYPTSETUP
1123 for (i = 0; i < d->n_decrypted; i++) {
1124 DecryptedPartition *p = d->decrypted + i;
1125
1126 if (p->relinquished)
1127 continue;
1128
1129 r = deferred_remove(p);
1130 if (r < 0)
1131 return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);
1132
1133 p->relinquished = true;
1134 }
1135 #endif
1136
1137 return 0;
1138 }
1139
1140 int root_hash_load(const char *image, void **ret, size_t *ret_size) {
1141 _cleanup_free_ char *text = NULL;
1142 _cleanup_free_ void *k = NULL;
1143 size_t l;
1144 int r;
1145
1146 assert(image);
1147 assert(ret);
1148 assert(ret_size);
1149
1150 if (is_device_path(image)) {
1151 /* If we are asked to load the root hash for a device node, exit early */
1152 *ret = NULL;
1153 *ret_size = 0;
1154 return 0;
1155 }
1156
1157 r = getxattr_malloc(image, "user.verity.roothash", &text, true);
1158 if (r < 0) {
1159 char *fn, *e, *n;
1160
1161 if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
1162 return r;
1163
1164 fn = newa(char, strlen(image) + strlen(".roothash") + 1);
1165 n = stpcpy(fn, image);
1166 e = endswith(fn, ".raw");
1167 if (e)
1168 n = e;
1169
1170 strcpy(n, ".roothash");
1171
1172 r = read_one_line_file(fn, &text);
1173 if (r == -ENOENT) {
1174 *ret = NULL;
1175 *ret_size = 0;
1176 return 0;
1177 }
1178 if (r < 0)
1179 return r;
1180 }
1181
1182 r = unhexmem(text, strlen(text), &k, &l);
1183 if (r < 0)
1184 return r;
1185 if (l < sizeof(sd_id128_t))
1186 return -EINVAL;
1187
1188 *ret = k;
1189 *ret_size = l;
1190
1191 k = NULL;
1192
1193 return 1;
1194 }
1195
1196 static const char *const partition_designator_table[] = {
1197 [PARTITION_ROOT] = "root",
1198 [PARTITION_ROOT_SECONDARY] = "root-secondary",
1199 [PARTITION_HOME] = "home",
1200 [PARTITION_SRV] = "srv",
1201 [PARTITION_ESP] = "esp",
1202 [PARTITION_SWAP] = "swap",
1203 [PARTITION_ROOT_VERITY] = "root-verity",
1204 [PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
1205 };
1206
1207 DEFINE_STRING_TABLE_LOOKUP(partition_designator, int);