]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/dissect-image.c
systemctl: restore "systemctl reboot ARG" functionality
[thirdparty/systemd.git] / src / shared / dissect-image.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <sys/mount.h>
4 #include <sys/prctl.h>
5 #include <sys/wait.h>
6
7 #include "sd-device.h"
8 #include "sd-id128.h"
9
10 #include "architecture.h"
11 #include "ask-password-api.h"
12 #include "blkid-util.h"
13 #include "blockdev-util.h"
14 #include "copy.h"
15 #include "crypt-util.h"
16 #include "def.h"
17 #include "device-nodes.h"
18 #include "device-util.h"
19 #include "dissect-image.h"
20 #include "env-file.h"
21 #include "fd-util.h"
22 #include "fileio.h"
23 #include "fs-util.h"
24 #include "gpt.h"
25 #include "hexdecoct.h"
26 #include "hostname-util.h"
27 #include "id128-util.h"
28 #include "linux-3.13/dm-ioctl.h"
29 #include "missing.h"
30 #include "mount-util.h"
31 #include "mountpoint-util.h"
32 #include "nulstr-util.h"
33 #include "os-util.h"
34 #include "path-util.h"
35 #include "process-util.h"
36 #include "raw-clone.h"
37 #include "signal-util.h"
38 #include "stat-util.h"
39 #include "stdio-util.h"
40 #include "string-table.h"
41 #include "string-util.h"
42 #include "strv.h"
43 #include "tmpfile-util.h"
44 #include "udev-util.h"
45 #include "user-util.h"
46 #include "xattr-util.h"
47
48 int probe_filesystem(const char *node, char **ret_fstype) {
49 /* Try to find device content type and return it in *ret_fstype. If nothing is found,
50 * 0/NULL will be returned. -EUCLEAN will be returned for ambigous results, and an
51 * different error otherwise. */
52
53 #if HAVE_BLKID
54 _cleanup_(blkid_free_probep) blkid_probe b = NULL;
55 const char *fstype;
56 int r;
57
58 errno = 0;
59 b = blkid_new_probe_from_filename(node);
60 if (!b)
61 return -errno ?: -ENOMEM;
62
63 blkid_probe_enable_superblocks(b, 1);
64 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
65
66 errno = 0;
67 r = blkid_do_safeprobe(b);
68 if (r == 1) {
69 log_debug("No type detected on partition %s", node);
70 goto not_found;
71 }
72 if (r == -2) {
73 log_debug("Results ambiguous for partition %s", node);
74 return -EUCLEAN;
75 }
76 if (r != 0)
77 return -errno ?: -EIO;
78
79 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
80
81 if (fstype) {
82 char *t;
83
84 t = strdup(fstype);
85 if (!t)
86 return -ENOMEM;
87
88 *ret_fstype = t;
89 return 1;
90 }
91
92 not_found:
93 *ret_fstype = NULL;
94 return 0;
95 #else
96 return -EOPNOTSUPP;
97 #endif
98 }
99
100 #if HAVE_BLKID
101 /* Detect RPMB and Boot partitions, which are not listed by blkid.
102 * See https://github.com/systemd/systemd/issues/5806. */
103 static bool device_is_mmc_special_partition(sd_device *d) {
104 const char *sysname;
105
106 assert(d);
107
108 if (sd_device_get_sysname(d, &sysname) < 0)
109 return false;
110
111 return startswith(sysname, "mmcblk") &&
112 (endswith(sysname, "rpmb") || endswith(sysname, "boot0") || endswith(sysname, "boot1"));
113 }
114
115 static bool device_is_block(sd_device *d) {
116 const char *ss;
117
118 assert(d);
119
120 if (sd_device_get_subsystem(d, &ss) < 0)
121 return false;
122
123 return streq(ss, "block");
124 }
125
126 static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
127 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
128 int r;
129
130 assert(d);
131 assert(ret);
132
133 r = sd_device_enumerator_new(&e);
134 if (r < 0)
135 return r;
136
137 r = sd_device_enumerator_allow_uninitialized(e);
138 if (r < 0)
139 return r;
140
141 r = sd_device_enumerator_add_match_parent(e, d);
142 if (r < 0)
143 return r;
144
145 *ret = TAKE_PTR(e);
146 return 0;
147 }
148
149 /* how many times to wait for the device nodes to appear */
150 #define N_DEVICE_NODE_LIST_ATTEMPTS 10
151
152 static int wait_for_partitions_to_appear(
153 int fd,
154 sd_device *d,
155 unsigned num_partitions,
156 DissectImageFlags flags,
157 sd_device_enumerator **ret_enumerator) {
158
159 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
160 sd_device *q;
161 unsigned n;
162 int r;
163
164 assert(fd >= 0);
165 assert(d);
166 assert(ret_enumerator);
167
168 r = enumerator_for_parent(d, &e);
169 if (r < 0)
170 return r;
171
172 /* Count the partitions enumerated by the kernel */
173 n = 0;
174 FOREACH_DEVICE(e, q) {
175 if (sd_device_get_devnum(q, NULL) < 0)
176 continue;
177 if (!device_is_block(q))
178 continue;
179 if (device_is_mmc_special_partition(q))
180 continue;
181
182 if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) {
183 r = device_wait_for_initialization(q, "block", NULL);
184 if (r < 0)
185 return r;
186 }
187
188 n++;
189 }
190
191 if (n == num_partitions + 1) {
192 *ret_enumerator = TAKE_PTR(e);
193 return 0; /* success! */
194 }
195 if (n > num_partitions + 1)
196 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
197 "blkid and kernel partition lists do not match.");
198
199 /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running or it
200 * got EBUSY because udev already opened the device. Let's reprobe the device, which is a synchronous
201 * call that waits until probing is complete. */
202
203 for (unsigned j = 0; ; j++) {
204 if (j++ > 20)
205 return -EBUSY;
206
207 if (ioctl(fd, BLKRRPART, 0) >= 0)
208 break;
209 r = -errno;
210 if (r == -EINVAL) {
211 struct loop_info64 info;
212
213 /* If we are running on a loop device that has partition scanning off, return
214 * an explicit recognizable error about this, so that callers can generate a
215 * proper message explaining the situation. */
216
217 if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0 && (info.lo_flags & LO_FLAGS_PARTSCAN) == 0) {
218 log_debug("Device is a loop device and partition scanning is off!");
219 return -EPROTONOSUPPORT;
220 }
221 }
222 if (r != -EBUSY)
223 return r;
224
225 /* If something else has the device open, such as an udev rule, the ioctl will return
226 * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a bit,
227 * and try again.
228 *
229 * This is really something they should fix in the kernel! */
230 (void) usleep(50 * USEC_PER_MSEC);
231
232 }
233
234 return -EAGAIN; /* no success yet, try again */
235 }
236
237 static int loop_wait_for_partitions_to_appear(
238 int fd,
239 sd_device *d,
240 unsigned num_partitions,
241 DissectImageFlags flags,
242 sd_device_enumerator **ret_enumerator) {
243 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
244 int r;
245
246 assert(fd >= 0);
247 assert(d);
248 assert(ret_enumerator);
249
250 log_debug("Waiting for device (parent + %d partitions) to appear...", num_partitions);
251
252 if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) {
253 r = device_wait_for_initialization(d, "block", &device);
254 if (r < 0)
255 return r;
256 } else
257 device = sd_device_ref(d);
258
259 for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
260 r = wait_for_partitions_to_appear(fd, device, num_partitions, flags, ret_enumerator);
261 if (r != -EAGAIN)
262 return r;
263 }
264
265 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
266 "Kernel partitions dit not appear within %d attempts",
267 N_DEVICE_NODE_LIST_ATTEMPTS);
268 }
269
270 #endif
271
272 int dissect_image(
273 int fd,
274 const void *root_hash,
275 size_t root_hash_size,
276 DissectImageFlags flags,
277 DissectedImage **ret) {
278
279 #if HAVE_BLKID
280 sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL;
281 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
282 bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
283 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
284 _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
285 _cleanup_(blkid_free_probep) blkid_probe b = NULL;
286 _cleanup_free_ char *generic_node = NULL;
287 sd_id128_t generic_uuid = SD_ID128_NULL;
288 const char *pttype = NULL;
289 blkid_partlist pl;
290 int r, generic_nr;
291 struct stat st;
292 sd_device *q;
293 unsigned i;
294
295 assert(fd >= 0);
296 assert(ret);
297 assert(root_hash || root_hash_size == 0);
298
299 /* Probes a disk image, and returns information about what it found in *ret.
300 *
301 * Returns -ENOPKG if no suitable partition table or file system could be found.
302 * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
303
304 if (root_hash) {
305 /* If a root hash is supplied, then we use the root partition that has a UUID that match the first
306 * 128bit of the root hash. And we use the verity partition that has a UUID that match the final
307 * 128bit. */
308
309 if (root_hash_size < sizeof(sd_id128_t))
310 return -EINVAL;
311
312 memcpy(&root_uuid, root_hash, sizeof(sd_id128_t));
313 memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t));
314
315 if (sd_id128_is_null(root_uuid))
316 return -EINVAL;
317 if (sd_id128_is_null(verity_uuid))
318 return -EINVAL;
319 }
320
321 if (fstat(fd, &st) < 0)
322 return -errno;
323
324 if (!S_ISBLK(st.st_mode))
325 return -ENOTBLK;
326
327 b = blkid_new_probe();
328 if (!b)
329 return -ENOMEM;
330
331 errno = 0;
332 r = blkid_probe_set_device(b, fd, 0, 0);
333 if (r != 0)
334 return -errno ?: -ENOMEM;
335
336 if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) {
337 /* Look for file system superblocks, unless we only shall look for GPT partition tables */
338 blkid_probe_enable_superblocks(b, 1);
339 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE);
340 }
341
342 blkid_probe_enable_partitions(b, 1);
343 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
344
345 errno = 0;
346 r = blkid_do_safeprobe(b);
347 if (IN_SET(r, -2, 1))
348 return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG), "Failed to identify any partition table.");
349 if (r != 0)
350 return -errno ?: -EIO;
351
352 m = new0(DissectedImage, 1);
353 if (!m)
354 return -ENOMEM;
355
356 r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
357 if (r < 0)
358 return r;
359
360 if (!(flags & DISSECT_IMAGE_GPT_ONLY) &&
361 (flags & DISSECT_IMAGE_REQUIRE_ROOT)) {
362 const char *usage = NULL;
363
364 (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
365 if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
366 _cleanup_free_ char *t = NULL, *n = NULL;
367 const char *fstype = NULL;
368
369 /* OK, we have found a file system, that's our root partition then. */
370 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
371
372 if (fstype) {
373 t = strdup(fstype);
374 if (!t)
375 return -ENOMEM;
376 }
377
378 r = device_path_make_major_minor(st.st_mode, st.st_rdev, &n);
379 if (r < 0)
380 return r;
381
382 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
383 .found = true,
384 .rw = true,
385 .partno = -1,
386 .architecture = _ARCHITECTURE_INVALID,
387 .fstype = TAKE_PTR(t),
388 .node = TAKE_PTR(n),
389 };
390
391 m->encrypted = streq_ptr(fstype, "crypto_LUKS");
392
393 r = loop_wait_for_partitions_to_appear(fd, d, 0, flags, &e);
394 if (r < 0)
395 return r;
396
397 *ret = TAKE_PTR(m);
398
399 return 0;
400 }
401 }
402
403 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
404 if (!pttype)
405 return -ENOPKG;
406
407 is_gpt = streq_ptr(pttype, "gpt");
408 is_mbr = streq_ptr(pttype, "dos");
409
410 if (!is_gpt && ((flags & DISSECT_IMAGE_GPT_ONLY) || !is_mbr))
411 return -ENOPKG;
412
413 errno = 0;
414 pl = blkid_probe_get_partitions(b);
415 if (!pl)
416 return -errno ?: -ENOMEM;
417
418 r = loop_wait_for_partitions_to_appear(fd, d, blkid_partlist_numof_partitions(pl), flags, &e);
419 if (r < 0)
420 return r;
421
422 FOREACH_DEVICE(e, q) {
423 unsigned long long pflags;
424 blkid_partition pp;
425 const char *node;
426 dev_t qn;
427 int nr;
428
429 r = sd_device_get_devnum(q, &qn);
430 if (r < 0)
431 continue;
432
433 if (st.st_rdev == qn)
434 continue;
435
436 if (!device_is_block(q))
437 continue;
438
439 if (device_is_mmc_special_partition(q))
440 continue;
441
442 r = sd_device_get_devname(q, &node);
443 if (r < 0)
444 continue;
445
446 pp = blkid_partlist_devno_to_partition(pl, qn);
447 if (!pp)
448 continue;
449
450 pflags = blkid_partition_get_flags(pp);
451
452 nr = blkid_partition_get_partno(pp);
453 if (nr < 0)
454 continue;
455
456 if (is_gpt) {
457 int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID;
458 const char *stype, *sid, *fstype = NULL;
459 sd_id128_t type_id, id;
460 bool rw = true;
461
462 sid = blkid_partition_get_uuid(pp);
463 if (!sid)
464 continue;
465 if (sd_id128_from_string(sid, &id) < 0)
466 continue;
467
468 stype = blkid_partition_get_type_string(pp);
469 if (!stype)
470 continue;
471 if (sd_id128_from_string(stype, &type_id) < 0)
472 continue;
473
474 if (sd_id128_equal(type_id, GPT_HOME)) {
475
476 if (pflags & GPT_FLAG_NO_AUTO)
477 continue;
478
479 designator = PARTITION_HOME;
480 rw = !(pflags & GPT_FLAG_READ_ONLY);
481 } else if (sd_id128_equal(type_id, GPT_SRV)) {
482
483 if (pflags & GPT_FLAG_NO_AUTO)
484 continue;
485
486 designator = PARTITION_SRV;
487 rw = !(pflags & GPT_FLAG_READ_ONLY);
488 } else if (sd_id128_equal(type_id, GPT_ESP)) {
489
490 /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined
491 * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the
492 * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */
493
494 if (pflags & GPT_FLAG_NO_BLOCK_IO_PROTOCOL)
495 continue;
496
497 designator = PARTITION_ESP;
498 fstype = "vfat";
499
500 } else if (sd_id128_equal(type_id, GPT_XBOOTLDR)) {
501
502 if (pflags & GPT_FLAG_NO_AUTO)
503 continue;
504
505 designator = PARTITION_XBOOTLDR;
506 rw = !(pflags & GPT_FLAG_READ_ONLY);
507 }
508 #ifdef GPT_ROOT_NATIVE
509 else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
510
511 if (pflags & GPT_FLAG_NO_AUTO)
512 continue;
513
514 /* If a root ID is specified, ignore everything but the root id */
515 if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
516 continue;
517
518 designator = PARTITION_ROOT;
519 architecture = native_architecture();
520 rw = !(pflags & GPT_FLAG_READ_ONLY);
521 } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
522
523 if (pflags & GPT_FLAG_NO_AUTO)
524 continue;
525
526 m->can_verity = true;
527
528 /* Ignore verity unless a root hash is specified */
529 if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id))
530 continue;
531
532 designator = PARTITION_ROOT_VERITY;
533 fstype = "DM_verity_hash";
534 architecture = native_architecture();
535 rw = false;
536 }
537 #endif
538 #ifdef GPT_ROOT_SECONDARY
539 else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
540
541 if (pflags & GPT_FLAG_NO_AUTO)
542 continue;
543
544 /* If a root ID is specified, ignore everything but the root id */
545 if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
546 continue;
547
548 designator = PARTITION_ROOT_SECONDARY;
549 architecture = SECONDARY_ARCHITECTURE;
550 rw = !(pflags & GPT_FLAG_READ_ONLY);
551 } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
552
553 if (pflags & GPT_FLAG_NO_AUTO)
554 continue;
555
556 m->can_verity = true;
557
558 /* Ignore verity unless root has is specified */
559 if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id))
560 continue;
561
562 designator = PARTITION_ROOT_SECONDARY_VERITY;
563 fstype = "DM_verity_hash";
564 architecture = SECONDARY_ARCHITECTURE;
565 rw = false;
566 }
567 #endif
568 else if (sd_id128_equal(type_id, GPT_SWAP)) {
569
570 if (pflags & GPT_FLAG_NO_AUTO)
571 continue;
572
573 designator = PARTITION_SWAP;
574 fstype = "swap";
575 } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
576
577 if (pflags & GPT_FLAG_NO_AUTO)
578 continue;
579
580 if (generic_node)
581 multiple_generic = true;
582 else {
583 generic_nr = nr;
584 generic_rw = !(pflags & GPT_FLAG_READ_ONLY);
585 generic_uuid = id;
586 generic_node = strdup(node);
587 if (!generic_node)
588 return -ENOMEM;
589 }
590 }
591
592 if (designator != _PARTITION_DESIGNATOR_INVALID) {
593 _cleanup_free_ char *t = NULL, *n = NULL;
594
595 /* First one wins */
596 if (m->partitions[designator].found)
597 continue;
598
599 if (fstype) {
600 t = strdup(fstype);
601 if (!t)
602 return -ENOMEM;
603 }
604
605 n = strdup(node);
606 if (!n)
607 return -ENOMEM;
608
609 m->partitions[designator] = (DissectedPartition) {
610 .found = true,
611 .partno = nr,
612 .rw = rw,
613 .architecture = architecture,
614 .node = TAKE_PTR(n),
615 .fstype = TAKE_PTR(t),
616 .uuid = id,
617 };
618 }
619
620 } else if (is_mbr) {
621
622 switch (blkid_partition_get_type(pp)) {
623
624 case 0x83: /* Linux partition */
625
626 if (pflags != 0x80) /* Bootable flag */
627 continue;
628
629 if (generic_node)
630 multiple_generic = true;
631 else {
632 generic_nr = nr;
633 generic_rw = true;
634 generic_node = strdup(node);
635 if (!generic_node)
636 return -ENOMEM;
637 }
638
639 break;
640
641 case 0xEA: { /* Boot Loader Spec extended $BOOT partition */
642 _cleanup_free_ char *n = NULL;
643 sd_id128_t id = SD_ID128_NULL;
644 const char *sid;
645
646 /* First one wins */
647 if (m->partitions[PARTITION_XBOOTLDR].found)
648 continue;
649
650 sid = blkid_partition_get_uuid(pp);
651 if (sid)
652 (void) sd_id128_from_string(sid, &id);
653
654 n = strdup(node);
655 if (!n)
656 return -ENOMEM;
657
658 m->partitions[PARTITION_XBOOTLDR] = (DissectedPartition) {
659 .found = true,
660 .partno = nr,
661 .rw = true,
662 .architecture = _ARCHITECTURE_INVALID,
663 .node = TAKE_PTR(n),
664 .uuid = id,
665 };
666
667 break;
668 }}
669 }
670 }
671
672 if (!m->partitions[PARTITION_ROOT].found) {
673 /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
674 * either, then check if there's a single generic one, and use that. */
675
676 if (m->partitions[PARTITION_ROOT_VERITY].found)
677 return -EADDRNOTAVAIL;
678
679 if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
680 m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
681 zero(m->partitions[PARTITION_ROOT_SECONDARY]);
682
683 m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
684 zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
685
686 } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) {
687
688 /* If the root has was set, then we won't fallback to a generic node, because the root hash
689 * decides */
690 if (root_hash)
691 return -EADDRNOTAVAIL;
692
693 /* If we didn't find a generic node, then we can't fix this up either */
694 if (!generic_node)
695 return -ENXIO;
696
697 /* If we didn't find a properly marked root partition, but we did find a single suitable
698 * generic Linux partition, then use this as root partition, if the caller asked for it. */
699 if (multiple_generic)
700 return -ENOTUNIQ;
701
702 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
703 .found = true,
704 .rw = generic_rw,
705 .partno = generic_nr,
706 .architecture = _ARCHITECTURE_INVALID,
707 .node = TAKE_PTR(generic_node),
708 .uuid = generic_uuid,
709 };
710 }
711 }
712
713 if (root_hash) {
714 if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
715 return -EADDRNOTAVAIL;
716
717 /* If we found the primary root with the hash, then we definitely want to suppress any secondary root
718 * (which would be weird, after all the root hash should only be assigned to one pair of
719 * partitions... */
720 m->partitions[PARTITION_ROOT_SECONDARY].found = false;
721 m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
722
723 /* If we found a verity setup, then the root partition is necessarily read-only. */
724 m->partitions[PARTITION_ROOT].rw = false;
725
726 m->verity = true;
727 }
728
729 blkid_free_probe(b);
730 b = NULL;
731
732 /* Fill in file system types if we don't know them yet. */
733 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
734 DissectedPartition *p = m->partitions + i;
735
736 if (!p->found)
737 continue;
738
739 if (!p->fstype && p->node) {
740 r = probe_filesystem(p->node, &p->fstype);
741 if (r < 0 && r != -EUCLEAN)
742 return r;
743 }
744
745 if (streq_ptr(p->fstype, "crypto_LUKS"))
746 m->encrypted = true;
747
748 if (p->fstype && fstype_is_ro(p->fstype))
749 p->rw = false;
750 }
751
752 *ret = TAKE_PTR(m);
753
754 return 0;
755 #else
756 return -EOPNOTSUPP;
757 #endif
758 }
759
760 DissectedImage* dissected_image_unref(DissectedImage *m) {
761 unsigned i;
762
763 if (!m)
764 return NULL;
765
766 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
767 free(m->partitions[i].fstype);
768 free(m->partitions[i].node);
769 free(m->partitions[i].decrypted_fstype);
770 free(m->partitions[i].decrypted_node);
771 }
772
773 free(m->hostname);
774 strv_free(m->machine_info);
775 strv_free(m->os_release);
776
777 return mfree(m);
778 }
779
780 static int is_loop_device(const char *path) {
781 char s[SYS_BLOCK_PATH_MAX("/../loop/")];
782 struct stat st;
783
784 assert(path);
785
786 if (stat(path, &st) < 0)
787 return -errno;
788
789 if (!S_ISBLK(st.st_mode))
790 return -ENOTBLK;
791
792 xsprintf_sys_block_path(s, "/loop/", st.st_dev);
793 if (access(s, F_OK) < 0) {
794 if (errno != ENOENT)
795 return -errno;
796
797 /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */
798 xsprintf_sys_block_path(s, "/../loop/", st.st_dev);
799 if (access(s, F_OK) < 0)
800 return errno == ENOENT ? false : -errno;
801 }
802
803 return true;
804 }
805
806 static int mount_partition(
807 DissectedPartition *m,
808 const char *where,
809 const char *directory,
810 uid_t uid_shift,
811 DissectImageFlags flags) {
812
813 _cleanup_free_ char *chased = NULL, *options = NULL;
814 const char *p, *node, *fstype;
815 bool rw;
816 int r;
817
818 assert(m);
819 assert(where);
820
821 node = m->decrypted_node ?: m->node;
822 fstype = m->decrypted_fstype ?: m->fstype;
823
824 if (!m->found || !node || !fstype)
825 return 0;
826
827 /* Stacked encryption? Yuck */
828 if (streq_ptr(fstype, "crypto_LUKS"))
829 return -ELOOP;
830
831 rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
832
833 if (directory) {
834 r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased);
835 if (r < 0)
836 return r;
837
838 p = chased;
839 } else
840 p = where;
841
842 /* If requested, turn on discard support. */
843 if (fstype_can_discard(fstype) &&
844 ((flags & DISSECT_IMAGE_DISCARD) ||
845 ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node)))) {
846 options = strdup("discard");
847 if (!options)
848 return -ENOMEM;
849 }
850
851 if (uid_is_valid(uid_shift) && uid_shift != 0 && fstype_can_uid_gid(fstype)) {
852 _cleanup_free_ char *uid_option = NULL;
853
854 if (asprintf(&uid_option, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0)
855 return -ENOMEM;
856
857 if (!strextend_with_separator(&options, ",", uid_option, NULL))
858 return -ENOMEM;
859 }
860
861 r = mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
862 if (r < 0)
863 return r;
864
865 return 1;
866 }
867
868 int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) {
869 int r, boot_mounted;
870
871 assert(m);
872 assert(where);
873
874 if (!m->partitions[PARTITION_ROOT].found)
875 return -ENXIO;
876
877 if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) {
878 r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
879 if (r < 0)
880 return r;
881
882 if (flags & DISSECT_IMAGE_VALIDATE_OS) {
883 r = path_is_os_tree(where);
884 if (r < 0)
885 return r;
886 if (r == 0)
887 return -EMEDIUMTYPE;
888 }
889 }
890
891 if (flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY)
892 return 0;
893
894 r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags);
895 if (r < 0)
896 return r;
897
898 r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", uid_shift, flags);
899 if (r < 0)
900 return r;
901
902 boot_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, flags);
903 if (boot_mounted < 0)
904 return boot_mounted;
905
906 if (m->partitions[PARTITION_ESP].found) {
907 /* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it
908 * exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */
909
910 r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL);
911 if (r >= 0) {
912 r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags);
913 if (r < 0)
914 return r;
915
916 } else if (boot_mounted <= 0) {
917 _cleanup_free_ char *p = NULL;
918
919 r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p);
920 if (r >= 0 && dir_is_empty(p) > 0) {
921 r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags);
922 if (r < 0)
923 return r;
924 }
925 }
926 }
927
928 return 0;
929 }
930
931 #if HAVE_LIBCRYPTSETUP
932 typedef struct DecryptedPartition {
933 struct crypt_device *device;
934 char *name;
935 bool relinquished;
936 } DecryptedPartition;
937
938 struct DecryptedImage {
939 DecryptedPartition *decrypted;
940 size_t n_decrypted;
941 size_t n_allocated;
942 };
943 #endif
944
945 DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
946 #if HAVE_LIBCRYPTSETUP
947 size_t i;
948 int r;
949
950 if (!d)
951 return NULL;
952
953 for (i = 0; i < d->n_decrypted; i++) {
954 DecryptedPartition *p = d->decrypted + i;
955
956 if (p->device && p->name && !p->relinquished) {
957 r = crypt_deactivate(p->device, p->name);
958 if (r < 0)
959 log_debug_errno(r, "Failed to deactivate encrypted partition %s", p->name);
960 }
961
962 if (p->device)
963 crypt_free(p->device);
964 free(p->name);
965 }
966
967 free(d);
968 #endif
969 return NULL;
970 }
971
972 #if HAVE_LIBCRYPTSETUP
973
974 static int make_dm_name_and_node(const void *original_node, const char *suffix, char **ret_name, char **ret_node) {
975 _cleanup_free_ char *name = NULL, *node = NULL;
976 const char *base;
977
978 assert(original_node);
979 assert(suffix);
980 assert(ret_name);
981 assert(ret_node);
982
983 base = strrchr(original_node, '/');
984 if (!base)
985 return -EINVAL;
986 base++;
987 if (isempty(base))
988 return -EINVAL;
989
990 name = strjoin(base, suffix);
991 if (!name)
992 return -ENOMEM;
993 if (!filename_is_valid(name))
994 return -EINVAL;
995
996 node = strjoin(crypt_get_dir(), "/", name);
997 if (!node)
998 return -ENOMEM;
999
1000 *ret_name = TAKE_PTR(name);
1001 *ret_node = TAKE_PTR(node);
1002
1003 return 0;
1004 }
1005
1006 static int decrypt_partition(
1007 DissectedPartition *m,
1008 const char *passphrase,
1009 DissectImageFlags flags,
1010 DecryptedImage *d) {
1011
1012 _cleanup_free_ char *node = NULL, *name = NULL;
1013 _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
1014 int r;
1015
1016 assert(m);
1017 assert(d);
1018
1019 if (!m->found || !m->node || !m->fstype)
1020 return 0;
1021
1022 if (!streq(m->fstype, "crypto_LUKS"))
1023 return 0;
1024
1025 if (!passphrase)
1026 return -ENOKEY;
1027
1028 r = make_dm_name_and_node(m->node, "-decrypted", &name, &node);
1029 if (r < 0)
1030 return r;
1031
1032 if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
1033 return -ENOMEM;
1034
1035 r = crypt_init(&cd, m->node);
1036 if (r < 0)
1037 return log_debug_errno(r, "Failed to initialize dm-crypt: %m");
1038
1039 r = crypt_load(cd, CRYPT_LUKS, NULL);
1040 if (r < 0)
1041 return log_debug_errno(r, "Failed to load LUKS metadata: %m");
1042
1043 r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
1044 ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
1045 ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
1046 if (r < 0) {
1047 log_debug_errno(r, "Failed to activate LUKS device: %m");
1048 return r == -EPERM ? -EKEYREJECTED : r;
1049 }
1050
1051 d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
1052 d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
1053 d->n_decrypted++;
1054
1055 m->decrypted_node = TAKE_PTR(node);
1056
1057 return 0;
1058 }
1059
1060 static int verity_partition(
1061 DissectedPartition *m,
1062 DissectedPartition *v,
1063 const void *root_hash,
1064 size_t root_hash_size,
1065 DissectImageFlags flags,
1066 DecryptedImage *d) {
1067
1068 _cleanup_free_ char *node = NULL, *name = NULL;
1069 _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
1070 int r;
1071
1072 assert(m);
1073 assert(v);
1074
1075 if (!root_hash)
1076 return 0;
1077
1078 if (!m->found || !m->node || !m->fstype)
1079 return 0;
1080 if (!v->found || !v->node || !v->fstype)
1081 return 0;
1082
1083 if (!streq(v->fstype, "DM_verity_hash"))
1084 return 0;
1085
1086 r = make_dm_name_and_node(m->node, "-verity", &name, &node);
1087 if (r < 0)
1088 return r;
1089
1090 if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
1091 return -ENOMEM;
1092
1093 r = crypt_init(&cd, v->node);
1094 if (r < 0)
1095 return r;
1096
1097 r = crypt_load(cd, CRYPT_VERITY, NULL);
1098 if (r < 0)
1099 return r;
1100
1101 r = crypt_set_data_device(cd, m->node);
1102 if (r < 0)
1103 return r;
1104
1105 r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
1106 if (r < 0)
1107 return r;
1108
1109 d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
1110 d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
1111 d->n_decrypted++;
1112
1113 m->decrypted_node = TAKE_PTR(node);
1114
1115 return 0;
1116 }
1117 #endif
1118
1119 int dissected_image_decrypt(
1120 DissectedImage *m,
1121 const char *passphrase,
1122 const void *root_hash,
1123 size_t root_hash_size,
1124 DissectImageFlags flags,
1125 DecryptedImage **ret) {
1126
1127 #if HAVE_LIBCRYPTSETUP
1128 _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
1129 unsigned i;
1130 int r;
1131 #endif
1132
1133 assert(m);
1134 assert(root_hash || root_hash_size == 0);
1135
1136 /* Returns:
1137 *
1138 * = 0 → There was nothing to decrypt
1139 * > 0 → Decrypted successfully
1140 * -ENOKEY → There's something to decrypt but no key was supplied
1141 * -EKEYREJECTED → Passed key was not correct
1142 */
1143
1144 if (root_hash && root_hash_size < sizeof(sd_id128_t))
1145 return -EINVAL;
1146
1147 if (!m->encrypted && !m->verity) {
1148 *ret = NULL;
1149 return 0;
1150 }
1151
1152 #if HAVE_LIBCRYPTSETUP
1153 d = new0(DecryptedImage, 1);
1154 if (!d)
1155 return -ENOMEM;
1156
1157 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
1158 DissectedPartition *p = m->partitions + i;
1159 int k;
1160
1161 if (!p->found)
1162 continue;
1163
1164 r = decrypt_partition(p, passphrase, flags, d);
1165 if (r < 0)
1166 return r;
1167
1168 k = PARTITION_VERITY_OF(i);
1169 if (k >= 0) {
1170 r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, flags, d);
1171 if (r < 0)
1172 return r;
1173 }
1174
1175 if (!p->decrypted_fstype && p->decrypted_node) {
1176 r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype);
1177 if (r < 0 && r != -EUCLEAN)
1178 return r;
1179 }
1180 }
1181
1182 *ret = TAKE_PTR(d);
1183
1184 return 1;
1185 #else
1186 return -EOPNOTSUPP;
1187 #endif
1188 }
1189
1190 int dissected_image_decrypt_interactively(
1191 DissectedImage *m,
1192 const char *passphrase,
1193 const void *root_hash,
1194 size_t root_hash_size,
1195 DissectImageFlags flags,
1196 DecryptedImage **ret) {
1197
1198 _cleanup_strv_free_erase_ char **z = NULL;
1199 int n = 3, r;
1200
1201 if (passphrase)
1202 n--;
1203
1204 for (;;) {
1205 r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, flags, ret);
1206 if (r >= 0)
1207 return r;
1208 if (r == -EKEYREJECTED)
1209 log_error_errno(r, "Incorrect passphrase, try again!");
1210 else if (r != -ENOKEY)
1211 return log_error_errno(r, "Failed to decrypt image: %m");
1212
1213 if (--n < 0)
1214 return log_error_errno(SYNTHETIC_ERRNO(EKEYREJECTED),
1215 "Too many retries.");
1216
1217 z = strv_free(z);
1218
1219 r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
1220 if (r < 0)
1221 return log_error_errno(r, "Failed to query for passphrase: %m");
1222
1223 passphrase = z[0];
1224 }
1225 }
1226
1227 #if HAVE_LIBCRYPTSETUP
1228 static int deferred_remove(DecryptedPartition *p) {
1229 struct dm_ioctl dm = {
1230 .version = {
1231 DM_VERSION_MAJOR,
1232 DM_VERSION_MINOR,
1233 DM_VERSION_PATCHLEVEL
1234 },
1235 .data_size = sizeof(dm),
1236 .flags = DM_DEFERRED_REMOVE,
1237 };
1238
1239 _cleanup_close_ int fd = -1;
1240
1241 assert(p);
1242
1243 /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
1244
1245 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
1246 if (fd < 0)
1247 return -errno;
1248
1249 if (strlen(p->name) > sizeof(dm.name))
1250 return -ENAMETOOLONG;
1251
1252 strncpy(dm.name, p->name, sizeof(dm.name));
1253
1254 if (ioctl(fd, DM_DEV_REMOVE, &dm))
1255 return -errno;
1256
1257 return 0;
1258 }
1259 #endif
1260
1261 int decrypted_image_relinquish(DecryptedImage *d) {
1262
1263 #if HAVE_LIBCRYPTSETUP
1264 size_t i;
1265 int r;
1266 #endif
1267
1268 assert(d);
1269
1270 /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
1271 * that we don't clean it up ourselves either anymore */
1272
1273 #if HAVE_LIBCRYPTSETUP
1274 for (i = 0; i < d->n_decrypted; i++) {
1275 DecryptedPartition *p = d->decrypted + i;
1276
1277 if (p->relinquished)
1278 continue;
1279
1280 r = deferred_remove(p);
1281 if (r < 0)
1282 return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);
1283
1284 p->relinquished = true;
1285 }
1286 #endif
1287
1288 return 0;
1289 }
1290
1291 int root_hash_load(const char *image, void **ret, size_t *ret_size) {
1292 _cleanup_free_ char *text = NULL;
1293 _cleanup_free_ void *k = NULL;
1294 size_t l;
1295 int r;
1296
1297 assert(image);
1298 assert(ret);
1299 assert(ret_size);
1300
1301 if (is_device_path(image)) {
1302 /* If we are asked to load the root hash for a device node, exit early */
1303 *ret = NULL;
1304 *ret_size = 0;
1305 return 0;
1306 }
1307
1308 r = getxattr_malloc(image, "user.verity.roothash", &text, true);
1309 if (r < 0) {
1310 char *fn, *e, *n;
1311
1312 if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
1313 return r;
1314
1315 fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
1316 n = stpcpy(fn, image);
1317 e = endswith(fn, ".raw");
1318 if (e)
1319 n = e;
1320
1321 strcpy(n, ".roothash");
1322
1323 r = read_one_line_file(fn, &text);
1324 if (r == -ENOENT) {
1325 *ret = NULL;
1326 *ret_size = 0;
1327 return 0;
1328 }
1329 if (r < 0)
1330 return r;
1331 }
1332
1333 r = unhexmem(text, strlen(text), &k, &l);
1334 if (r < 0)
1335 return r;
1336 if (l < sizeof(sd_id128_t))
1337 return -EINVAL;
1338
1339 *ret = TAKE_PTR(k);
1340 *ret_size = l;
1341
1342 return 1;
1343 }
1344
1345 int dissected_image_acquire_metadata(DissectedImage *m) {
1346
1347 enum {
1348 META_HOSTNAME,
1349 META_MACHINE_ID,
1350 META_MACHINE_INFO,
1351 META_OS_RELEASE,
1352 _META_MAX,
1353 };
1354
1355 static const char *const paths[_META_MAX] = {
1356 [META_HOSTNAME] = "/etc/hostname\0",
1357 [META_MACHINE_ID] = "/etc/machine-id\0",
1358 [META_MACHINE_INFO] = "/etc/machine-info\0",
1359 [META_OS_RELEASE] = "/etc/os-release\0/usr/lib/os-release\0",
1360 };
1361
1362 _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL;
1363 _cleanup_(rmdir_and_freep) char *t = NULL;
1364 _cleanup_(sigkill_waitp) pid_t child = 0;
1365 sd_id128_t machine_id = SD_ID128_NULL;
1366 _cleanup_free_ char *hostname = NULL;
1367 unsigned n_meta_initialized = 0, k;
1368 int fds[2 * _META_MAX], r;
1369
1370 BLOCK_SIGNALS(SIGCHLD);
1371
1372 assert(m);
1373
1374 for (; n_meta_initialized < _META_MAX; n_meta_initialized ++)
1375 if (pipe2(fds + 2*n_meta_initialized, O_CLOEXEC) < 0) {
1376 r = -errno;
1377 goto finish;
1378 }
1379
1380 r = mkdtemp_malloc("/tmp/dissect-XXXXXX", &t);
1381 if (r < 0)
1382 goto finish;
1383
1384 r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
1385 if (r < 0)
1386 goto finish;
1387 if (r == 0) {
1388 r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS);
1389 if (r < 0) {
1390 log_debug_errno(r, "Failed to mount dissected image: %m");
1391 _exit(EXIT_FAILURE);
1392 }
1393
1394 for (k = 0; k < _META_MAX; k++) {
1395 _cleanup_close_ int fd = -1;
1396 const char *p;
1397
1398 fds[2*k] = safe_close(fds[2*k]);
1399
1400 NULSTR_FOREACH(p, paths[k]) {
1401 fd = chase_symlinks_and_open(p, t, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
1402 if (fd >= 0)
1403 break;
1404 }
1405 if (fd < 0) {
1406 log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]);
1407 continue;
1408 }
1409
1410 r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0);
1411 if (r < 0)
1412 _exit(EXIT_FAILURE);
1413
1414 fds[2*k+1] = safe_close(fds[2*k+1]);
1415 }
1416
1417 _exit(EXIT_SUCCESS);
1418 }
1419
1420 for (k = 0; k < _META_MAX; k++) {
1421 _cleanup_fclose_ FILE *f = NULL;
1422
1423 fds[2*k+1] = safe_close(fds[2*k+1]);
1424
1425 f = fdopen(fds[2*k], "r");
1426 if (!f) {
1427 r = -errno;
1428 goto finish;
1429 }
1430
1431 fds[2*k] = -1;
1432
1433 switch (k) {
1434
1435 case META_HOSTNAME:
1436 r = read_etc_hostname_stream(f, &hostname);
1437 if (r < 0)
1438 log_debug_errno(r, "Failed to read /etc/hostname: %m");
1439
1440 break;
1441
1442 case META_MACHINE_ID: {
1443 _cleanup_free_ char *line = NULL;
1444
1445 r = read_line(f, LONG_LINE_MAX, &line);
1446 if (r < 0)
1447 log_debug_errno(r, "Failed to read /etc/machine-id: %m");
1448 else if (r == 33) {
1449 r = sd_id128_from_string(line, &machine_id);
1450 if (r < 0)
1451 log_debug_errno(r, "Image contains invalid /etc/machine-id: %s", line);
1452 } else if (r == 0)
1453 log_debug("/etc/machine-id file is empty.");
1454 else
1455 log_debug("/etc/machine-id has unexpected length %i.", r);
1456
1457 break;
1458 }
1459
1460 case META_MACHINE_INFO:
1461 r = load_env_file_pairs(f, "machine-info", &machine_info);
1462 if (r < 0)
1463 log_debug_errno(r, "Failed to read /etc/machine-info: %m");
1464
1465 break;
1466
1467 case META_OS_RELEASE:
1468 r = load_env_file_pairs(f, "os-release", &os_release);
1469 if (r < 0)
1470 log_debug_errno(r, "Failed to read OS release file: %m");
1471
1472 break;
1473 }
1474 }
1475
1476 r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
1477 child = 0;
1478 if (r < 0)
1479 goto finish;
1480 if (r != EXIT_SUCCESS)
1481 return -EPROTO;
1482
1483 free_and_replace(m->hostname, hostname);
1484 m->machine_id = machine_id;
1485 strv_free_and_replace(m->machine_info, machine_info);
1486 strv_free_and_replace(m->os_release, os_release);
1487
1488 finish:
1489 for (k = 0; k < n_meta_initialized; k++)
1490 safe_close_pair(fds + 2*k);
1491
1492 return r;
1493 }
1494
1495 int dissect_image_and_warn(
1496 int fd,
1497 const char *name,
1498 const void *root_hash,
1499 size_t root_hash_size,
1500 DissectImageFlags flags,
1501 DissectedImage **ret) {
1502
1503 _cleanup_free_ char *buffer = NULL;
1504 int r;
1505
1506 if (!name) {
1507 r = fd_get_path(fd, &buffer);
1508 if (r < 0)
1509 return r;
1510
1511 name = buffer;
1512 }
1513
1514 r = dissect_image(fd, root_hash, root_hash_size, flags, ret);
1515
1516 switch (r) {
1517
1518 case -EOPNOTSUPP:
1519 return log_error_errno(r, "Dissecting images is not supported, compiled without blkid support.");
1520
1521 case -ENOPKG:
1522 return log_error_errno(r, "Couldn't identify a suitable partition table or file system in '%s'.", name);
1523
1524 case -EADDRNOTAVAIL:
1525 return log_error_errno(r, "No root partition for specified root hash found in '%s'.", name);
1526
1527 case -ENOTUNIQ:
1528 return log_error_errno(r, "Multiple suitable root partitions found in image '%s'.", name);
1529
1530 case -ENXIO:
1531 return log_error_errno(r, "No suitable root partition found in image '%s'.", name);
1532
1533 case -EPROTONOSUPPORT:
1534 return log_error_errno(r, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", name);
1535
1536 default:
1537 if (r < 0)
1538 return log_error_errno(r, "Failed to dissect image '%s': %m", name);
1539
1540 return r;
1541 }
1542 }
1543
1544 static const char *const partition_designator_table[] = {
1545 [PARTITION_ROOT] = "root",
1546 [PARTITION_ROOT_SECONDARY] = "root-secondary",
1547 [PARTITION_HOME] = "home",
1548 [PARTITION_SRV] = "srv",
1549 [PARTITION_ESP] = "esp",
1550 [PARTITION_XBOOTLDR] = "xbootldr",
1551 [PARTITION_SWAP] = "swap",
1552 [PARTITION_ROOT_VERITY] = "root-verity",
1553 [PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
1554 };
1555
1556 DEFINE_STRING_TABLE_LOOKUP(partition_designator, int);