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