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