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