]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/dissect-image.c
nspawn: when generating a machine name from an image name, truncate .raw suffix
[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"
8c1be37e
LP
31#include "gpt.h"
32#include "mount-util.h"
33#include "path-util.h"
34#include "stat-util.h"
18b5886e 35#include "stdio-util.h"
8c1be37e
LP
36#include "string-table.h"
37#include "string-util.h"
38#include "udev-util.h"
39
18b5886e
LP
40static int probe_filesystem(const char *node, char **ret_fstype) {
41#ifdef HAVE_BLKID
42 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
43 const char *fstype;
44 int r;
45
46 b = blkid_new_probe_from_filename(node);
47 if (!b)
48 return -ENOMEM;
49
50 blkid_probe_enable_superblocks(b, 1);
51 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
52
53 errno = 0;
54 r = blkid_do_safeprobe(b);
55 if (r == -2 || r == 1) {
56 log_debug("Failed to identify any partition type on partition %s", node);
57 goto not_found;
58 }
59 if (r != 0) {
60 if (errno == 0)
61 return -EIO;
62
63 return -errno;
64 }
65
66 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
67
68 if (fstype) {
69 char *t;
70
71 t = strdup(fstype);
72 if (!t)
73 return -ENOMEM;
74
75 *ret_fstype = t;
76 return 1;
77 }
78
79not_found:
80 *ret_fstype = NULL;
81 return 0;
82#else
83 return -EOPNOTSUPP;
84#endif
85}
86
8c1be37e
LP
87int dissect_image(int fd, DissectedImage **ret) {
88
89#ifdef HAVE_BLKID
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;
97 const char *pttype = NULL, *usage = NULL;
98 struct udev_list_entry *first, *item;
99 blkid_partlist pl;
100 int r, generic_nr;
101 struct stat st;
102 unsigned i;
103
104 assert(fd >= 0);
105 assert(ret);
106
107 /* Probes a disk image, and returns information about what it found in *ret.
108 *
109 * Returns -ENOPKG if no suitable partition table or file system could be found. */
110
111 if (fstat(fd, &st) < 0)
112 return -errno;
113
114 if (!S_ISBLK(st.st_mode))
115 return -ENOTBLK;
116
117 b = blkid_new_probe();
118 if (!b)
119 return -ENOMEM;
120
121 errno = 0;
122 r = blkid_probe_set_device(b, fd, 0, 0);
123 if (r != 0) {
124 if (errno == 0)
125 return -ENOMEM;
126
127 return -errno;
128 }
129
130 blkid_probe_enable_superblocks(b, 1);
131 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE);
132 blkid_probe_enable_partitions(b, 1);
133 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
134
135 errno = 0;
136 r = blkid_do_safeprobe(b);
137 if (r == -2 || r == 1) {
138 log_debug("Failed to identify any partition table.");
139 return -ENOPKG;
140 }
141 if (r != 0) {
142 if (errno == 0)
143 return -EIO;
144
145 return -errno;
146 }
147
148 m = new0(DissectedImage, 1);
149 if (!m)
150 return -ENOMEM;
151
152 (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
18b5886e 153 if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
8c1be37e
LP
154 _cleanup_free_ char *t = NULL, *n = NULL;
155 const char *fstype = NULL;
156
157 /* OK, we have found a file system, that's our root partition then. */
158 (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
159
160 if (fstype) {
161 t = strdup(fstype);
162 if (!t)
163 return -ENOMEM;
164 }
165
166 if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
167 return -ENOMEM;
168
169 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
170 .found = true,
171 .rw = true,
172 .partno = -1,
173 .architecture = _ARCHITECTURE_INVALID,
174 .fstype = t,
175 .node = n,
176 };
177
178 t = n = NULL;
179
18b5886e
LP
180 m->encrypted = streq(fstype, "crypto_LUKS");
181
8c1be37e
LP
182 *ret = m;
183 m = NULL;
184
185 return 0;
186 }
187
188 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
189 if (!pttype)
190 return -ENOPKG;
191
192 is_gpt = streq_ptr(pttype, "gpt");
193 is_mbr = streq_ptr(pttype, "dos");
194
195 if (!is_gpt && !is_mbr)
196 return -ENOPKG;
197
198 errno = 0;
199 pl = blkid_probe_get_partitions(b);
200 if (!pl) {
201 if (errno == 0)
202 return -ENOMEM;
203
204 return -errno;
205 }
206
207 udev = udev_new();
208 if (!udev)
209 return -errno;
210
211 d = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
212 if (!d)
213 return -ENOMEM;
214
215 for (i = 0;; i++) {
216 int n, z;
217
218 if (i >= 10) {
219 log_debug("Kernel partitions never appeared.");
220 return -ENXIO;
221 }
222
223 e = udev_enumerate_new(udev);
224 if (!e)
225 return -errno;
226
227 r = udev_enumerate_add_match_parent(e, d);
228 if (r < 0)
229 return r;
230
231 r = udev_enumerate_scan_devices(e);
232 if (r < 0)
233 return r;
234
235 /* Count the partitions enumerated by the kernel */
236 n = 0;
237 first = udev_enumerate_get_list_entry(e);
238 udev_list_entry_foreach(item, first)
239 n++;
240
241 /* Count the partitions enumerated by blkid */
242 z = blkid_partlist_numof_partitions(pl);
243 if (n == z + 1)
244 break;
245 if (n > z + 1) {
246 log_debug("blkid and kernel partition list do not match.");
247 return -EIO;
248 }
249 if (n < z + 1) {
250 unsigned j;
251
252 /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running
253 * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a
254 * synchronous call that waits until probing is complete. */
255
256 for (j = 0; j < 20; j++) {
257
258 r = ioctl(fd, BLKRRPART, 0);
259 if (r < 0)
260 r = -errno;
261 if (r >= 0 || r != -EBUSY)
262 break;
263
264 /* If something else has the device open, such as an udev rule, the ioctl will return
265 * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a
266 * bit, and try again.
267 *
268 * This is really something they should fix in the kernel! */
269
270 usleep(50 * USEC_PER_MSEC);
271 }
272
273 if (r < 0)
274 return r;
275 }
276
277 e = udev_enumerate_unref(e);
278 }
279
280 first = udev_enumerate_get_list_entry(e);
281 udev_list_entry_foreach(item, first) {
282 _cleanup_udev_device_unref_ struct udev_device *q;
283 unsigned long long flags;
284 blkid_partition pp;
285 const char *node;
286 dev_t qn;
287 int nr;
288
289 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
290 if (!q)
291 return -errno;
292
293 qn = udev_device_get_devnum(q);
294 if (major(qn) == 0)
295 continue;
296
297 if (st.st_rdev == qn)
298 continue;
299
300 node = udev_device_get_devnode(q);
301 if (!node)
302 continue;
303
304 pp = blkid_partlist_devno_to_partition(pl, qn);
305 if (!pp)
306 continue;
307
308 flags = blkid_partition_get_flags(pp);
309
310 nr = blkid_partition_get_partno(pp);
311 if (nr < 0)
312 continue;
313
314 if (is_gpt) {
315 int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID;
316 const char *stype, *fstype = NULL;
317 sd_id128_t type_id;
318 bool rw = true;
319
320 if (flags & GPT_FLAG_NO_AUTO)
321 continue;
322
323 stype = blkid_partition_get_type_string(pp);
324 if (!stype)
325 continue;
326
327 if (sd_id128_from_string(stype, &type_id) < 0)
328 continue;
329
330 if (sd_id128_equal(type_id, GPT_HOME)) {
331 designator = PARTITION_HOME;
332 rw = !(flags & GPT_FLAG_READ_ONLY);
333 } else if (sd_id128_equal(type_id, GPT_SRV)) {
334 designator = PARTITION_SRV;
335 rw = !(flags & GPT_FLAG_READ_ONLY);
336 } else if (sd_id128_equal(type_id, GPT_ESP)) {
337 designator = PARTITION_ESP;
338 fstype = "vfat";
339 }
340#ifdef GPT_ROOT_NATIVE
341 else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
342 designator = PARTITION_ROOT;
343 architecture = native_architecture();
344 rw = !(flags & GPT_FLAG_READ_ONLY);
345 }
346#endif
347#ifdef GPT_ROOT_SECONDARY
348 else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
349 designator = PARTITION_ROOT_SECONDARY;
350 architecture = SECONDARY_ARCHITECTURE;
351 rw = !(flags & GPT_FLAG_READ_ONLY);
352 }
353#endif
354 else if (sd_id128_equal(type_id, GPT_SWAP)) {
355 designator = PARTITION_SWAP;
356 fstype = "swap";
357 } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
358
359 if (generic_node)
360 multiple_generic = true;
361 else {
362 generic_nr = nr;
363 generic_rw = !(flags & GPT_FLAG_READ_ONLY);
364 generic_node = strdup(node);
365 if (!generic_node)
366 return -ENOMEM;
367 }
368 }
369
370 if (designator != _PARTITION_DESIGNATOR_INVALID) {
371 _cleanup_free_ char *t = NULL, *n = NULL;
372
373 /* First one wins */
374 if (m->partitions[designator].found)
375 continue;
376
377 if (fstype) {
378 t = strdup(fstype);
379 if (!t)
380 return -ENOMEM;
381 }
382
383 n = strdup(node);
384 if (!n)
385 return -ENOMEM;
386
387 m->partitions[designator] = (DissectedPartition) {
388 .found = true,
389 .partno = nr,
390 .rw = rw,
391 .architecture = architecture,
392 .node = n,
393 .fstype = t,
394 };
395
396 n = t = NULL;
397 }
398
399 } else if (is_mbr) {
400
401 if (flags != 0x80) /* Bootable flag */
402 continue;
403
404 if (blkid_partition_get_type(pp) != 0x83) /* Linux partition */
405 continue;
406
407 if (generic_node)
408 multiple_generic = true;
409 else {
410 generic_nr = nr;
411 generic_rw = true;
412 generic_node = strdup(node);
413 if (!generic_node)
414 return -ENOMEM;
415 }
416 }
417 }
418
419 if (!m->partitions[PARTITION_ROOT].found) {
420 /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
421 * either, then check if there's a single generic one, and use that. */
422
423 if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
424 m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
425 zero(m->partitions[PARTITION_ROOT_SECONDARY]);
426 } else if (generic_node) {
427
428 if (multiple_generic)
429 return -ENOTUNIQ;
430
431 m->partitions[PARTITION_ROOT] = (DissectedPartition) {
432 .found = true,
433 .rw = generic_rw,
434 .partno = generic_nr,
435 .architecture = _ARCHITECTURE_INVALID,
436 .node = generic_node,
437 };
438
439 generic_node = NULL;
440 } else
441 return -ENXIO;
442 }
443
18b5886e
LP
444 blkid_free_probe(b);
445 b = NULL;
446
8c1be37e
LP
447 /* Fill in file system types if we don't know them yet. */
448 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
18b5886e 449 DissectedPartition *p = m->partitions + i;
8c1be37e 450
18b5886e 451 if (!p->found)
8c1be37e
LP
452 continue;
453
18b5886e
LP
454 if (!p->fstype && p->node) {
455 r = probe_filesystem(p->node, &p->fstype);
456 if (r < 0)
457 return r;
8c1be37e
LP
458 }
459
18b5886e
LP
460 if (streq_ptr(p->fstype, "crypto_LUKS"))
461 m->encrypted = true;
8c1be37e
LP
462 }
463
464 *ret = m;
465 m = NULL;
466
467 return 0;
468#else
469 return -EOPNOTSUPP;
470#endif
471}
472
473DissectedImage* dissected_image_unref(DissectedImage *m) {
474 unsigned i;
475
476 if (!m)
477 return NULL;
478
479 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
480 free(m->partitions[i].fstype);
481 free(m->partitions[i].node);
18b5886e
LP
482 free(m->partitions[i].decrypted_fstype);
483 free(m->partitions[i].decrypted_node);
8c1be37e
LP
484 }
485
486 free(m);
487 return NULL;
488}
489
18b5886e
LP
490static int is_loop_device(const char *path) {
491 char s[strlen("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen("/../loop/")];
492 struct stat st;
493
494 assert(path);
495
496 if (stat(path, &st) < 0)
497 return -errno;
498
499 if (!S_ISBLK(st.st_mode))
500 return -ENOTBLK;
501
502 xsprintf(s, "/sys/dev/block/%u:%u/loop/", major(st.st_rdev), minor(st.st_rdev));
503 if (access(s, F_OK) < 0) {
504 if (errno != ENOENT)
505 return -errno;
506
507 /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */
508 xsprintf(s, "/sys/dev/block/%u:%u/../loop/", major(st.st_rdev), minor(st.st_rdev));
509 if (access(s, F_OK) < 0)
510 return errno == ENOENT ? false : -errno;
511 }
512
513 return true;
514}
515
516static int mount_partition(
517 DissectedPartition *m,
518 const char *where,
519 const char *directory,
520 DissectImageFlags flags) {
521
522 const char *p, *options = NULL, *node, *fstype;
8c1be37e
LP
523 bool rw;
524
525 assert(m);
526 assert(where);
527
18b5886e
LP
528 node = m->decrypted_node ?: m->node;
529 fstype = m->decrypted_fstype ?: m->fstype;
530
531 if (!m->found || !node || !fstype)
8c1be37e
LP
532 return 0;
533
18b5886e
LP
534 /* Stacked encryption? Yuck */
535 if (streq_ptr(fstype, "crypto_LUKS"))
536 return -ELOOP;
537
538 rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
8c1be37e
LP
539
540 if (directory)
541 p = strjoina(where, directory);
542 else
543 p = where;
544
18b5886e
LP
545 /* If requested, turn on discard support. */
546 if (STR_IN_SET(fstype, "btrfs", "ext4", "vfat", "xfs") &&
547 ((flags & DISSECT_IMAGE_DISCARD) ||
548 ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node))))
549 options = "discard";
8c1be37e 550
18b5886e 551 return mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
8c1be37e
LP
552}
553
18b5886e 554int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlags flags) {
8c1be37e
LP
555 int r;
556
557 assert(m);
558 assert(where);
559
560 if (!m->partitions[PARTITION_ROOT].found)
561 return -ENXIO;
562
563 r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, flags);
564 if (r < 0)
565 return r;
566
567 r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", flags);
568 if (r < 0)
569 return r;
570
571 r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", flags);
572 if (r < 0)
573 return r;
574
575 if (m->partitions[PARTITION_ESP].found) {
576 const char *mp, *x;
577
578 /* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */
579
580 mp = "/efi";
581 x = strjoina(where, mp);
582 r = dir_is_empty(x);
583 if (r == -ENOENT) {
584 mp = "/boot";
585 x = strjoina(where, mp);
586 r = dir_is_empty(x);
587 }
588 if (r > 0) {
589 r = mount_partition(m->partitions + PARTITION_ESP, where, mp, flags);
590 if (r < 0)
591 return r;
592 }
593 }
594
595 return 0;
596}
597
18b5886e
LP
598#ifdef HAVE_LIBCRYPTSETUP
599typedef struct DecryptedPartition {
600 struct crypt_device *device;
601 char *name;
602 bool relinquished;
603} DecryptedPartition;
604
605struct DecryptedImage {
606 DecryptedPartition *decrypted;
607 size_t n_decrypted;
608 size_t n_allocated;
609};
610#endif
611
612DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
613#ifdef HAVE_LIBCRYPTSETUP
614 size_t i;
615 int r;
616
617 if (!d)
618 return NULL;
619
620 for (i = 0; i < d->n_decrypted; i++) {
621 DecryptedPartition *p = d->decrypted + i;
622
623 if (p->device && p->name && !p->relinquished) {
624 r = crypt_deactivate(p->device, p->name);
625 if (r < 0)
626 log_debug_errno(r, "Failed to deactivate encrypted partition %s", p->name);
627 }
628
629 if (p->device)
630 crypt_free(p->device);
631 free(p->name);
632 }
633
634 free(d);
635#endif
636 return NULL;
637}
638
639#ifdef HAVE_LIBCRYPTSETUP
640static int decrypt_partition(
641 DissectedPartition *m,
642 const char *passphrase,
643 DissectImageFlags flags,
644 DecryptedImage *d) {
645
646 _cleanup_free_ char *node = NULL, *name = NULL;
647 struct crypt_device *cd;
648 const char *suffix;
649 int r;
650
651 assert(m);
652 assert(d);
653
654 if (!m->found || !m->node || !m->fstype)
655 return 0;
656
657 if (!streq(m->fstype, "crypto_LUKS"))
658 return 0;
659
660 suffix = strrchr(m->node, '/');
661 if (!suffix)
662 return -EINVAL;
663 suffix++;
664 if (isempty(suffix))
665 return -EINVAL;
666
667 name = strjoin(suffix, "-decrypted");
668 if (!name)
669 return -ENOMEM;
670 if (!filename_is_valid(name))
671 return -EINVAL;
672
673 node = strjoin(crypt_get_dir(), "/", name);
674 if (!node)
675 return -ENOMEM;
676
677 if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
678 return -ENOMEM;
679
680 r = crypt_init(&cd, m->node);
681 if (r < 0)
682 return r;
683
684 r = crypt_load(cd, CRYPT_LUKS1, NULL);
685 if (r < 0)
686 goto fail;
687
688 r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
689 ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
690 ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
691 if (r == -EPERM) {
692 r = -EKEYREJECTED;
693 goto fail;
694 }
695 if (r < 0)
696 goto fail;
697
698 d->decrypted[d->n_decrypted].name = name;
699 name = NULL;
700
701 d->decrypted[d->n_decrypted].device = cd;
702 d->n_decrypted++;
703
704 m->decrypted_node = node;
705 node = NULL;
706
707 return 0;
708
709fail:
710 crypt_free(cd);
711 return r;
712}
713#endif
714
715int dissected_image_decrypt(
716 DissectedImage *m,
717 const char *passphrase,
718 DissectImageFlags flags,
719 DecryptedImage **ret) {
720
721 _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
722#ifdef HAVE_LIBCRYPTSETUP
723 unsigned i;
724 int r;
725#endif
726
727 assert(m);
728
729 /* Returns:
730 *
731 * = 0 → There was nothing to decrypt
732 * > 0 → Decrypted successfully
733 * -ENOKEY → There's some to decrypt but no key was supplied
734 * -EKEYREJECTED → Passed key was not correct
735 */
736
737 if (!m->encrypted) {
738 *ret = NULL;
739 return 0;
740 }
741
742#ifdef HAVE_LIBCRYPTSETUP
743 if (!passphrase)
744 return -ENOKEY;
745
746 d = new0(DecryptedImage, 1);
747 if (!d)
748 return -ENOMEM;
749
750 for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
751 DissectedPartition *p = m->partitions + i;
752
753 if (!p->found)
754 continue;
755
756 r = decrypt_partition(p, passphrase, flags, d);
757 if (r < 0)
758 return r;
759
760 if (!p->decrypted_fstype && p->decrypted_node) {
761 r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype);
762 if (r < 0)
763 return r;
764 }
765 }
766
767 *ret = d;
768 d = NULL;
769
770 return 1;
771#else
772 return -EOPNOTSUPP;
773#endif
774}
775
776int dissected_image_decrypt_interactively(
777 DissectedImage *m,
778 const char *passphrase,
779 DissectImageFlags flags,
780 DecryptedImage **ret) {
781
782 _cleanup_strv_free_erase_ char **z = NULL;
783 int n = 3, r;
784
785 if (passphrase)
786 n--;
787
788 for (;;) {
789 r = dissected_image_decrypt(m, passphrase, flags, ret);
790 if (r >= 0)
791 return r;
792 if (r == -EKEYREJECTED)
793 log_error_errno(r, "Incorrect passphrase, try again!");
794 else if (r != -ENOKEY) {
795 log_error_errno(r, "Failed to decrypt image: %m");
796 return r;
797 }
798
799 if (--n < 0) {
800 log_error("Too many retries.");
801 return -EKEYREJECTED;
802 }
803
804 z = strv_free(z);
805
806 r = ask_password_auto("Please enter image passphrase!", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
807 if (r < 0)
808 return log_error_errno(r, "Failed to query for passphrase: %m");
809
810 passphrase = z[0];
811 }
812}
813
814#ifdef HAVE_LIBCRYPTSETUP
815static int deferred_remove(DecryptedPartition *p) {
816
817 struct dm_ioctl dm = {
818 .version = {
819 DM_VERSION_MAJOR,
820 DM_VERSION_MINOR,
821 DM_VERSION_PATCHLEVEL
822 },
823 .data_size = sizeof(dm),
824 .flags = DM_DEFERRED_REMOVE,
825 };
826
827 _cleanup_close_ int fd = -1;
828
829 assert(p);
830
831 /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
832
833 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
834 if (fd < 0)
835 return -errno;
836
837 strncpy(dm.name, p->name, sizeof(dm.name));
838
839 if (ioctl(fd, DM_DEV_REMOVE, &dm))
840 return -errno;
841
842 return 0;
843}
844#endif
845
846int decrypted_image_relinquish(DecryptedImage *d) {
847
848#ifdef HAVE_LIBCRYPTSETUP
849 size_t i;
850 int r;
851#endif
852
853 assert(d);
854
855 /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
856 * that we don't clean it up ourselves either anymore */
857
858#ifdef HAVE_LIBCRYPTSETUP
859 for (i = 0; i < d->n_decrypted; i++) {
860 DecryptedPartition *p = d->decrypted + i;
861
862 if (p->relinquished)
863 continue;
864
865 r = deferred_remove(p);
866 if (r < 0)
867 return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);
868
869 p->relinquished = true;
870 }
871#endif
872
873 return 0;
874}
875
8c1be37e
LP
876static const char *const partition_designator_table[] = {
877 [PARTITION_ROOT] = "root",
878 [PARTITION_ROOT_SECONDARY] = "root-secondary",
879 [PARTITION_HOME] = "home",
880 [PARTITION_SRV] = "srv",
881 [PARTITION_ESP] = "esp",
882 [PARTITION_SWAP] = "swap",
883};
884
885DEFINE_STRING_TABLE_LOOKUP(partition_designator, int);