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