]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/partition/repart.c
tree-wide: use IOVEC_MAKE() in a couple more places
[thirdparty/systemd.git] / src / partition / repart.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #if HAVE_VALGRIND_MEMCHECK_H
4 #include <valgrind/memcheck.h>
5 #endif
6
7 #include <fcntl.h>
8 #include <getopt.h>
9 #include <linux/fs.h>
10 #include <linux/loop.h>
11 #include <sys/file.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14
15 #include "sd-device.h"
16 #include "sd-id128.h"
17
18 #include "alloc-util.h"
19 #include "blkid-util.h"
20 #include "blockdev-util.h"
21 #include "btrfs-util.h"
22 #include "build.h"
23 #include "chase.h"
24 #include "conf-files.h"
25 #include "conf-parser.h"
26 #include "constants.h"
27 #include "cryptsetup-util.h"
28 #include "device-util.h"
29 #include "devnum-util.h"
30 #include "dirent-util.h"
31 #include "efivars.h"
32 #include "errno-util.h"
33 #include "fd-util.h"
34 #include "fdisk-util.h"
35 #include "fileio.h"
36 #include "format-table.h"
37 #include "format-util.h"
38 #include "fs-util.h"
39 #include "glyph-util.h"
40 #include "gpt.h"
41 #include "hexdecoct.h"
42 #include "hmac.h"
43 #include "id128-util.h"
44 #include "initrd-util.h"
45 #include "io-util.h"
46 #include "json.h"
47 #include "list.h"
48 #include "loop-util.h"
49 #include "main-func.h"
50 #include "mkdir.h"
51 #include "mkfs-util.h"
52 #include "mount-util.h"
53 #include "mountpoint-util.h"
54 #include "nulstr-util.h"
55 #include "openssl-util.h"
56 #include "parse-argument.h"
57 #include "parse-helpers.h"
58 #include "pretty-print.h"
59 #include "proc-cmdline.h"
60 #include "process-util.h"
61 #include "random-util.h"
62 #include "resize-fs.h"
63 #include "rm-rf.h"
64 #include "sort-util.h"
65 #include "specifier.h"
66 #include "stdio-util.h"
67 #include "string-table.h"
68 #include "string-util.h"
69 #include "strv.h"
70 #include "sync-util.h"
71 #include "terminal-util.h"
72 #include "tmpfile-util.h"
73 #include "tpm2-pcr.h"
74 #include "tpm2-util.h"
75 #include "user-util.h"
76 #include "utf8.h"
77
78 /* If not configured otherwise use a minimal partition size of 10M */
79 #define DEFAULT_MIN_SIZE (10ULL*1024ULL*1024ULL)
80
81 /* Hard lower limit for new partition sizes */
82 #define HARD_MIN_SIZE 4096ULL
83
84 /* We know up front we're never going to put more than this in a verity sig partition. */
85 #define VERITY_SIG_SIZE (HARD_MIN_SIZE*4ULL)
86
87 /* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */
88 #define GPT_METADATA_SIZE (1044ULL*1024ULL)
89
90 /* LUKS2 takes off 16M of the partition size with its metadata by default */
91 #define LUKS2_METADATA_SIZE (16ULL*1024ULL*1024ULL)
92
93 /* To do LUKS2 offline encryption, we need to keep some extra free space at the end of the partition. */
94 #define LUKS2_METADATA_KEEP_FREE (LUKS2_METADATA_SIZE*2ULL)
95
96 /* LUKS2 volume key size. */
97 #define VOLUME_KEY_SIZE (512ULL/8ULL)
98
99 /* Use 4K as the default filesystem sector size because as long as the partitions are aligned to 4K, the
100 * filesystems will then also be compatible with sector sizes 512, 1024 and 2048. */
101 #define DEFAULT_FILESYSTEM_SECTOR_SIZE 4096ULL
102
103 #define APIVFS_TMP_DIRS_NULSTR "proc\0sys\0dev\0tmp\0run\0var/tmp\0"
104
105 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
106 * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
107 * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
108 * waste 3K per partition, which is probably fine. */
109
110 typedef enum EmptyMode {
111 EMPTY_UNSET, /* no choice has been made yet */
112 EMPTY_REFUSE, /* refuse empty disks, never create a partition table */
113 EMPTY_ALLOW, /* allow empty disks, create partition table if necessary */
114 EMPTY_REQUIRE, /* require an empty disk, create a partition table */
115 EMPTY_FORCE, /* make disk empty, erase everything, create a partition table always */
116 EMPTY_CREATE, /* create disk as loopback file, create a partition table always */
117 _EMPTY_MODE_MAX,
118 _EMPTY_MODE_INVALID = -EINVAL,
119 } EmptyMode;
120
121 typedef enum FilterPartitionType {
122 FILTER_PARTITIONS_NONE,
123 FILTER_PARTITIONS_EXCLUDE,
124 FILTER_PARTITIONS_INCLUDE,
125 _FILTER_PARTITIONS_MAX,
126 _FILTER_PARTITIONS_INVALID = -EINVAL,
127 } FilterPartitionsType;
128
129 static EmptyMode arg_empty = EMPTY_UNSET;
130 static bool arg_dry_run = true;
131 static const char *arg_node = NULL;
132 static char *arg_root = NULL;
133 static char *arg_image = NULL;
134 static char **arg_definitions = NULL;
135 static bool arg_discard = true;
136 static bool arg_can_factory_reset = false;
137 static int arg_factory_reset = -1;
138 static sd_id128_t arg_seed = SD_ID128_NULL;
139 static bool arg_randomize = false;
140 static int arg_pretty = -1;
141 static uint64_t arg_size = UINT64_MAX;
142 static bool arg_size_auto = false;
143 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
144 static PagerFlags arg_pager_flags = 0;
145 static bool arg_legend = true;
146 static void *arg_key = NULL;
147 static size_t arg_key_size = 0;
148 static EVP_PKEY *arg_private_key = NULL;
149 static X509 *arg_certificate = NULL;
150 static char *arg_tpm2_device = NULL;
151 static uint32_t arg_tpm2_seal_key_handle = 0;
152 static char *arg_tpm2_device_key = NULL;
153 static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL;
154 static size_t arg_tpm2_n_hash_pcr_values = 0;
155 static char *arg_tpm2_public_key = NULL;
156 static uint32_t arg_tpm2_public_key_pcr_mask = 0;
157 static char *arg_tpm2_pcrlock = NULL;
158 static bool arg_split = false;
159 static GptPartitionType *arg_filter_partitions = NULL;
160 static size_t arg_n_filter_partitions = 0;
161 static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE;
162 static GptPartitionType *arg_defer_partitions = NULL;
163 static size_t arg_n_defer_partitions = 0;
164 static uint64_t arg_sector_size = 0;
165 static ImagePolicy *arg_image_policy = NULL;
166 static Architecture arg_architecture = _ARCHITECTURE_INVALID;
167 static int arg_offline = -1;
168 static char **arg_copy_from = NULL;
169 static char *arg_copy_source = NULL;
170 static char *arg_make_ddi = NULL;
171
172 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
173 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
174 STATIC_DESTRUCTOR_REGISTER(arg_definitions, strv_freep);
175 STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
176 STATIC_DESTRUCTOR_REGISTER(arg_private_key, EVP_PKEY_freep);
177 STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep);
178 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
179 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device_key, freep);
180 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, freep);
181 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
182 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
183 STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
184 STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
185 STATIC_DESTRUCTOR_REGISTER(arg_copy_from, strv_freep);
186 STATIC_DESTRUCTOR_REGISTER(arg_copy_source, freep);
187 STATIC_DESTRUCTOR_REGISTER(arg_make_ddi, freep);
188
189 typedef struct FreeArea FreeArea;
190
191 typedef enum EncryptMode {
192 ENCRYPT_OFF,
193 ENCRYPT_KEY_FILE,
194 ENCRYPT_TPM2,
195 ENCRYPT_KEY_FILE_TPM2,
196 _ENCRYPT_MODE_MAX,
197 _ENCRYPT_MODE_INVALID = -EINVAL,
198 } EncryptMode;
199
200 typedef enum VerityMode {
201 VERITY_OFF,
202 VERITY_DATA,
203 VERITY_HASH,
204 VERITY_SIG,
205 _VERITY_MODE_MAX,
206 _VERITY_MODE_INVALID = -EINVAL,
207 } VerityMode;
208
209 typedef enum MinimizeMode {
210 MINIMIZE_OFF,
211 MINIMIZE_BEST,
212 MINIMIZE_GUESS,
213 _MINIMIZE_MODE_MAX,
214 _MINIMIZE_MODE_INVALID = -EINVAL,
215 } MinimizeMode;
216
217 typedef struct Partition {
218 char *definition_path;
219 char **drop_in_files;
220
221 GptPartitionType type;
222 sd_id128_t current_uuid, new_uuid;
223 bool new_uuid_is_set;
224 char *current_label, *new_label;
225 sd_id128_t fs_uuid, luks_uuid, verity_uuid;
226 uint8_t verity_salt[SHA256_DIGEST_SIZE];
227
228 bool dropped;
229 bool factory_reset;
230 int32_t priority;
231
232 uint32_t weight, padding_weight;
233
234 uint64_t current_size, new_size;
235 uint64_t size_min, size_max;
236
237 uint64_t current_padding, new_padding;
238 uint64_t padding_min, padding_max;
239
240 uint64_t partno;
241 uint64_t offset;
242
243 struct fdisk_partition *current_partition;
244 struct fdisk_partition *new_partition;
245 FreeArea *padding_area;
246 FreeArea *allocated_to_area;
247
248 char *copy_blocks_path;
249 bool copy_blocks_path_is_our_file;
250 bool copy_blocks_auto;
251 const char *copy_blocks_root;
252 int copy_blocks_fd;
253 uint64_t copy_blocks_offset;
254 uint64_t copy_blocks_size;
255
256 char *format;
257 char **copy_files;
258 char **exclude_files_source;
259 char **exclude_files_target;
260 char **make_directories;
261 char **subvolumes;
262 EncryptMode encrypt;
263 VerityMode verity;
264 char *verity_match_key;
265 MinimizeMode minimize;
266 uint64_t verity_data_block_size;
267 uint64_t verity_hash_block_size;
268
269 uint64_t gpt_flags;
270 int no_auto;
271 int read_only;
272 int growfs;
273
274 struct iovec roothash;
275
276 char *split_name_format;
277 char *split_path;
278
279 struct Partition *siblings[_VERITY_MODE_MAX];
280
281 LIST_FIELDS(struct Partition, partitions);
282 } Partition;
283
284 #define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
285 #define PARTITION_EXISTS(p) (!!(p)->current_partition)
286
287 struct FreeArea {
288 Partition *after;
289 uint64_t size;
290 uint64_t allocated;
291 };
292
293 typedef struct Context {
294 LIST_HEAD(Partition, partitions);
295 size_t n_partitions;
296
297 FreeArea **free_areas;
298 size_t n_free_areas;
299
300 uint64_t start, end, total;
301
302 struct fdisk_context *fdisk_context;
303 uint64_t sector_size, grain_size, fs_sector_size;
304
305 sd_id128_t seed;
306
307 char *node;
308 bool node_is_our_file;
309 int backing_fd;
310
311 bool from_scratch;
312 } Context;
313
314 static const char *empty_mode_table[_EMPTY_MODE_MAX] = {
315 [EMPTY_UNSET] = "unset",
316 [EMPTY_REFUSE] = "refuse",
317 [EMPTY_ALLOW] = "allow",
318 [EMPTY_REQUIRE] = "require",
319 [EMPTY_FORCE] = "force",
320 [EMPTY_CREATE] = "create",
321 };
322
323 static const char *encrypt_mode_table[_ENCRYPT_MODE_MAX] = {
324 [ENCRYPT_OFF] = "off",
325 [ENCRYPT_KEY_FILE] = "key-file",
326 [ENCRYPT_TPM2] = "tpm2",
327 [ENCRYPT_KEY_FILE_TPM2] = "key-file+tpm2",
328 };
329
330 static const char *verity_mode_table[_VERITY_MODE_MAX] = {
331 [VERITY_OFF] = "off",
332 [VERITY_DATA] = "data",
333 [VERITY_HASH] = "hash",
334 [VERITY_SIG] = "signature",
335 };
336
337 static const char *minimize_mode_table[_MINIMIZE_MODE_MAX] = {
338 [MINIMIZE_OFF] = "off",
339 [MINIMIZE_BEST] = "best",
340 [MINIMIZE_GUESS] = "guess",
341 };
342
343 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(empty_mode, EmptyMode);
344 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE);
345 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(verity_mode, VerityMode);
346 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(minimize_mode, MinimizeMode, MINIMIZE_BEST);
347
348 static uint64_t round_down_size(uint64_t v, uint64_t p) {
349 return (v / p) * p;
350 }
351
352 static uint64_t round_up_size(uint64_t v, uint64_t p) {
353
354 v = DIV_ROUND_UP(v, p);
355
356 if (v > UINT64_MAX / p)
357 return UINT64_MAX; /* overflow */
358
359 return v * p;
360 }
361
362 static Partition *partition_new(void) {
363 Partition *p;
364
365 p = new(Partition, 1);
366 if (!p)
367 return NULL;
368
369 *p = (Partition) {
370 .weight = 1000,
371 .padding_weight = 0,
372 .current_size = UINT64_MAX,
373 .new_size = UINT64_MAX,
374 .size_min = UINT64_MAX,
375 .size_max = UINT64_MAX,
376 .current_padding = UINT64_MAX,
377 .new_padding = UINT64_MAX,
378 .padding_min = UINT64_MAX,
379 .padding_max = UINT64_MAX,
380 .partno = UINT64_MAX,
381 .offset = UINT64_MAX,
382 .copy_blocks_fd = -EBADF,
383 .copy_blocks_offset = UINT64_MAX,
384 .copy_blocks_size = UINT64_MAX,
385 .no_auto = -1,
386 .read_only = -1,
387 .growfs = -1,
388 .verity_data_block_size = UINT64_MAX,
389 .verity_hash_block_size = UINT64_MAX,
390 };
391
392 return p;
393 }
394
395 static Partition* partition_free(Partition *p) {
396 if (!p)
397 return NULL;
398
399 free(p->current_label);
400 free(p->new_label);
401 free(p->definition_path);
402 strv_free(p->drop_in_files);
403
404 if (p->current_partition)
405 fdisk_unref_partition(p->current_partition);
406 if (p->new_partition)
407 fdisk_unref_partition(p->new_partition);
408
409 if (p->copy_blocks_path_is_our_file)
410 unlink_and_free(p->copy_blocks_path);
411 else
412 free(p->copy_blocks_path);
413 safe_close(p->copy_blocks_fd);
414
415 free(p->format);
416 strv_free(p->copy_files);
417 strv_free(p->exclude_files_source);
418 strv_free(p->exclude_files_target);
419 strv_free(p->make_directories);
420 strv_free(p->subvolumes);
421 free(p->verity_match_key);
422
423 iovec_done(&p->roothash);
424
425 free(p->split_name_format);
426 unlink_and_free(p->split_path);
427
428 return mfree(p);
429 }
430
431 static void partition_foreignize(Partition *p) {
432 assert(p);
433 assert(PARTITION_EXISTS(p));
434
435 /* Reset several parameters set through definition file to make the partition foreign. */
436
437 p->definition_path = mfree(p->definition_path);
438 p->drop_in_files = strv_free(p->drop_in_files);
439
440 p->copy_blocks_path = mfree(p->copy_blocks_path);
441 p->copy_blocks_fd = safe_close(p->copy_blocks_fd);
442 p->copy_blocks_root = NULL;
443
444 p->format = mfree(p->format);
445 p->copy_files = strv_free(p->copy_files);
446 p->exclude_files_source = strv_free(p->exclude_files_source);
447 p->exclude_files_target = strv_free(p->exclude_files_target);
448 p->make_directories = strv_free(p->make_directories);
449 p->subvolumes = strv_free(p->subvolumes);
450 p->verity_match_key = mfree(p->verity_match_key);
451
452 p->priority = 0;
453 p->weight = 1000;
454 p->padding_weight = 0;
455 p->size_min = UINT64_MAX;
456 p->size_max = UINT64_MAX;
457 p->padding_min = UINT64_MAX;
458 p->padding_max = UINT64_MAX;
459 p->no_auto = -1;
460 p->read_only = -1;
461 p->growfs = -1;
462 p->verity = VERITY_OFF;
463 }
464
465 static bool partition_type_exclude(const GptPartitionType *type) {
466 if (arg_filter_partitions_type == FILTER_PARTITIONS_NONE)
467 return false;
468
469 for (size_t i = 0; i < arg_n_filter_partitions; i++)
470 if (sd_id128_equal(type->uuid, arg_filter_partitions[i].uuid))
471 return arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE;
472
473 return arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE;
474 }
475
476 static bool partition_type_defer(const GptPartitionType *type) {
477 for (size_t i = 0; i < arg_n_defer_partitions; i++)
478 if (sd_id128_equal(type->uuid, arg_defer_partitions[i].uuid))
479 return true;
480
481 return false;
482 }
483
484 static Partition* partition_unlink_and_free(Context *context, Partition *p) {
485 if (!p)
486 return NULL;
487
488 LIST_REMOVE(partitions, context->partitions, p);
489
490 assert(context->n_partitions > 0);
491 context->n_partitions--;
492
493 return partition_free(p);
494 }
495
496 DEFINE_TRIVIAL_CLEANUP_FUNC(Partition*, partition_free);
497
498 static Context *context_new(sd_id128_t seed) {
499 Context *context;
500
501 context = new(Context, 1);
502 if (!context)
503 return NULL;
504
505 *context = (Context) {
506 .start = UINT64_MAX,
507 .end = UINT64_MAX,
508 .total = UINT64_MAX,
509 .seed = seed,
510 };
511
512 return context;
513 }
514
515 static void context_free_free_areas(Context *context) {
516 assert(context);
517
518 for (size_t i = 0; i < context->n_free_areas; i++)
519 free(context->free_areas[i]);
520
521 context->free_areas = mfree(context->free_areas);
522 context->n_free_areas = 0;
523 }
524
525 static Context *context_free(Context *context) {
526 if (!context)
527 return NULL;
528
529 while (context->partitions)
530 partition_unlink_and_free(context, context->partitions);
531 assert(context->n_partitions == 0);
532
533 context_free_free_areas(context);
534
535 if (context->fdisk_context)
536 fdisk_unref_context(context->fdisk_context);
537
538 safe_close(context->backing_fd);
539 if (context->node_is_our_file)
540 unlink_and_free(context->node);
541 else
542 free(context->node);
543
544 return mfree(context);
545 }
546
547 DEFINE_TRIVIAL_CLEANUP_FUNC(Context*, context_free);
548
549 static int context_add_free_area(
550 Context *context,
551 uint64_t size,
552 Partition *after) {
553
554 FreeArea *a;
555
556 assert(context);
557 assert(!after || !after->padding_area);
558
559 if (!GREEDY_REALLOC(context->free_areas, context->n_free_areas + 1))
560 return -ENOMEM;
561
562 a = new(FreeArea, 1);
563 if (!a)
564 return -ENOMEM;
565
566 *a = (FreeArea) {
567 .size = size,
568 .after = after,
569 };
570
571 context->free_areas[context->n_free_areas++] = a;
572
573 if (after)
574 after->padding_area = a;
575
576 return 0;
577 }
578
579 static void partition_drop_or_foreignize(Partition *p) {
580 if (!p || p->dropped || PARTITION_IS_FOREIGN(p))
581 return;
582
583 if (PARTITION_EXISTS(p)) {
584 log_info("Can't grow existing partition %s of priority %" PRIi32 ", ignoring.",
585 strna(p->current_label ?: p->new_label), p->priority);
586
587 /* Handle the partition as foreign. Do not set dropped flag. */
588 partition_foreignize(p);
589 } else {
590 log_info("Can't fit partition %s of priority %" PRIi32 ", dropping.",
591 p->definition_path, p->priority);
592
593 p->dropped = true;
594 p->allocated_to_area = NULL;
595 }
596 }
597
598 static bool context_drop_or_foreignize_one_priority(Context *context) {
599 int32_t priority = 0;
600
601 LIST_FOREACH(partitions, p, context->partitions) {
602 if (p->dropped)
603 continue;
604
605 priority = MAX(priority, p->priority);
606 }
607
608 /* Refuse to drop partitions with 0 or negative priorities or partitions of priorities that have at
609 * least one existing priority */
610 if (priority <= 0)
611 return false;
612
613 LIST_FOREACH(partitions, p, context->partitions) {
614 if (p->priority < priority)
615 continue;
616
617 partition_drop_or_foreignize(p);
618
619 /* We ensure that all verity sibling partitions have the same priority, so it's safe
620 * to drop all siblings here as well. */
621
622 for (VerityMode mode = VERITY_OFF + 1; mode < _VERITY_MODE_MAX; mode++)
623 partition_drop_or_foreignize(p->siblings[mode]);
624 }
625
626 return true;
627 }
628
629 static uint64_t partition_min_size(const Context *context, const Partition *p) {
630 uint64_t sz;
631
632 assert(context);
633 assert(p);
634
635 /* Calculate the disk space we really need at minimum for this partition. If the partition already
636 * exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
637 * than 4K.
638 *
639 * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
640
641 if (PARTITION_IS_FOREIGN(p)) {
642 /* Don't allow changing size of partitions not managed by us */
643 assert(p->current_size != UINT64_MAX);
644 return p->current_size;
645 }
646
647 if (p->verity == VERITY_SIG)
648 return VERITY_SIG_SIZE;
649
650 sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
651
652 if (!PARTITION_EXISTS(p)) {
653 uint64_t d = 0;
654
655 if (p->encrypt != ENCRYPT_OFF)
656 d += round_up_size(LUKS2_METADATA_KEEP_FREE, context->grain_size);
657
658 if (p->copy_blocks_size != UINT64_MAX)
659 d += round_up_size(p->copy_blocks_size, context->grain_size);
660 else if (p->format || p->encrypt != ENCRYPT_OFF) {
661 uint64_t f;
662
663 /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */
664 f = p->format ? round_up_size(minimal_size_by_fs_name(p->format), context->grain_size) : UINT64_MAX;
665 d += f == UINT64_MAX ? context->grain_size : f;
666 }
667
668 if (d > sz)
669 sz = d;
670 }
671
672 return MAX(round_up_size(p->size_min != UINT64_MAX ? p->size_min : DEFAULT_MIN_SIZE, context->grain_size), sz);
673 }
674
675 static uint64_t partition_max_size(const Context *context, const Partition *p) {
676 uint64_t sm;
677
678 /* Calculate how large the partition may become at max. This is generally the configured maximum
679 * size, except when it already exists and is larger than that. In that case it's the existing size,
680 * since we never want to shrink partitions. */
681
682 assert(context);
683 assert(p);
684
685 if (PARTITION_IS_FOREIGN(p)) {
686 /* Don't allow changing size of partitions not managed by us */
687 assert(p->current_size != UINT64_MAX);
688 return p->current_size;
689 }
690
691 if (p->verity == VERITY_SIG)
692 return VERITY_SIG_SIZE;
693
694 if (p->size_max == UINT64_MAX)
695 return UINT64_MAX;
696
697 sm = round_down_size(p->size_max, context->grain_size);
698
699 if (p->current_size != UINT64_MAX)
700 sm = MAX(p->current_size, sm);
701
702 return MAX(partition_min_size(context, p), sm);
703 }
704
705 static uint64_t partition_min_padding(const Partition *p) {
706 assert(p);
707 return p->padding_min != UINT64_MAX ? p->padding_min : 0;
708 }
709
710 static uint64_t partition_max_padding(const Partition *p) {
711 assert(p);
712 return p->padding_max;
713 }
714
715 static uint64_t partition_min_size_with_padding(Context *context, const Partition *p) {
716 uint64_t sz;
717
718 /* Calculate the disk space we need for this partition plus any free space coming after it. This
719 * takes user configured padding into account as well as any additional whitespace needed to align
720 * the next partition to 4K again. */
721
722 assert(context);
723 assert(p);
724
725 sz = partition_min_size(context, p) + partition_min_padding(p);
726
727 if (PARTITION_EXISTS(p)) {
728 /* If the partition wasn't aligned, add extra space so that any we might add will be aligned */
729 assert(p->offset != UINT64_MAX);
730 return round_up_size(p->offset + sz, context->grain_size) - p->offset;
731 }
732
733 /* If this is a new partition we'll place it aligned, hence we just need to round up the required size here */
734 return round_up_size(sz, context->grain_size);
735 }
736
737 static uint64_t free_area_available(const FreeArea *a) {
738 assert(a);
739
740 /* Determines how much of this free area is not allocated yet */
741
742 assert(a->size >= a->allocated);
743 return a->size - a->allocated;
744 }
745
746 static uint64_t free_area_current_end(Context *context, const FreeArea *a) {
747 assert(context);
748 assert(a);
749
750 if (!a->after)
751 return free_area_available(a);
752
753 assert(a->after->offset != UINT64_MAX);
754 assert(a->after->current_size != UINT64_MAX);
755
756 /* Calculate where the free area ends, based on the offset of the partition preceding it. */
757 return round_up_size(a->after->offset + a->after->current_size, context->grain_size) + free_area_available(a);
758 }
759
760 static uint64_t free_area_min_end(Context *context, const FreeArea *a) {
761 assert(context);
762 assert(a);
763
764 if (!a->after)
765 return 0;
766
767 assert(a->after->offset != UINT64_MAX);
768 assert(a->after->current_size != UINT64_MAX);
769
770 /* Calculate where the partition would end when we give it as much as it needs. */
771 return round_up_size(a->after->offset + partition_min_size_with_padding(context, a->after), context->grain_size);
772 }
773
774 static uint64_t free_area_available_for_new_partitions(Context *context, const FreeArea *a) {
775 assert(context);
776 assert(a);
777
778 /* Similar to free_area_available(), but takes into account that the required size and padding of the
779 * preceding partition is honoured. */
780
781 return LESS_BY(free_area_current_end(context, a), free_area_min_end(context, a));
782 }
783
784 static int free_area_compare(FreeArea *const *a, FreeArea *const*b, Context *context) {
785 assert(context);
786
787 return CMP(free_area_available_for_new_partitions(context, *a),
788 free_area_available_for_new_partitions(context, *b));
789 }
790
791 static uint64_t charge_size(Context *context, uint64_t total, uint64_t amount) {
792 assert(context);
793 /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
794 assert(amount <= total);
795 return LESS_BY(total, round_up_size(amount, context->grain_size));
796 }
797
798 static uint64_t charge_weight(uint64_t total, uint64_t amount) {
799 assert(amount <= total);
800 return total - amount;
801 }
802
803 static bool context_allocate_partitions(Context *context, uint64_t *ret_largest_free_area) {
804 assert(context);
805
806 /* This may be called multiple times. Reset previous assignments. */
807 for (size_t i = 0; i < context->n_free_areas; i++)
808 context->free_areas[i]->allocated = 0;
809
810 /* Sort free areas by size, putting smallest first */
811 typesafe_qsort_r(context->free_areas, context->n_free_areas, free_area_compare, context);
812
813 /* In any case return size of the largest free area (i.e. not the size of all free areas
814 * combined!) */
815 if (ret_largest_free_area)
816 *ret_largest_free_area =
817 context->n_free_areas == 0 ? 0 :
818 free_area_available_for_new_partitions(context, context->free_areas[context->n_free_areas-1]);
819
820 /* Check that each existing partition can fit its area. */
821 for (size_t i = 0; i < context->n_free_areas; i++)
822 if (free_area_current_end(context, context->free_areas[i]) <
823 free_area_min_end(context, context->free_areas[i]))
824 return false;
825
826 /* A simple first-fit algorithm. We return true if we can fit the partitions in, otherwise false. */
827 LIST_FOREACH(partitions, p, context->partitions) {
828 bool fits = false;
829 uint64_t required;
830 FreeArea *a = NULL;
831
832 /* Skip partitions we already dropped or that already exist */
833 if (p->dropped || PARTITION_EXISTS(p))
834 continue;
835
836 /* How much do we need to fit? */
837 required = partition_min_size_with_padding(context, p);
838 assert(required % context->grain_size == 0);
839
840 for (size_t i = 0; i < context->n_free_areas; i++) {
841 a = context->free_areas[i];
842
843 if (free_area_available_for_new_partitions(context, a) >= required) {
844 fits = true;
845 break;
846 }
847 }
848
849 if (!fits)
850 return false; /* 😢 Oh no! We can't fit this partition into any free area! */
851
852 /* Assign the partition to this free area */
853 p->allocated_to_area = a;
854
855 /* Budget the minimal partition size */
856 a->allocated += required;
857 }
858
859 return true;
860 }
861
862 static int context_sum_weights(Context *context, FreeArea *a, uint64_t *ret) {
863 uint64_t weight_sum = 0;
864
865 assert(context);
866 assert(a);
867 assert(ret);
868
869 /* Determine the sum of the weights of all partitions placed in or before the specified free area */
870
871 LIST_FOREACH(partitions, p, context->partitions) {
872 if (p->padding_area != a && p->allocated_to_area != a)
873 continue;
874
875 if (p->weight > UINT64_MAX - weight_sum)
876 goto overflow_sum;
877 weight_sum += p->weight;
878
879 if (p->padding_weight > UINT64_MAX - weight_sum)
880 goto overflow_sum;
881 weight_sum += p->padding_weight;
882 }
883
884 *ret = weight_sum;
885 return 0;
886
887 overflow_sum:
888 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Combined weight of partition exceeds unsigned 64-bit range, refusing.");
889 }
890
891 static uint64_t scale_by_weight(uint64_t value, uint64_t weight, uint64_t weight_sum) {
892 assert(weight_sum >= weight);
893
894 for (;;) {
895 if (weight == 0)
896 return 0;
897 if (weight == weight_sum)
898 return value;
899 if (value <= UINT64_MAX / weight)
900 return value * weight / weight_sum;
901
902 /* Rescale weight and weight_sum to make not the calculation overflow. To satisfy the
903 * following conditions, 'weight_sum' is rounded up but 'weight' is rounded down:
904 * - the sum of scale_by_weight() for all weights must not be larger than the input value,
905 * - scale_by_weight() must not be larger than the ideal value (i.e. calculated with uint128_t). */
906 weight_sum = DIV_ROUND_UP(weight_sum, 2);
907 weight /= 2;
908 }
909 }
910
911 typedef enum GrowPartitionPhase {
912 /* The zeroth phase: do not touch foreign partitions (i.e. those we don't manage). */
913 PHASE_FOREIGN,
914
915 /* The first phase: we charge partitions which need more (according to constraints) than their weight-based share. */
916 PHASE_OVERCHARGE,
917
918 /* The second phase: we charge partitions which need less (according to constraints) than their weight-based share. */
919 PHASE_UNDERCHARGE,
920
921 /* The third phase: we distribute what remains among the remaining partitions, according to the weights */
922 PHASE_DISTRIBUTE,
923
924 _GROW_PARTITION_PHASE_MAX,
925 } GrowPartitionPhase;
926
927 static bool context_grow_partitions_phase(
928 Context *context,
929 FreeArea *a,
930 GrowPartitionPhase phase,
931 uint64_t *span,
932 uint64_t *weight_sum) {
933
934 bool try_again = false;
935
936 assert(context);
937 assert(a);
938 assert(span);
939 assert(weight_sum);
940
941 /* Now let's look at the intended weights and adjust them taking the minimum space assignments into
942 * account. i.e. if a partition has a small weight but a high minimum space value set it should not
943 * get any additional room from the left-overs. Similar, if two partitions have the same weight they
944 * should get the same space if possible, even if one has a smaller minimum size than the other. */
945 LIST_FOREACH(partitions, p, context->partitions) {
946
947 /* Look only at partitions associated with this free area, i.e. immediately
948 * preceding it, or allocated into it */
949 if (p->allocated_to_area != a && p->padding_area != a)
950 continue;
951
952 if (p->new_size == UINT64_MAX) {
953 uint64_t share, rsz, xsz;
954 bool charge = false;
955
956 /* Calculate how much this space this partition needs if everyone would get
957 * the weight based share */
958 share = scale_by_weight(*span, p->weight, *weight_sum);
959
960 rsz = partition_min_size(context, p);
961 xsz = partition_max_size(context, p);
962
963 if (phase == PHASE_FOREIGN && PARTITION_IS_FOREIGN(p)) {
964 /* Never change of foreign partitions (i.e. those we don't manage) */
965
966 p->new_size = p->current_size;
967 charge = true;
968
969 } else if (phase == PHASE_OVERCHARGE && rsz > share) {
970 /* This partition needs more than its calculated share. Let's assign
971 * it that, and take this partition out of all calculations and start
972 * again. */
973
974 p->new_size = rsz;
975 charge = try_again = true;
976
977 } else if (phase == PHASE_UNDERCHARGE && xsz < share) {
978 /* This partition accepts less than its calculated
979 * share. Let's assign it that, and take this partition out
980 * of all calculations and start again. */
981
982 p->new_size = xsz;
983 charge = try_again = true;
984
985 } else if (phase == PHASE_DISTRIBUTE) {
986 /* This partition can accept its calculated share. Let's
987 * assign it. There's no need to restart things here since
988 * assigning this shouldn't impact the shares of the other
989 * partitions. */
990
991 assert(share >= rsz);
992 p->new_size = CLAMP(round_down_size(share, context->grain_size), rsz, xsz);
993 charge = true;
994 }
995
996 if (charge) {
997 *span = charge_size(context, *span, p->new_size);
998 *weight_sum = charge_weight(*weight_sum, p->weight);
999 }
1000 }
1001
1002 if (p->new_padding == UINT64_MAX) {
1003 uint64_t share, rsz, xsz;
1004 bool charge = false;
1005
1006 share = scale_by_weight(*span, p->padding_weight, *weight_sum);
1007
1008 rsz = partition_min_padding(p);
1009 xsz = partition_max_padding(p);
1010
1011 if (phase == PHASE_OVERCHARGE && rsz > share) {
1012 p->new_padding = rsz;
1013 charge = try_again = true;
1014 } else if (phase == PHASE_UNDERCHARGE && xsz < share) {
1015 p->new_padding = xsz;
1016 charge = try_again = true;
1017 } else if (phase == PHASE_DISTRIBUTE) {
1018 assert(share >= rsz);
1019 p->new_padding = CLAMP(round_down_size(share, context->grain_size), rsz, xsz);
1020 charge = true;
1021 }
1022
1023 if (charge) {
1024 *span = charge_size(context, *span, p->new_padding);
1025 *weight_sum = charge_weight(*weight_sum, p->padding_weight);
1026 }
1027 }
1028 }
1029
1030 return !try_again;
1031 }
1032
1033 static void context_grow_partition_one(Context *context, FreeArea *a, Partition *p, uint64_t *span) {
1034 uint64_t m;
1035
1036 assert(context);
1037 assert(a);
1038 assert(p);
1039 assert(span);
1040
1041 if (*span == 0)
1042 return;
1043
1044 if (p->allocated_to_area != a)
1045 return;
1046
1047 if (PARTITION_IS_FOREIGN(p))
1048 return;
1049
1050 assert(p->new_size != UINT64_MAX);
1051
1052 /* Calculate new size and align. */
1053 m = round_down_size(p->new_size + *span, context->grain_size);
1054 /* But ensure this doesn't shrink the size. */
1055 m = MAX(m, p->new_size);
1056 /* And ensure this doesn't exceed the maximum size. */
1057 m = MIN(m, partition_max_size(context, p));
1058
1059 assert(m >= p->new_size);
1060
1061 *span = charge_size(context, *span, m - p->new_size);
1062 p->new_size = m;
1063 }
1064
1065 static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
1066 uint64_t weight_sum = 0, span;
1067 int r;
1068
1069 assert(context);
1070 assert(a);
1071
1072 r = context_sum_weights(context, a, &weight_sum);
1073 if (r < 0)
1074 return r;
1075
1076 /* Let's calculate the total area covered by this free area and the partition before it */
1077 span = a->size;
1078 if (a->after) {
1079 assert(a->after->offset != UINT64_MAX);
1080 assert(a->after->current_size != UINT64_MAX);
1081
1082 span += round_up_size(a->after->offset + a->after->current_size, context->grain_size) - a->after->offset;
1083 }
1084
1085 for (GrowPartitionPhase phase = 0; phase < _GROW_PARTITION_PHASE_MAX;)
1086 if (context_grow_partitions_phase(context, a, phase, &span, &weight_sum))
1087 phase++; /* go to the next phase */
1088
1089 /* We still have space left over? Donate to preceding partition if we have one */
1090 if (span > 0 && a->after)
1091 context_grow_partition_one(context, a, a->after, &span);
1092
1093 /* What? Even still some space left (maybe because there was no preceding partition, or it had a
1094 * size limit), then let's donate it to whoever wants it. */
1095 if (span > 0)
1096 LIST_FOREACH(partitions, p, context->partitions) {
1097 context_grow_partition_one(context, a, p, &span);
1098 if (span == 0)
1099 break;
1100 }
1101
1102 /* Yuck, still no one? Then make it padding */
1103 if (span > 0 && a->after) {
1104 assert(a->after->new_padding != UINT64_MAX);
1105 a->after->new_padding += span;
1106 }
1107
1108 return 0;
1109 }
1110
1111 static int context_grow_partitions(Context *context) {
1112 int r;
1113
1114 assert(context);
1115
1116 for (size_t i = 0; i < context->n_free_areas; i++) {
1117 r = context_grow_partitions_on_free_area(context, context->free_areas[i]);
1118 if (r < 0)
1119 return r;
1120 }
1121
1122 /* All existing partitions that have no free space after them can't change size */
1123 LIST_FOREACH(partitions, p, context->partitions) {
1124 if (p->dropped)
1125 continue;
1126
1127 if (!PARTITION_EXISTS(p) || p->padding_area) {
1128 /* The algorithm above must have initialized this already */
1129 assert(p->new_size != UINT64_MAX);
1130 continue;
1131 }
1132
1133 assert(p->new_size == UINT64_MAX);
1134 p->new_size = p->current_size;
1135
1136 assert(p->new_padding == UINT64_MAX);
1137 p->new_padding = p->current_padding;
1138 }
1139
1140 return 0;
1141 }
1142
1143 static uint64_t find_first_unused_partno(Context *context) {
1144 uint64_t partno = 0;
1145
1146 assert(context);
1147
1148 for (partno = 0;; partno++) {
1149 bool found = false;
1150 LIST_FOREACH(partitions, p, context->partitions)
1151 if (p->partno != UINT64_MAX && p->partno == partno)
1152 found = true;
1153 if (!found)
1154 break;
1155 }
1156
1157 return partno;
1158 }
1159
1160 static void context_place_partitions(Context *context) {
1161
1162 assert(context);
1163
1164 for (size_t i = 0; i < context->n_free_areas; i++) {
1165 FreeArea *a = context->free_areas[i];
1166 _unused_ uint64_t left;
1167 uint64_t start;
1168
1169 if (a->after) {
1170 assert(a->after->offset != UINT64_MAX);
1171 assert(a->after->new_size != UINT64_MAX);
1172 assert(a->after->new_padding != UINT64_MAX);
1173
1174 start = a->after->offset + a->after->new_size + a->after->new_padding;
1175 } else
1176 start = context->start;
1177
1178 start = round_up_size(start, context->grain_size);
1179 left = a->size;
1180
1181 LIST_FOREACH(partitions, p, context->partitions) {
1182 if (p->allocated_to_area != a)
1183 continue;
1184
1185 p->offset = start;
1186 p->partno = find_first_unused_partno(context);
1187
1188 assert(left >= p->new_size);
1189 start += p->new_size;
1190 left -= p->new_size;
1191
1192 assert(left >= p->new_padding);
1193 start += p->new_padding;
1194 left -= p->new_padding;
1195 }
1196 }
1197 }
1198
1199 static int config_parse_type(
1200 const char *unit,
1201 const char *filename,
1202 unsigned line,
1203 const char *section,
1204 unsigned section_line,
1205 const char *lvalue,
1206 int ltype,
1207 const char *rvalue,
1208 void *data,
1209 void *userdata) {
1210
1211 GptPartitionType *type = ASSERT_PTR(data);
1212 int r;
1213
1214 assert(rvalue);
1215
1216 r = gpt_partition_type_from_string(rvalue, type);
1217 if (r < 0)
1218 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue);
1219
1220 if (arg_architecture >= 0)
1221 *type = gpt_partition_type_override_architecture(*type, arg_architecture);
1222
1223 return 0;
1224 }
1225
1226 static int config_parse_label(
1227 const char *unit,
1228 const char *filename,
1229 unsigned line,
1230 const char *section,
1231 unsigned section_line,
1232 const char *lvalue,
1233 int ltype,
1234 const char *rvalue,
1235 void *data,
1236 void *userdata) {
1237
1238 _cleanup_free_ char *resolved = NULL;
1239 char **label = ASSERT_PTR(data);
1240 int r;
1241
1242 assert(rvalue);
1243
1244 /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
1245 * assigning the empty string to reset to default here, but really accept it as label to set. */
1246
1247 r = specifier_printf(rvalue, GPT_LABEL_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
1248 if (r < 0) {
1249 log_syntax(unit, LOG_WARNING, filename, line, r,
1250 "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
1251 return 0;
1252 }
1253
1254 if (!utf8_is_valid(resolved)) {
1255 log_syntax(unit, LOG_WARNING, filename, line, 0,
1256 "Partition label not valid UTF-8, ignoring: %s", rvalue);
1257 return 0;
1258 }
1259
1260 r = gpt_partition_label_valid(resolved);
1261 if (r < 0) {
1262 log_syntax(unit, LOG_WARNING, filename, line, r,
1263 "Failed to check if string is valid as GPT partition label, ignoring: \"%s\" (from \"%s\")",
1264 resolved, rvalue);
1265 return 0;
1266 }
1267 if (!r) {
1268 log_syntax(unit, LOG_WARNING, filename, line, 0,
1269 "Partition label too long for GPT table, ignoring: \"%s\" (from \"%s\")",
1270 resolved, rvalue);
1271 return 0;
1272 }
1273
1274 free_and_replace(*label, resolved);
1275 return 0;
1276 }
1277
1278 static int config_parse_weight(
1279 const char *unit,
1280 const char *filename,
1281 unsigned line,
1282 const char *section,
1283 unsigned section_line,
1284 const char *lvalue,
1285 int ltype,
1286 const char *rvalue,
1287 void *data,
1288 void *userdata) {
1289
1290 uint32_t *w = ASSERT_PTR(data), v;
1291 int r;
1292
1293 assert(rvalue);
1294
1295 r = safe_atou32(rvalue, &v);
1296 if (r < 0) {
1297 log_syntax(unit, LOG_WARNING, filename, line, r,
1298 "Failed to parse weight value, ignoring: %s", rvalue);
1299 return 0;
1300 }
1301
1302 if (v > 1000U*1000U) {
1303 log_syntax(unit, LOG_WARNING, filename, line, 0,
1304 "Weight needs to be in range 0…10000000, ignoring: %" PRIu32, v);
1305 return 0;
1306 }
1307
1308 *w = v;
1309 return 0;
1310 }
1311
1312 static int config_parse_size4096(
1313 const char *unit,
1314 const char *filename,
1315 unsigned line,
1316 const char *section,
1317 unsigned section_line,
1318 const char *lvalue,
1319 int ltype,
1320 const char *rvalue,
1321 void *data,
1322 void *userdata) {
1323
1324 uint64_t *sz = data, parsed;
1325 int r;
1326
1327 assert(rvalue);
1328 assert(data);
1329
1330 r = parse_size(rvalue, 1024, &parsed);
1331 if (r < 0)
1332 return log_syntax(unit, LOG_ERR, filename, line, r,
1333 "Failed to parse size value: %s", rvalue);
1334
1335 if (ltype > 0)
1336 *sz = round_up_size(parsed, 4096);
1337 else if (ltype < 0)
1338 *sz = round_down_size(parsed, 4096);
1339 else
1340 *sz = parsed;
1341
1342 if (*sz != parsed)
1343 log_syntax(unit, LOG_NOTICE, filename, line, r, "Rounded %s= size %" PRIu64 " %s %" PRIu64 ", a multiple of 4096.",
1344 lvalue, parsed, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), *sz);
1345
1346 return 0;
1347 }
1348
1349 static int config_parse_block_size(
1350 const char *unit,
1351 const char *filename,
1352 unsigned line,
1353 const char *section,
1354 unsigned section_line,
1355 const char *lvalue,
1356 int ltype,
1357 const char *rvalue,
1358 void *data,
1359 void *userdata) {
1360
1361 uint64_t *blksz = ASSERT_PTR(data), parsed;
1362 int r;
1363
1364 assert(rvalue);
1365
1366 r = parse_size(rvalue, 1024, &parsed);
1367 if (r < 0)
1368 return log_syntax(unit, LOG_ERR, filename, line, r,
1369 "Failed to parse size value: %s", rvalue);
1370
1371 if (parsed < 512 || parsed > 4096)
1372 return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
1373 "Value not between 512 and 4096: %s", rvalue);
1374
1375 if (!ISPOWEROF2(parsed))
1376 return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
1377 "Value not a power of 2: %s", rvalue);
1378
1379 *blksz = parsed;
1380 return 0;
1381 }
1382
1383 static int config_parse_fstype(
1384 const char *unit,
1385 const char *filename,
1386 unsigned line,
1387 const char *section,
1388 unsigned section_line,
1389 const char *lvalue,
1390 int ltype,
1391 const char *rvalue,
1392 void *data,
1393 void *userdata) {
1394
1395 char **fstype = ASSERT_PTR(data);
1396 const char *e;
1397
1398 assert(rvalue);
1399
1400 /* Let's provide an easy way to override the chosen fstype for file system partitions */
1401 e = secure_getenv("SYSTEMD_REPART_OVERRIDE_FSTYPE");
1402 if (e && !streq(rvalue, e)) {
1403 log_syntax(unit, LOG_NOTICE, filename, line, 0,
1404 "Overriding defined file system type '%s' with '%s'.", rvalue, e);
1405 rvalue = e;
1406 }
1407
1408 if (!filename_is_valid(rvalue))
1409 return log_syntax(unit, LOG_ERR, filename, line, 0,
1410 "File system type is not valid, refusing: %s", rvalue);
1411
1412 return free_and_strdup_warn(fstype, rvalue);
1413 }
1414
1415 static int config_parse_copy_files(
1416 const char *unit,
1417 const char *filename,
1418 unsigned line,
1419 const char *section,
1420 unsigned section_line,
1421 const char *lvalue,
1422 int ltype,
1423 const char *rvalue,
1424 void *data,
1425 void *userdata) {
1426
1427 _cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL;
1428 const char *p = rvalue, *target;
1429 char ***copy_files = ASSERT_PTR(data);
1430 int r;
1431
1432 assert(rvalue);
1433
1434 r = extract_first_word(&p, &source, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1435 if (r < 0)
1436 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract source path: %s", rvalue);
1437 if (r == 0) {
1438 log_syntax(unit, LOG_WARNING, filename, line, 0, "No argument specified: %s", rvalue);
1439 return 0;
1440 }
1441
1442 r = extract_first_word(&p, &buffer, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1443 if (r < 0)
1444 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract target path: %s", rvalue);
1445 if (r == 0)
1446 target = source; /* No target, then it's the same as the source */
1447 else
1448 target = buffer;
1449
1450 if (!isempty(p))
1451 return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
1452
1453 r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_source);
1454 if (r < 0) {
1455 log_syntax(unit, LOG_WARNING, filename, line, r,
1456 "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue);
1457 return 0;
1458 }
1459
1460 r = path_simplify_and_warn(resolved_source, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1461 if (r < 0)
1462 return 0;
1463
1464 r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_target);
1465 if (r < 0) {
1466 log_syntax(unit, LOG_WARNING, filename, line, r,
1467 "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target);
1468 return 0;
1469 }
1470
1471 r = path_simplify_and_warn(resolved_target, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1472 if (r < 0)
1473 return 0;
1474
1475 r = strv_consume_pair(copy_files, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target));
1476 if (r < 0)
1477 return log_oom();
1478
1479 return 0;
1480 }
1481
1482 static int config_parse_exclude_files(
1483 const char *unit,
1484 const char *filename,
1485 unsigned line,
1486 const char *section,
1487 unsigned section_line,
1488 const char *lvalue,
1489 int ltype,
1490 const char *rvalue,
1491 void *data,
1492 void *userdata) {
1493 _cleanup_free_ char *resolved = NULL;
1494 char ***exclude_files = ASSERT_PTR(data);
1495 int r;
1496
1497 if (isempty(rvalue)) {
1498 *exclude_files = strv_free(*exclude_files);
1499 return 0;
1500 }
1501
1502 r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
1503 if (r < 0) {
1504 log_syntax(unit, LOG_WARNING, filename, line, r,
1505 "Failed to expand specifiers in ExcludeFiles= path, ignoring: %s", rvalue);
1506 return 0;
1507 }
1508
1509 r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE|PATH_KEEP_TRAILING_SLASH, unit, filename, line, lvalue);
1510 if (r < 0)
1511 return 0;
1512
1513 if (strv_consume(exclude_files, TAKE_PTR(resolved)) < 0)
1514 return log_oom();
1515
1516 return 0;
1517 }
1518
1519 static int config_parse_copy_blocks(
1520 const char *unit,
1521 const char *filename,
1522 unsigned line,
1523 const char *section,
1524 unsigned section_line,
1525 const char *lvalue,
1526 int ltype,
1527 const char *rvalue,
1528 void *data,
1529 void *userdata) {
1530
1531 _cleanup_free_ char *d = NULL;
1532 Partition *partition = ASSERT_PTR(data);
1533 int r;
1534
1535 assert(rvalue);
1536
1537 if (isempty(rvalue)) {
1538 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1539 partition->copy_blocks_auto = false;
1540 return 0;
1541 }
1542
1543 if (streq(rvalue, "auto")) {
1544 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1545 partition->copy_blocks_auto = true;
1546 partition->copy_blocks_root = arg_root;
1547 return 0;
1548 }
1549
1550 r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
1551 if (r < 0) {
1552 log_syntax(unit, LOG_WARNING, filename, line, r,
1553 "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
1554 return 0;
1555 }
1556
1557 r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1558 if (r < 0)
1559 return 0;
1560
1561 free_and_replace(partition->copy_blocks_path, d);
1562 partition->copy_blocks_auto = false;
1563 partition->copy_blocks_root = arg_root;
1564 return 0;
1565 }
1566
1567 static int config_parse_make_dirs(
1568 const char *unit,
1569 const char *filename,
1570 unsigned line,
1571 const char *section,
1572 unsigned section_line,
1573 const char *lvalue,
1574 int ltype,
1575 const char *rvalue,
1576 void *data,
1577 void *userdata) {
1578
1579 char ***sv = ASSERT_PTR(data);
1580 const char *p = ASSERT_PTR(rvalue);
1581 int r;
1582
1583 for (;;) {
1584 _cleanup_free_ char *word = NULL, *d = NULL;
1585
1586 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1587 if (r == -ENOMEM)
1588 return log_oom();
1589 if (r < 0) {
1590 log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
1591 return 0;
1592 }
1593 if (r == 0)
1594 return 0;
1595
1596 r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
1597 if (r < 0) {
1598 log_syntax(unit, LOG_WARNING, filename, line, r,
1599 "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);
1600 continue;
1601 }
1602
1603 r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1604 if (r < 0)
1605 continue;
1606
1607 r = strv_consume(sv, TAKE_PTR(d));
1608 if (r < 0)
1609 return log_oom();
1610 }
1611 }
1612
1613 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt, encrypt_mode, EncryptMode, ENCRYPT_OFF, "Invalid encryption mode");
1614
1615 static int config_parse_gpt_flags(
1616 const char *unit,
1617 const char *filename,
1618 unsigned line,
1619 const char *section,
1620 unsigned section_line,
1621 const char *lvalue,
1622 int ltype,
1623 const char *rvalue,
1624 void *data,
1625 void *userdata) {
1626
1627 uint64_t *gpt_flags = ASSERT_PTR(data);
1628 int r;
1629
1630 assert(rvalue);
1631
1632 r = safe_atou64(rvalue, gpt_flags);
1633 if (r < 0) {
1634 log_syntax(unit, LOG_WARNING, filename, line, r,
1635 "Failed to parse Flags= value, ignoring: %s", rvalue);
1636 return 0;
1637 }
1638
1639 return 0;
1640 }
1641
1642 static int config_parse_uuid(
1643 const char *unit,
1644 const char *filename,
1645 unsigned line,
1646 const char *section,
1647 unsigned section_line,
1648 const char *lvalue,
1649 int ltype,
1650 const char *rvalue,
1651 void *data,
1652 void *userdata) {
1653
1654 Partition *partition = ASSERT_PTR(data);
1655 int r;
1656
1657 if (isempty(rvalue)) {
1658 partition->new_uuid = SD_ID128_NULL;
1659 partition->new_uuid_is_set = false;
1660 return 0;
1661 }
1662
1663 if (streq(rvalue, "null")) {
1664 partition->new_uuid = SD_ID128_NULL;
1665 partition->new_uuid_is_set = true;
1666 return 0;
1667 }
1668
1669 r = sd_id128_from_string(rvalue, &partition->new_uuid);
1670 if (r < 0) {
1671 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 128-bit ID/UUID, ignoring: %s", rvalue);
1672 return 0;
1673 }
1674
1675 partition->new_uuid_is_set = true;
1676
1677 return 0;
1678 }
1679
1680 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_verity, verity_mode, VerityMode, VERITY_OFF, "Invalid verity mode");
1681 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_minimize, minimize_mode, MinimizeMode, MINIMIZE_OFF, "Invalid minimize mode");
1682
1683 static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
1684
1685 ConfigTableItem table[] = {
1686 { "Partition", "Type", config_parse_type, 0, &p->type },
1687 { "Partition", "Label", config_parse_label, 0, &p->new_label },
1688 { "Partition", "UUID", config_parse_uuid, 0, p },
1689 { "Partition", "Priority", config_parse_int32, 0, &p->priority },
1690 { "Partition", "Weight", config_parse_weight, 0, &p->weight },
1691 { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight },
1692 { "Partition", "SizeMinBytes", config_parse_size4096, -1, &p->size_min },
1693 { "Partition", "SizeMaxBytes", config_parse_size4096, 1, &p->size_max },
1694 { "Partition", "PaddingMinBytes", config_parse_size4096, -1, &p->padding_min },
1695 { "Partition", "PaddingMaxBytes", config_parse_size4096, 1, &p->padding_max },
1696 { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset },
1697 { "Partition", "CopyBlocks", config_parse_copy_blocks, 0, p },
1698 { "Partition", "Format", config_parse_fstype, 0, &p->format },
1699 { "Partition", "CopyFiles", config_parse_copy_files, 0, &p->copy_files },
1700 { "Partition", "ExcludeFiles", config_parse_exclude_files, 0, &p->exclude_files_source },
1701 { "Partition", "ExcludeFilesTarget", config_parse_exclude_files, 0, &p->exclude_files_target },
1702 { "Partition", "MakeDirectories", config_parse_make_dirs, 0, &p->make_directories },
1703 { "Partition", "Encrypt", config_parse_encrypt, 0, &p->encrypt },
1704 { "Partition", "Verity", config_parse_verity, 0, &p->verity },
1705 { "Partition", "VerityMatchKey", config_parse_string, 0, &p->verity_match_key },
1706 { "Partition", "Flags", config_parse_gpt_flags, 0, &p->gpt_flags },
1707 { "Partition", "ReadOnly", config_parse_tristate, 0, &p->read_only },
1708 { "Partition", "NoAuto", config_parse_tristate, 0, &p->no_auto },
1709 { "Partition", "GrowFileSystem", config_parse_tristate, 0, &p->growfs },
1710 { "Partition", "SplitName", config_parse_string, 0, &p->split_name_format },
1711 { "Partition", "Minimize", config_parse_minimize, 0, &p->minimize },
1712 { "Partition", "Subvolumes", config_parse_make_dirs, 0, &p->subvolumes },
1713 { "Partition", "VerityDataBlockSizeBytes", config_parse_block_size, 0, &p->verity_data_block_size },
1714 { "Partition", "VerityHashBlockSizeBytes", config_parse_block_size, 0, &p->verity_hash_block_size },
1715 {}
1716 };
1717 int r;
1718 _cleanup_free_ char *filename = NULL;
1719 const char* dropin_dirname;
1720
1721 r = path_extract_filename(path, &filename);
1722 if (r < 0)
1723 return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
1724
1725 dropin_dirname = strjoina(filename, ".d");
1726
1727 r = config_parse_many(
1728 STRV_MAKE_CONST(path),
1729 conf_file_dirs,
1730 dropin_dirname,
1731 arg_definitions ? NULL : arg_root,
1732 "Partition\0",
1733 config_item_table_lookup, table,
1734 CONFIG_PARSE_WARN,
1735 p,
1736 NULL,
1737 &p->drop_in_files);
1738 if (r < 0)
1739 return r;
1740
1741 if (partition_type_exclude(&p->type))
1742 return 0;
1743
1744 if (p->size_min != UINT64_MAX && p->size_max != UINT64_MAX && p->size_min > p->size_max)
1745 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1746 "SizeMinBytes= larger than SizeMaxBytes=, refusing.");
1747
1748 if (p->padding_min != UINT64_MAX && p->padding_max != UINT64_MAX && p->padding_min > p->padding_max)
1749 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1750 "PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
1751
1752 if (sd_id128_is_null(p->type.uuid))
1753 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1754 "Type= not defined, refusing.");
1755
1756 if ((p->copy_blocks_path || p->copy_blocks_auto) &&
1757 (p->format || !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)))
1758 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1759 "Format=/CopyFiles=/MakeDirectories= and CopyBlocks= cannot be combined, refusing.");
1760
1761 if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && streq_ptr(p->format, "swap"))
1762 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1763 "Format=swap and CopyFiles= cannot be combined, refusing.");
1764
1765 if (!p->format) {
1766 const char *format = NULL;
1767
1768 if (!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories) || (p->encrypt != ENCRYPT_OFF && !(p->copy_blocks_path || p->copy_blocks_auto)))
1769 /* Pick "vfat" as file system for esp and xbootldr partitions, otherwise default to "ext4". */
1770 format = IN_SET(p->type.designator, PARTITION_ESP, PARTITION_XBOOTLDR) ? "vfat" : "ext4";
1771 else if (p->type.designator == PARTITION_SWAP)
1772 format = "swap";
1773
1774 if (format) {
1775 p->format = strdup(format);
1776 if (!p->format)
1777 return log_oom();
1778 }
1779 }
1780
1781 if (p->minimize != MINIMIZE_OFF && !p->format && p->verity != VERITY_HASH)
1782 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1783 "Minimize= can only be enabled if Format= or Verity=hash are set");
1784
1785 if (p->minimize == MINIMIZE_BEST && (p->format && !fstype_is_ro(p->format)) && p->verity != VERITY_HASH)
1786 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1787 "Minimize=best can only be used with read-only filesystems or Verity=hash");
1788
1789 if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && !mkfs_supports_root_option(p->format) && geteuid() != 0)
1790 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EPERM),
1791 "Need to be root to populate %s filesystems with CopyFiles=/MakeDirectories=",
1792 p->format);
1793
1794 if (p->format && fstype_is_ro(p->format) && strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
1795 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1796 "Cannot format %s filesystem without source files, refusing", p->format);
1797
1798 if (p->verity != VERITY_OFF || p->encrypt != ENCRYPT_OFF) {
1799 r = dlopen_cryptsetup();
1800 if (r < 0)
1801 return log_syntax(NULL, LOG_ERR, path, 1, r,
1802 "libcryptsetup not found, Verity=/Encrypt= are not supported: %m");
1803 }
1804
1805 if (p->verity != VERITY_OFF && !p->verity_match_key)
1806 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1807 "VerityMatchKey= must be set if Verity=%s", verity_mode_to_string(p->verity));
1808
1809 if (p->verity == VERITY_OFF && p->verity_match_key)
1810 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1811 "VerityMatchKey= can only be set if Verity= is not \"%s\"",
1812 verity_mode_to_string(p->verity));
1813
1814 if (IN_SET(p->verity, VERITY_HASH, VERITY_SIG) &&
1815 (p->copy_files || p->copy_blocks_path || p->copy_blocks_auto || p->format || p->make_directories))
1816 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1817 "CopyBlocks=/CopyFiles=/Format=/MakeDirectories= cannot be used with Verity=%s",
1818 verity_mode_to_string(p->verity));
1819
1820 if (p->verity != VERITY_OFF && p->encrypt != ENCRYPT_OFF)
1821 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1822 "Encrypting verity hash/data partitions is not supported");
1823
1824 if (p->verity == VERITY_SIG && !arg_private_key)
1825 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1826 "Verity signature partition requested but no private key provided (--private-key=)");
1827
1828 if (p->verity == VERITY_SIG && !arg_certificate)
1829 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1830 "Verity signature partition requested but no PEM certificate provided (--certificate=)");
1831
1832 if (p->verity == VERITY_SIG && (p->size_min != UINT64_MAX || p->size_max != UINT64_MAX))
1833 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1834 "SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s",
1835 verity_mode_to_string(p->verity));
1836
1837 if (!strv_isempty(p->subvolumes) && arg_offline > 0)
1838 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
1839 "Subvolumes= cannot be used with --offline=yes");
1840
1841 /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
1842 if ((IN_SET(p->type.designator,
1843 PARTITION_ROOT_VERITY,
1844 PARTITION_USR_VERITY) || p->verity == VERITY_DATA) && p->read_only < 0)
1845 p->read_only = true;
1846
1847 /* Default to "growfs" on, unless read-only */
1848 if (gpt_partition_type_knows_growfs(p->type) &&
1849 p->read_only <= 0)
1850 p->growfs = true;
1851
1852 if (!p->split_name_format) {
1853 char *s = strdup("%t");
1854 if (!s)
1855 return log_oom();
1856
1857 p->split_name_format = s;
1858 } else if (streq(p->split_name_format, "-"))
1859 p->split_name_format = mfree(p->split_name_format);
1860
1861 return 1;
1862 }
1863
1864 static int find_verity_sibling(Context *context, Partition *p, VerityMode mode, Partition **ret) {
1865 Partition *s = NULL;
1866
1867 assert(p);
1868 assert(p->verity != VERITY_OFF);
1869 assert(p->verity_match_key);
1870 assert(mode != VERITY_OFF);
1871 assert(p->verity != mode);
1872 assert(ret);
1873
1874 /* Try to find the matching sibling partition of the given type for a verity partition. For a data
1875 * partition, this is the corresponding hash partition with the same verity name (and vice versa for
1876 * the hash partition). */
1877
1878 LIST_FOREACH(partitions, q, context->partitions) {
1879 if (p == q)
1880 continue;
1881
1882 if (q->verity != mode)
1883 continue;
1884
1885 assert(q->verity_match_key);
1886
1887 if (!streq(p->verity_match_key, q->verity_match_key))
1888 continue;
1889
1890 if (s)
1891 return -ENOTUNIQ;
1892
1893 s = q;
1894 }
1895
1896 if (!s)
1897 return -ENXIO;
1898
1899 *ret = s;
1900
1901 return 0;
1902 }
1903
1904 static int context_open_and_lock_backing_fd(const char *node, int operation, int *backing_fd) {
1905 _cleanup_close_ int fd = -EBADF;
1906
1907 assert(node);
1908 assert(backing_fd);
1909
1910 if (*backing_fd >= 0)
1911 return 0;
1912
1913 fd = open(node, O_RDONLY|O_CLOEXEC);
1914 if (fd < 0)
1915 return log_error_errno(errno, "Failed to open device '%s': %m", node);
1916
1917 /* Tell udev not to interfere while we are processing the device */
1918 if (flock(fd, operation) < 0)
1919 return log_error_errno(errno, "Failed to lock device '%s': %m", node);
1920
1921 log_debug("Device %s opened and locked.", node);
1922 *backing_fd = TAKE_FD(fd);
1923 return 1;
1924 }
1925
1926 static int determine_current_padding(
1927 struct fdisk_context *c,
1928 struct fdisk_table *t,
1929 struct fdisk_partition *p,
1930 uint64_t secsz,
1931 uint64_t grainsz,
1932 uint64_t *ret) {
1933
1934 size_t n_partitions;
1935 uint64_t offset, next = UINT64_MAX;
1936
1937 assert(c);
1938 assert(t);
1939 assert(p);
1940 assert(ret);
1941
1942 if (!fdisk_partition_has_end(p))
1943 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition has no end!");
1944
1945 offset = fdisk_partition_get_end(p);
1946 assert(offset < UINT64_MAX);
1947 offset++; /* The end is one sector before the next partition or padding. */
1948 assert(offset < UINT64_MAX / secsz);
1949 offset *= secsz;
1950
1951 n_partitions = fdisk_table_get_nents(t);
1952 for (size_t i = 0; i < n_partitions; i++) {
1953 struct fdisk_partition *q;
1954 uint64_t start;
1955
1956 q = fdisk_table_get_partition(t, i);
1957 if (!q)
1958 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1959
1960 if (fdisk_partition_is_used(q) <= 0)
1961 continue;
1962
1963 if (!fdisk_partition_has_start(q))
1964 continue;
1965
1966 start = fdisk_partition_get_start(q);
1967 assert(start < UINT64_MAX / secsz);
1968 start *= secsz;
1969
1970 if (start >= offset && (next == UINT64_MAX || next > start))
1971 next = start;
1972 }
1973
1974 if (next == UINT64_MAX) {
1975 /* No later partition? In that case check the end of the usable area */
1976 next = fdisk_get_last_lba(c);
1977 assert(next < UINT64_MAX);
1978 next++; /* The last LBA is one sector before the end */
1979
1980 assert(next < UINT64_MAX / secsz);
1981 next *= secsz;
1982
1983 if (offset > next)
1984 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
1985 }
1986
1987 assert(next >= offset);
1988 offset = round_up_size(offset, grainsz);
1989 next = round_down_size(next, grainsz);
1990
1991 *ret = LESS_BY(next, offset); /* Saturated subtraction, rounding might have fucked things up */
1992 return 0;
1993 }
1994
1995 static int context_copy_from_one(Context *context, const char *src) {
1996 _cleanup_close_ int fd = -EBADF;
1997 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
1998 _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
1999 Partition *last = NULL;
2000 unsigned long secsz, grainsz;
2001 size_t n_partitions;
2002 int r;
2003
2004 assert(src);
2005
2006 r = context_open_and_lock_backing_fd(src, LOCK_SH, &fd);
2007 if (r < 0)
2008 return r;
2009
2010 r = fd_verify_regular(fd);
2011 if (r < 0)
2012 return log_error_errno(r, "%s is not a file: %m", src);
2013
2014 r = fdisk_new_context_at(fd, /* path = */ NULL, /* read_only = */ true, /* sector_size = */ UINT32_MAX, &c);
2015 if (r < 0)
2016 return log_error_errno(r, "Failed to create fdisk context: %m");
2017
2018 secsz = fdisk_get_sector_size(c);
2019 grainsz = fdisk_get_grain_size(c);
2020
2021 /* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
2022 if (secsz < 512 || !ISPOWEROF2(secsz))
2023 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
2024
2025 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
2026 return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Cannot copy from disk %s with no GPT disk label.", src);
2027
2028 r = fdisk_get_partitions(c, &t);
2029 if (r < 0)
2030 return log_error_errno(r, "Failed to acquire partition table: %m");
2031
2032 n_partitions = fdisk_table_get_nents(t);
2033 for (size_t i = 0; i < n_partitions; i++) {
2034 _cleanup_(partition_freep) Partition *np = NULL;
2035 _cleanup_free_ char *label_copy = NULL;
2036 struct fdisk_partition *p;
2037 const char *label;
2038 uint64_t sz, start, padding;
2039 sd_id128_t ptid, id;
2040 GptPartitionType type;
2041
2042 p = fdisk_table_get_partition(t, i);
2043 if (!p)
2044 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
2045
2046 if (fdisk_partition_is_used(p) <= 0)
2047 continue;
2048
2049 if (fdisk_partition_has_start(p) <= 0 ||
2050 fdisk_partition_has_size(p) <= 0 ||
2051 fdisk_partition_has_partno(p) <= 0)
2052 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
2053
2054 r = fdisk_partition_get_type_as_id128(p, &ptid);
2055 if (r < 0)
2056 return log_error_errno(r, "Failed to query partition type UUID: %m");
2057
2058 type = gpt_partition_type_from_uuid(ptid);
2059
2060 r = fdisk_partition_get_uuid_as_id128(p, &id);
2061 if (r < 0)
2062 return log_error_errno(r, "Failed to query partition UUID: %m");
2063
2064 label = fdisk_partition_get_name(p);
2065 if (!isempty(label)) {
2066 label_copy = strdup(label);
2067 if (!label_copy)
2068 return log_oom();
2069 }
2070
2071 sz = fdisk_partition_get_size(p);
2072 assert(sz <= UINT64_MAX/secsz);
2073 sz *= secsz;
2074
2075 start = fdisk_partition_get_start(p);
2076 assert(start <= UINT64_MAX/secsz);
2077 start *= secsz;
2078
2079 if (partition_type_exclude(&type))
2080 continue;
2081
2082 np = partition_new();
2083 if (!np)
2084 return log_oom();
2085
2086 np->type = type;
2087 np->new_uuid = id;
2088 np->new_uuid_is_set = true;
2089 np->size_min = np->size_max = sz;
2090 np->new_label = TAKE_PTR(label_copy);
2091
2092 np->definition_path = strdup(src);
2093 if (!np->definition_path)
2094 return log_oom();
2095
2096 r = determine_current_padding(c, t, p, secsz, grainsz, &padding);
2097 if (r < 0)
2098 return r;
2099
2100 np->padding_min = np->padding_max = padding;
2101
2102 np->copy_blocks_path = strdup(src);
2103 if (!np->copy_blocks_path)
2104 return log_oom();
2105
2106 np->copy_blocks_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2107 if (np->copy_blocks_fd < 0)
2108 return log_error_errno(r, "Failed to duplicate file descriptor of %s: %m", src);
2109
2110 np->copy_blocks_offset = start;
2111 np->copy_blocks_size = sz;
2112
2113 r = fdisk_partition_get_attrs_as_uint64(p, &np->gpt_flags);
2114 if (r < 0)
2115 return log_error_errno(r, "Failed to get partition flags: %m");
2116
2117 LIST_INSERT_AFTER(partitions, context->partitions, last, np);
2118 last = TAKE_PTR(np);
2119 context->n_partitions++;
2120 }
2121
2122 return 0;
2123 }
2124
2125 static int context_copy_from(Context *context) {
2126 int r;
2127
2128 assert(context);
2129
2130 STRV_FOREACH(src, arg_copy_from) {
2131 r = context_copy_from_one(context, *src);
2132 if (r < 0)
2133 return r;
2134 }
2135
2136 return 0;
2137 }
2138
2139 static int context_read_definitions(Context *context) {
2140 _cleanup_strv_free_ char **files = NULL;
2141 Partition *last = LIST_FIND_TAIL(partitions, context->partitions);
2142 const char *const *dirs;
2143 int r;
2144
2145 assert(context);
2146
2147 dirs = (const char* const*) (arg_definitions ?: CONF_PATHS_STRV("repart.d"));
2148
2149 r = conf_files_list_strv(&files, ".conf", arg_definitions ? NULL : arg_root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, dirs);
2150 if (r < 0)
2151 return log_error_errno(r, "Failed to enumerate *.conf files: %m");
2152
2153 STRV_FOREACH(f, files) {
2154 _cleanup_(partition_freep) Partition *p = NULL;
2155
2156 p = partition_new();
2157 if (!p)
2158 return log_oom();
2159
2160 p->definition_path = strdup(*f);
2161 if (!p->definition_path)
2162 return log_oom();
2163
2164 r = partition_read_definition(p, *f, dirs);
2165 if (r < 0)
2166 return r;
2167 if (r == 0)
2168 continue;
2169
2170 LIST_INSERT_AFTER(partitions, context->partitions, last, p);
2171 last = TAKE_PTR(p);
2172 context->n_partitions++;
2173 }
2174
2175 /* Check that each configured verity hash/data partition has a matching verity data/hash partition. */
2176
2177 LIST_FOREACH(partitions, p, context->partitions) {
2178 if (p->verity == VERITY_OFF)
2179 continue;
2180
2181 for (VerityMode mode = VERITY_OFF + 1; mode < _VERITY_MODE_MAX; mode++) {
2182 Partition *q = NULL;
2183
2184 if (p->verity == mode)
2185 continue;
2186
2187 if (p->siblings[mode])
2188 continue;
2189
2190 r = find_verity_sibling(context, p, mode, &q);
2191 if (r == -ENXIO) {
2192 if (mode != VERITY_SIG)
2193 return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
2194 "Missing verity %s partition for verity %s partition with VerityMatchKey=%s",
2195 verity_mode_to_string(mode), verity_mode_to_string(p->verity), p->verity_match_key);
2196 } else if (r == -ENOTUNIQ)
2197 return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
2198 "Multiple verity %s partitions found for verity %s partition with VerityMatchKey=%s",
2199 verity_mode_to_string(mode), verity_mode_to_string(p->verity), p->verity_match_key);
2200 else if (r < 0)
2201 return log_syntax(NULL, LOG_ERR, p->definition_path, 1, r,
2202 "Failed to find verity %s partition for verity %s partition with VerityMatchKey=%s",
2203 verity_mode_to_string(mode), verity_mode_to_string(p->verity), p->verity_match_key);
2204
2205 if (q) {
2206 if (q->priority != p->priority)
2207 return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
2208 "Priority mismatch (%i != %i) for verity sibling partitions with VerityMatchKey=%s",
2209 p->priority, q->priority, p->verity_match_key);
2210
2211 p->siblings[mode] = q;
2212 }
2213 }
2214 }
2215
2216 LIST_FOREACH(partitions, p, context->partitions) {
2217 Partition *dp;
2218
2219 if (p->verity != VERITY_HASH)
2220 continue;
2221
2222 if (p->minimize == MINIMIZE_OFF)
2223 continue;
2224
2225 assert_se(dp = p->siblings[VERITY_DATA]);
2226
2227 if (dp->minimize == MINIMIZE_OFF && !(dp->copy_blocks_path || dp->copy_blocks_auto))
2228 return log_syntax(NULL, LOG_ERR, p->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
2229 "Minimize= set for verity hash partition but data partition does "
2230 "not set CopyBlocks= or Minimize=");
2231
2232 }
2233
2234 return 0;
2235 }
2236
2237 static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *data) {
2238 _cleanup_free_ char *ids = NULL;
2239 int r;
2240
2241 if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
2242 return -EINVAL;
2243
2244 ids = new(char, SD_ID128_UUID_STRING_MAX);
2245 if (!ids)
2246 return -ENOMEM;
2247
2248 r = fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids));
2249 if (r < 0)
2250 return r;
2251
2252 TAKE_PTR(ids);
2253 return 0;
2254 }
2255
2256 static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id) {
2257 int r;
2258
2259 r = fdisk_set_ask(c, fdisk_ask_cb, &id);
2260 if (r < 0)
2261 return r;
2262
2263 r = fdisk_set_disklabel_id(c);
2264 if (r < 0)
2265 return r;
2266
2267 return fdisk_set_ask(c, NULL, NULL);
2268 }
2269
2270 static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) {
2271 union {
2272 uint8_t md[SHA256_DIGEST_SIZE];
2273 sd_id128_t id;
2274 } result;
2275
2276 assert(token);
2277 assert(ret);
2278
2279 /* Derive a new UUID from the specified UUID in a stable and reasonably safe way. Specifically, we
2280 * calculate the HMAC-SHA256 of the specified token string, keyed by the supplied base (typically the
2281 * machine ID). We use the machine ID as key (and not as cleartext!) of the HMAC operation since it's
2282 * the machine ID we don't want to leak. */
2283
2284 hmac_sha256(base.bytes, sizeof(base.bytes), token, strlen(token), result.md);
2285
2286 /* Take the first half, mark it as v4 UUID */
2287 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
2288 *ret = id128_make_v4_uuid(result.id);
2289 return 0;
2290 }
2291
2292 static void derive_salt(sd_id128_t base, const char *token, uint8_t ret[static SHA256_DIGEST_SIZE]) {
2293 assert(token);
2294
2295 hmac_sha256(base.bytes, sizeof(base.bytes), token, strlen(token), ret);
2296 }
2297
2298 static int context_load_partition_table(Context *context) {
2299 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
2300 _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
2301 uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors;
2302 _cleanup_free_ char *disk_uuid_string = NULL;
2303 bool from_scratch = false;
2304 sd_id128_t disk_uuid;
2305 size_t n_partitions;
2306 unsigned long secsz;
2307 uint64_t grainsz, fs_secsz = DEFAULT_FILESYSTEM_SECTOR_SIZE;
2308 int r;
2309
2310 assert(context);
2311 assert(!context->fdisk_context);
2312 assert(!context->free_areas);
2313 assert(context->start == UINT64_MAX);
2314 assert(context->end == UINT64_MAX);
2315 assert(context->total == UINT64_MAX);
2316
2317 c = fdisk_new_context();
2318 if (!c)
2319 return log_oom();
2320
2321 if (arg_sector_size > 0) {
2322 fs_secsz = arg_sector_size;
2323 r = fdisk_save_user_sector_size(c, /* phy= */ 0, arg_sector_size);
2324 } else {
2325 uint32_t ssz;
2326 struct stat st;
2327
2328 r = context_open_and_lock_backing_fd(context->node, arg_dry_run ? LOCK_SH : LOCK_EX,
2329 &context->backing_fd);
2330 if (r < 0)
2331 return r;
2332
2333 if (fstat(context->backing_fd, &st) < 0)
2334 return log_error_errno(errno, "Failed to stat %s: %m", context->node);
2335
2336 /* Auto-detect sector size if not specified. */
2337 r = probe_sector_size_prefer_ioctl(context->backing_fd, &ssz);
2338 if (r < 0)
2339 return log_error_errno(r, "Failed to probe sector size of '%s': %m", context->node);
2340
2341 /* If we found the sector size and we're operating on a block device, use it as the file
2342 * system sector size as well, as we know its the sector size of the actual block device and
2343 * not just the offset at which we found the GPT header. */
2344 if (r > 0 && S_ISBLK(st.st_mode))
2345 fs_secsz = ssz;
2346
2347 r = fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
2348 }
2349 if (r < 0)
2350 return log_error_errno(r, "Failed to set sector size: %m");
2351
2352 /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
2353 * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
2354 r = fdisk_assign_device(
2355 c,
2356 context->backing_fd >= 0 ? FORMAT_PROC_FD_PATH(context->backing_fd) : context->node,
2357 arg_dry_run);
2358 if (r == -EINVAL && arg_size_auto) {
2359 struct stat st;
2360
2361 /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept
2362 * it if automatic sizing is requested. */
2363
2364 if (context->backing_fd < 0)
2365 r = stat(context->node, &st);
2366 else
2367 r = fstat(context->backing_fd, &st);
2368 if (r < 0)
2369 return log_error_errno(errno, "Failed to stat block device '%s': %m", context->node);
2370
2371 if (S_ISREG(st.st_mode) && st.st_size == 0) {
2372 /* Use the fallback values if we have no better idea */
2373 context->sector_size = fdisk_get_sector_size(c);
2374 context->fs_sector_size = fs_secsz;
2375 context->grain_size = 4096;
2376 return /* from_scratch = */ true;
2377 }
2378
2379 r = -EINVAL;
2380 }
2381 if (r < 0)
2382 return log_error_errno(r, "Failed to open device '%s': %m", context->node);
2383
2384 if (context->backing_fd < 0) {
2385 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
2386 r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)),
2387 arg_dry_run ? LOCK_SH : LOCK_EX,
2388 &context->backing_fd);
2389 if (r < 0)
2390 return r;
2391 }
2392
2393 /* The offsets/sizes libfdisk returns to us will be in multiple of the sector size of the
2394 * device. This is typically 512, and sometimes 4096. Let's query libfdisk once for it, and then use
2395 * it for all our needs. Note that the values we use ourselves always are in bytes though, thus mean
2396 * the same thing universally. Also note that regardless what kind of sector size is in use we'll
2397 * place partitions at multiples of 4K. */
2398 secsz = fdisk_get_sector_size(c);
2399
2400 /* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
2401 if (secsz < 512 || !ISPOWEROF2(secsz))
2402 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
2403
2404 /* Use at least 4K, and ensure it's a multiple of the sector size, regardless if that is smaller or
2405 * larger */
2406 grainsz = secsz < 4096 ? 4096 : secsz;
2407
2408 log_debug("Sector size of device is %lu bytes. Using grain size of %" PRIu64 ".", secsz, grainsz);
2409
2410 switch (arg_empty) {
2411
2412 case EMPTY_REFUSE:
2413 /* Refuse empty disks, insist on an existing GPT partition table */
2414 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
2415 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", context->node);
2416
2417 break;
2418
2419 case EMPTY_REQUIRE:
2420 /* Require an empty disk, refuse any existing partition table */
2421 r = fdisk_has_label(c);
2422 if (r < 0)
2423 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
2424 if (r > 0)
2425 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", context->node);
2426
2427 from_scratch = true;
2428 break;
2429
2430 case EMPTY_ALLOW:
2431 /* Allow both an empty disk and an existing partition table, but only GPT */
2432 r = fdisk_has_label(c);
2433 if (r < 0)
2434 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
2435 if (r > 0) {
2436 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
2437 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", context->node);
2438 } else
2439 from_scratch = true;
2440
2441 break;
2442
2443 case EMPTY_FORCE:
2444 case EMPTY_CREATE:
2445 /* Always reinitiaize the disk, don't consider what there was on the disk before */
2446 from_scratch = true;
2447 break;
2448
2449 default:
2450 assert_not_reached();
2451 }
2452
2453 if (from_scratch) {
2454 r = fdisk_create_disklabel(c, "gpt");
2455 if (r < 0)
2456 return log_error_errno(r, "Failed to create GPT disk label: %m");
2457
2458 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
2459 if (r < 0)
2460 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
2461
2462 r = fdisk_set_disklabel_id_by_uuid(c, disk_uuid);
2463 if (r < 0)
2464 return log_error_errno(r, "Failed to set GPT disk label: %m");
2465
2466 goto add_initial_free_area;
2467 }
2468
2469 r = fdisk_get_disklabel_id(c, &disk_uuid_string);
2470 if (r < 0)
2471 return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
2472
2473 r = id128_from_string_nonzero(disk_uuid_string, &disk_uuid);
2474 if (r == -ENXIO) {
2475 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
2476 if (r < 0)
2477 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
2478
2479 r = fdisk_set_disklabel_id(c);
2480 if (r < 0)
2481 return log_error_errno(r, "Failed to set GPT disk label: %m");
2482 } else if (r < 0)
2483 return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
2484
2485 r = fdisk_get_partitions(c, &t);
2486 if (r < 0)
2487 return log_error_errno(r, "Failed to acquire partition table: %m");
2488
2489 n_partitions = fdisk_table_get_nents(t);
2490 for (size_t i = 0; i < n_partitions; i++) {
2491 _cleanup_free_ char *label_copy = NULL;
2492 Partition *last = NULL;
2493 struct fdisk_partition *p;
2494 const char *label;
2495 uint64_t sz, start;
2496 bool found = false;
2497 sd_id128_t ptid, id;
2498 size_t partno;
2499
2500 p = fdisk_table_get_partition(t, i);
2501 if (!p)
2502 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
2503
2504 if (fdisk_partition_is_used(p) <= 0)
2505 continue;
2506
2507 if (fdisk_partition_has_start(p) <= 0 ||
2508 fdisk_partition_has_size(p) <= 0 ||
2509 fdisk_partition_has_partno(p) <= 0)
2510 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
2511
2512 r = fdisk_partition_get_type_as_id128(p, &ptid);
2513 if (r < 0)
2514 return log_error_errno(r, "Failed to query partition type UUID: %m");
2515
2516 r = fdisk_partition_get_uuid_as_id128(p, &id);
2517 if (r < 0)
2518 return log_error_errno(r, "Failed to query partition UUID: %m");
2519
2520 label = fdisk_partition_get_name(p);
2521 if (!isempty(label)) {
2522 label_copy = strdup(label);
2523 if (!label_copy)
2524 return log_oom();
2525 }
2526
2527 sz = fdisk_partition_get_size(p);
2528 assert(sz <= UINT64_MAX/secsz);
2529 sz *= secsz;
2530
2531 start = fdisk_partition_get_start(p);
2532 assert(start <= UINT64_MAX/secsz);
2533 start *= secsz;
2534
2535 partno = fdisk_partition_get_partno(p);
2536
2537 if (left_boundary == UINT64_MAX || left_boundary > start)
2538 left_boundary = start;
2539
2540 /* Assign this existing partition to the first partition of the right type that doesn't have
2541 * an existing one assigned yet. */
2542 LIST_FOREACH(partitions, pp, context->partitions) {
2543 last = pp;
2544
2545 if (!sd_id128_equal(pp->type.uuid, ptid))
2546 continue;
2547
2548 if (!pp->current_partition) {
2549 pp->current_uuid = id;
2550 pp->current_size = sz;
2551 pp->offset = start;
2552 pp->partno = partno;
2553 pp->current_label = TAKE_PTR(label_copy);
2554
2555 pp->current_partition = p;
2556 fdisk_ref_partition(p);
2557
2558 r = determine_current_padding(c, t, p, secsz, grainsz, &pp->current_padding);
2559 if (r < 0)
2560 return r;
2561
2562 if (pp->current_padding > 0) {
2563 r = context_add_free_area(context, pp->current_padding, pp);
2564 if (r < 0)
2565 return r;
2566 }
2567
2568 found = true;
2569 break;
2570 }
2571 }
2572
2573 /* If we have no matching definition, create a new one. */
2574 if (!found) {
2575 _cleanup_(partition_freep) Partition *np = NULL;
2576
2577 np = partition_new();
2578 if (!np)
2579 return log_oom();
2580
2581 np->current_uuid = id;
2582 np->type = gpt_partition_type_from_uuid(ptid);
2583 np->current_size = sz;
2584 np->offset = start;
2585 np->partno = partno;
2586 np->current_label = TAKE_PTR(label_copy);
2587
2588 np->current_partition = p;
2589 fdisk_ref_partition(p);
2590
2591 r = determine_current_padding(c, t, p, secsz, grainsz, &np->current_padding);
2592 if (r < 0)
2593 return r;
2594
2595 if (np->current_padding > 0) {
2596 r = context_add_free_area(context, np->current_padding, np);
2597 if (r < 0)
2598 return r;
2599 }
2600
2601 LIST_INSERT_AFTER(partitions, context->partitions, last, TAKE_PTR(np));
2602 context->n_partitions++;
2603 }
2604 }
2605
2606 add_initial_free_area:
2607 nsectors = fdisk_get_nsectors(c);
2608 assert(nsectors <= UINT64_MAX/secsz);
2609 nsectors *= secsz;
2610
2611 first_lba = fdisk_get_first_lba(c);
2612 assert(first_lba <= UINT64_MAX/secsz);
2613 first_lba *= secsz;
2614
2615 last_lba = fdisk_get_last_lba(c);
2616 assert(last_lba < UINT64_MAX);
2617 last_lba++;
2618 assert(last_lba <= UINT64_MAX/secsz);
2619 last_lba *= secsz;
2620
2621 assert(last_lba >= first_lba);
2622
2623 if (left_boundary == UINT64_MAX) {
2624 /* No partitions at all? Then the whole disk is up for grabs. */
2625
2626 first_lba = round_up_size(first_lba, grainsz);
2627 last_lba = round_down_size(last_lba, grainsz);
2628
2629 if (last_lba > first_lba) {
2630 r = context_add_free_area(context, last_lba - first_lba, NULL);
2631 if (r < 0)
2632 return r;
2633 }
2634 } else {
2635 /* Add space left of first partition */
2636 assert(left_boundary >= first_lba);
2637
2638 first_lba = round_up_size(first_lba, grainsz);
2639 left_boundary = round_down_size(left_boundary, grainsz);
2640 last_lba = round_down_size(last_lba, grainsz);
2641
2642 if (left_boundary > first_lba) {
2643 r = context_add_free_area(context, left_boundary - first_lba, NULL);
2644 if (r < 0)
2645 return r;
2646 }
2647 }
2648
2649 context->start = first_lba;
2650 context->end = last_lba;
2651 context->total = nsectors;
2652 context->sector_size = secsz;
2653 context->fs_sector_size = fs_secsz;
2654 context->grain_size = grainsz;
2655 context->fdisk_context = TAKE_PTR(c);
2656
2657 return from_scratch;
2658 }
2659
2660 static void context_unload_partition_table(Context *context) {
2661 assert(context);
2662
2663 LIST_FOREACH(partitions, p, context->partitions) {
2664
2665 /* Entirely remove partitions that have no configuration */
2666 if (PARTITION_IS_FOREIGN(p)) {
2667 partition_unlink_and_free(context, p);
2668 continue;
2669 }
2670
2671 /* Otherwise drop all data we read off the block device and everything we might have
2672 * calculated based on it */
2673
2674 p->dropped = false;
2675 p->current_size = UINT64_MAX;
2676 p->new_size = UINT64_MAX;
2677 p->current_padding = UINT64_MAX;
2678 p->new_padding = UINT64_MAX;
2679 p->partno = UINT64_MAX;
2680 p->offset = UINT64_MAX;
2681
2682 if (p->current_partition) {
2683 fdisk_unref_partition(p->current_partition);
2684 p->current_partition = NULL;
2685 }
2686
2687 if (p->new_partition) {
2688 fdisk_unref_partition(p->new_partition);
2689 p->new_partition = NULL;
2690 }
2691
2692 p->padding_area = NULL;
2693 p->allocated_to_area = NULL;
2694
2695 p->current_uuid = SD_ID128_NULL;
2696 p->current_label = mfree(p->current_label);
2697 }
2698
2699 context->start = UINT64_MAX;
2700 context->end = UINT64_MAX;
2701 context->total = UINT64_MAX;
2702
2703 if (context->fdisk_context) {
2704 fdisk_unref_context(context->fdisk_context);
2705 context->fdisk_context = NULL;
2706 }
2707
2708 context_free_free_areas(context);
2709 }
2710
2711 static int format_size_change(uint64_t from, uint64_t to, char **ret) {
2712 char *t;
2713
2714 if (from != UINT64_MAX) {
2715 if (from == to || to == UINT64_MAX)
2716 t = strdup(FORMAT_BYTES(from));
2717 else
2718 t = strjoin(FORMAT_BYTES(from), " ", special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
2719 } else if (to != UINT64_MAX)
2720 t = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
2721 else {
2722 *ret = NULL;
2723 return 0;
2724 }
2725
2726 if (!t)
2727 return log_oom();
2728
2729 *ret = t;
2730 return 1;
2731 }
2732
2733 static const char *partition_label(const Partition *p) {
2734 assert(p);
2735
2736 if (p->new_label)
2737 return p->new_label;
2738
2739 if (p->current_label)
2740 return p->current_label;
2741
2742 return gpt_partition_type_uuid_to_string(p->type.uuid);
2743 }
2744
2745 static int context_dump_partitions(Context *context) {
2746 _cleanup_(table_unrefp) Table *t = NULL;
2747 uint64_t sum_padding = 0, sum_size = 0;
2748 int r;
2749 const size_t roothash_col = 14, dropin_files_col = 15, split_path_col = 16;
2750 bool has_roothash = false, has_dropin_files = false, has_split_path = false;
2751
2752 if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) {
2753 log_info("Empty partition table.");
2754 return 0;
2755 }
2756
2757 t = table_new("type",
2758 "label",
2759 "uuid",
2760 "partno",
2761 "file",
2762 "node",
2763 "offset",
2764 "old size",
2765 "raw size",
2766 "size",
2767 "old padding",
2768 "raw padding",
2769 "padding",
2770 "activity",
2771 "roothash",
2772 "drop-in files",
2773 "split path");
2774 if (!t)
2775 return log_oom();
2776
2777 if (!DEBUG_LOGGING) {
2778 if (arg_json_format_flags & JSON_FORMAT_OFF)
2779 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2780 (size_t) 8, (size_t) 9, (size_t) 12, roothash_col, dropin_files_col,
2781 split_path_col);
2782 else
2783 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2784 (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 8, (size_t) 10,
2785 (size_t) 11, (size_t) 13, roothash_col, dropin_files_col,
2786 split_path_col);
2787 }
2788
2789 (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
2790 (void) table_set_align_percent(t, table_get_cell(t, 0, 6), 100);
2791 (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100);
2792 (void) table_set_align_percent(t, table_get_cell(t, 0, 8), 100);
2793 (void) table_set_align_percent(t, table_get_cell(t, 0, 9), 100);
2794 (void) table_set_align_percent(t, table_get_cell(t, 0, 10), 100);
2795 (void) table_set_align_percent(t, table_get_cell(t, 0, 11), 100);
2796
2797 LIST_FOREACH(partitions, p, context->partitions) {
2798 _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL, *rh = NULL;
2799 char uuid_buffer[SD_ID128_UUID_STRING_MAX];
2800 const char *label, *activity = NULL;
2801
2802 if (p->dropped)
2803 continue;
2804
2805 if (p->current_size == UINT64_MAX)
2806 activity = "create";
2807 else if (p->current_size != p->new_size)
2808 activity = "resize";
2809
2810 label = partition_label(p);
2811 partname = p->partno != UINT64_MAX ? fdisk_partname(context->node, p->partno+1) : NULL;
2812
2813 r = format_size_change(p->current_size, p->new_size, &size_change);
2814 if (r < 0)
2815 return r;
2816
2817 r = format_size_change(p->current_padding, p->new_padding, &padding_change);
2818 if (r < 0)
2819 return r;
2820
2821 if (p->new_size != UINT64_MAX)
2822 sum_size += p->new_size;
2823 if (p->new_padding != UINT64_MAX)
2824 sum_padding += p->new_padding;
2825
2826 if (p->verity != VERITY_OFF) {
2827 Partition *hp = p->verity == VERITY_HASH ? p : p->siblings[VERITY_HASH];
2828
2829 rh = iovec_is_set(&hp->roothash) ? hexmem(hp->roothash.iov_base, hp->roothash.iov_len) : strdup("TBD");
2830 if (!rh)
2831 return log_oom();
2832 }
2833
2834 r = table_add_many(
2835 t,
2836 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type.uuid, uuid_buffer),
2837 TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
2838 TABLE_UUID, p->new_uuid_is_set ? p->new_uuid : p->current_uuid,
2839 TABLE_UINT64, p->partno,
2840 TABLE_PATH_BASENAME, p->definition_path, TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
2841 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
2842 TABLE_UINT64, p->offset,
2843 TABLE_UINT64, p->current_size == UINT64_MAX ? 0 : p->current_size,
2844 TABLE_UINT64, p->new_size,
2845 TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL,
2846 TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding,
2847 TABLE_UINT64, p->new_padding,
2848 TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL,
2849 TABLE_STRING, activity ?: "unchanged",
2850 TABLE_STRING, rh,
2851 TABLE_STRV, p->drop_in_files,
2852 TABLE_STRING, empty_to_null(p->split_path) ?: "-");
2853 if (r < 0)
2854 return table_log_add_error(r);
2855
2856 has_roothash = has_roothash || !isempty(rh);
2857 has_dropin_files = has_dropin_files || !strv_isempty(p->drop_in_files);
2858 has_split_path = has_split_path || !isempty(p->split_path);
2859 }
2860
2861 if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) {
2862 const char *a, *b;
2863
2864 a = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_size));
2865 b = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_padding));
2866
2867 r = table_add_many(
2868 t,
2869 TABLE_EMPTY,
2870 TABLE_EMPTY,
2871 TABLE_EMPTY,
2872 TABLE_EMPTY,
2873 TABLE_EMPTY,
2874 TABLE_EMPTY,
2875 TABLE_EMPTY,
2876 TABLE_EMPTY,
2877 TABLE_EMPTY,
2878 TABLE_STRING, a,
2879 TABLE_EMPTY,
2880 TABLE_EMPTY,
2881 TABLE_STRING, b,
2882 TABLE_EMPTY,
2883 TABLE_EMPTY,
2884 TABLE_EMPTY,
2885 TABLE_EMPTY);
2886 if (r < 0)
2887 return table_log_add_error(r);
2888 }
2889
2890 if (!has_roothash) {
2891 r = table_hide_column_from_display(t, roothash_col);
2892 if (r < 0)
2893 return log_error_errno(r, "Failed to set columns to display: %m");
2894 }
2895
2896 if (!has_dropin_files) {
2897 r = table_hide_column_from_display(t, dropin_files_col);
2898 if (r < 0)
2899 return log_error_errno(r, "Failed to set columns to display: %m");
2900 }
2901
2902 if (!has_split_path) {
2903 r = table_hide_column_from_display(t, split_path_col);
2904 if (r < 0)
2905 return log_error_errno(r, "Failed to set columns to display: %m");
2906 }
2907
2908 return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
2909 }
2910
2911 static void context_bar_char_process_partition(
2912 Context *context,
2913 Partition *bar[],
2914 size_t n,
2915 Partition *p,
2916 size_t *ret_start) {
2917
2918 uint64_t from, to, total;
2919 size_t x, y;
2920
2921 assert(context);
2922 assert(bar);
2923 assert(n > 0);
2924 assert(p);
2925
2926 if (p->dropped)
2927 return;
2928
2929 assert(p->offset != UINT64_MAX);
2930 assert(p->new_size != UINT64_MAX);
2931
2932 from = p->offset;
2933 to = from + p->new_size;
2934
2935 assert(context->total > 0);
2936 total = context->total;
2937
2938 assert(from <= total);
2939 x = from * n / total;
2940
2941 assert(to <= total);
2942 y = to * n / total;
2943
2944 assert(x <= y);
2945 assert(y <= n);
2946
2947 for (size_t i = x; i < y; i++)
2948 bar[i] = p;
2949
2950 *ret_start = x;
2951 }
2952
2953 static int partition_hint(const Partition *p, const char *node, char **ret) {
2954 _cleanup_free_ char *buf = NULL;
2955 const char *label;
2956 sd_id128_t id;
2957
2958 /* Tries really hard to find a suitable description for this partition */
2959
2960 if (p->definition_path)
2961 return path_extract_filename(p->definition_path, ret);
2962
2963 label = partition_label(p);
2964 if (!isempty(label)) {
2965 buf = strdup(label);
2966 goto done;
2967 }
2968
2969 if (p->partno != UINT64_MAX) {
2970 buf = fdisk_partname(node, p->partno+1);
2971 goto done;
2972 }
2973
2974 if (p->new_uuid_is_set)
2975 id = p->new_uuid;
2976 else if (!sd_id128_is_null(p->current_uuid))
2977 id = p->current_uuid;
2978 else
2979 id = p->type.uuid;
2980
2981 buf = strdup(SD_ID128_TO_UUID_STRING(id));
2982
2983 done:
2984 if (!buf)
2985 return -ENOMEM;
2986
2987 *ret = TAKE_PTR(buf);
2988 return 0;
2989 }
2990
2991 static int context_dump_partition_bar(Context *context) {
2992 _cleanup_free_ Partition **bar = NULL;
2993 _cleanup_free_ size_t *start_array = NULL;
2994 Partition *last = NULL;
2995 bool z = false;
2996 size_t c, j = 0;
2997
2998 assert_se((c = columns()) >= 2);
2999 c -= 2; /* We do not use the leftmost and rightmost character cell */
3000
3001 bar = new0(Partition*, c);
3002 if (!bar)
3003 return log_oom();
3004
3005 start_array = new(size_t, context->n_partitions);
3006 if (!start_array)
3007 return log_oom();
3008
3009 LIST_FOREACH(partitions, p, context->partitions)
3010 context_bar_char_process_partition(context, bar, c, p, start_array + j++);
3011
3012 putc(' ', stdout);
3013
3014 for (size_t i = 0; i < c; i++) {
3015 if (bar[i]) {
3016 if (last != bar[i])
3017 z = !z;
3018
3019 fputs(z ? ansi_green() : ansi_yellow(), stdout);
3020 fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE), stdout);
3021 } else {
3022 fputs(ansi_normal(), stdout);
3023 fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), stdout);
3024 }
3025
3026 last = bar[i];
3027 }
3028
3029 fputs(ansi_normal(), stdout);
3030 putc('\n', stdout);
3031
3032 for (size_t i = 0; i < context->n_partitions; i++) {
3033 _cleanup_free_ char **line = NULL;
3034
3035 line = new0(char*, c);
3036 if (!line)
3037 return log_oom();
3038
3039 j = 0;
3040 LIST_FOREACH(partitions, p, context->partitions) {
3041 _cleanup_free_ char *d = NULL;
3042 j++;
3043
3044 if (i < context->n_partitions - j) {
3045
3046 if (line[start_array[j-1]]) {
3047 const char *e;
3048
3049 /* Upgrade final corner to the right with a branch to the right */
3050 e = startswith(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
3051 if (e) {
3052 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), e);
3053 if (!d)
3054 return log_oom();
3055 }
3056 }
3057
3058 if (!d) {
3059 d = strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
3060 if (!d)
3061 return log_oom();
3062 }
3063
3064 } else if (i == context->n_partitions - j) {
3065 _cleanup_free_ char *hint = NULL;
3066
3067 (void) partition_hint(p, context->node, &hint);
3068
3069 if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)))
3070 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint));
3071 else
3072 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT), " ", strna(hint));
3073
3074 if (!d)
3075 return log_oom();
3076 }
3077
3078 if (d)
3079 free_and_replace(line[start_array[j-1]], d);
3080 }
3081
3082 putc(' ', stdout);
3083
3084 j = 0;
3085 while (j < c) {
3086 if (line[j]) {
3087 fputs(line[j], stdout);
3088 j += utf8_console_width(line[j]);
3089 } else {
3090 putc(' ', stdout);
3091 j++;
3092 }
3093 }
3094
3095 putc('\n', stdout);
3096
3097 for (j = 0; j < c; j++)
3098 free(line[j]);
3099 }
3100
3101 return 0;
3102 }
3103
3104 static bool context_has_roothash(Context *context) {
3105 LIST_FOREACH(partitions, p, context->partitions)
3106 if (iovec_is_set(&p->roothash))
3107 return true;
3108
3109 return false;
3110 }
3111
3112 static int context_dump(Context *context, bool late) {
3113 int r;
3114
3115 assert(context);
3116
3117 if (arg_pretty == 0 && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
3118 return 0;
3119
3120 /* If we're outputting JSON, only dump after doing all operations so we can include the roothashes
3121 * in the output. */
3122 if (!late && !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
3123 return 0;
3124
3125 /* If we're not outputting JSON, only dump again after doing all operations if there are any
3126 * roothashes that we need to communicate to the user. */
3127 if (late && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !context_has_roothash(context))
3128 return 0;
3129
3130 r = context_dump_partitions(context);
3131 if (r < 0)
3132 return r;
3133
3134 /* Make sure we only write the partition bar once, even if we're writing the partition table twice to
3135 * communicate roothashes. */
3136 if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !late) {
3137 putc('\n', stdout);
3138
3139 r = context_dump_partition_bar(context);
3140 if (r < 0)
3141 return r;
3142
3143 putc('\n', stdout);
3144 }
3145
3146 fflush(stdout);
3147
3148 return 0;
3149 }
3150
3151
3152 static bool context_changed(const Context *context) {
3153 assert(context);
3154
3155 LIST_FOREACH(partitions, p, context->partitions) {
3156 if (p->dropped)
3157 continue;
3158
3159 if (p->allocated_to_area)
3160 return true;
3161
3162 if (p->new_size != p->current_size)
3163 return true;
3164 }
3165
3166 return false;
3167 }
3168
3169 static int context_wipe_range(Context *context, uint64_t offset, uint64_t size) {
3170 _cleanup_(blkid_free_probep) blkid_probe probe = NULL;
3171 int r;
3172
3173 assert(context);
3174 assert(offset != UINT64_MAX);
3175 assert(size != UINT64_MAX);
3176
3177 probe = blkid_new_probe();
3178 if (!probe)
3179 return log_oom();
3180
3181 errno = 0;
3182 r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size);
3183 if (r < 0)
3184 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping.");
3185
3186 errno = 0;
3187 if (blkid_probe_enable_superblocks(probe, true) < 0 ||
3188 blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 ||
3189 blkid_probe_enable_partitions(probe, true) < 0 ||
3190 blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0)
3191 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing.");
3192
3193 for (;;) {
3194 errno = 0;
3195 r = blkid_do_probe(probe);
3196 if (r < 0)
3197 return log_error_errno(errno_or_else(EIO), "Failed to probe for file systems.");
3198 if (r > 0)
3199 break;
3200
3201 errno = 0;
3202 if (blkid_do_wipe(probe, false) < 0)
3203 return log_error_errno(errno_or_else(EIO), "Failed to wipe file system signature.");
3204 }
3205
3206 return 0;
3207 }
3208
3209 static int context_wipe_partition(Context *context, Partition *p) {
3210 int r;
3211
3212 assert(context);
3213 assert(p);
3214 assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */
3215
3216 assert(p->offset != UINT64_MAX);
3217 assert(p->new_size != UINT64_MAX);
3218
3219 r = context_wipe_range(context, p->offset, p->new_size);
3220 if (r < 0)
3221 return r;
3222
3223 log_info("Successfully wiped file system signatures from future partition %" PRIu64 ".", p->partno);
3224 return 0;
3225 }
3226
3227 static int context_discard_range(
3228 Context *context,
3229 uint64_t offset,
3230 uint64_t size) {
3231
3232 struct stat st;
3233 int fd;
3234
3235 assert(context);
3236 assert(offset != UINT64_MAX);
3237 assert(size != UINT64_MAX);
3238
3239 if (size <= 0)
3240 return 0;
3241
3242 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3243
3244 if (fstat(fd, &st) < 0)
3245 return -errno;
3246
3247 if (S_ISREG(st.st_mode)) {
3248 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, size) < 0) {
3249 if (ERRNO_IS_NOT_SUPPORTED(errno))
3250 return -EOPNOTSUPP;
3251
3252 return -errno;
3253 }
3254
3255 return 1;
3256 }
3257
3258 if (S_ISBLK(st.st_mode)) {
3259 uint64_t range[2], end;
3260
3261 range[0] = round_up_size(offset, context->sector_size);
3262
3263 if (offset > UINT64_MAX - size)
3264 return -ERANGE;
3265
3266 end = offset + size;
3267 if (end <= range[0])
3268 return 0;
3269
3270 range[1] = round_down_size(end - range[0], context->sector_size);
3271 if (range[1] <= 0)
3272 return 0;
3273
3274 if (ioctl(fd, BLKDISCARD, range) < 0) {
3275 if (ERRNO_IS_NOT_SUPPORTED(errno))
3276 return -EOPNOTSUPP;
3277
3278 return -errno;
3279 }
3280
3281 return 1;
3282 }
3283
3284 return -EOPNOTSUPP;
3285 }
3286
3287 static int context_discard_partition(Context *context, Partition *p) {
3288 int r;
3289
3290 assert(context);
3291 assert(p);
3292
3293 assert(p->offset != UINT64_MAX);
3294 assert(p->new_size != UINT64_MAX);
3295 assert(!PARTITION_EXISTS(p)); /* Safety check: never discard existing partitions */
3296
3297 if (!arg_discard)
3298 return 0;
3299
3300 r = context_discard_range(context, p->offset, p->new_size);
3301 if (r == -EOPNOTSUPP) {
3302 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno);
3303 return 0;
3304 }
3305 if (r == -EBUSY) {
3306 /* Let's handle this gracefully: https://bugzilla.kernel.org/show_bug.cgi?id=211167 */
3307 log_info("Block device is busy, not discarding partition %" PRIu64 " because it probably is mounted.", p->partno);
3308 return 0;
3309 }
3310 if (r == 0) {
3311 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
3312 return 0;
3313 }
3314 if (r < 0)
3315 return log_error_errno(r, "Failed to discard data for future partition %" PRIu64 ".", p->partno);
3316
3317 log_info("Successfully discarded data from future partition %" PRIu64 ".", p->partno);
3318 return 1;
3319 }
3320
3321 static int context_discard_gap_after(Context *context, Partition *p) {
3322 uint64_t gap, next = UINT64_MAX;
3323 int r;
3324
3325 assert(context);
3326 assert(!p || (p->offset != UINT64_MAX && p->new_size != UINT64_MAX));
3327
3328 if (!arg_discard)
3329 return 0;
3330
3331 if (p)
3332 gap = p->offset + p->new_size;
3333 else
3334 /* The context start gets rounded up to grain_size, however
3335 * existing partitions may be before that so ensure the gap
3336 * starts at the first actually usable lba
3337 */
3338 gap = fdisk_get_first_lba(context->fdisk_context) * context->sector_size;
3339
3340 LIST_FOREACH(partitions, q, context->partitions) {
3341 if (q->dropped)
3342 continue;
3343
3344 assert(q->offset != UINT64_MAX);
3345 assert(q->new_size != UINT64_MAX);
3346
3347 if (q->offset < gap)
3348 continue;
3349
3350 if (next == UINT64_MAX || q->offset < next)
3351 next = q->offset;
3352 }
3353
3354 if (next == UINT64_MAX) {
3355 next = (fdisk_get_last_lba(context->fdisk_context) + 1) * context->sector_size;
3356 if (gap > next)
3357 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
3358 }
3359
3360 assert(next >= gap);
3361 r = context_discard_range(context, gap, next - gap);
3362 if (r == -EOPNOTSUPP) {
3363 if (p)
3364 log_info("Storage does not support discard, not discarding gap after partition %" PRIu64 ".", p->partno);
3365 else
3366 log_info("Storage does not support discard, not discarding gap at beginning of disk.");
3367 return 0;
3368 }
3369 if (r == 0) /* Too short */
3370 return 0;
3371 if (r < 0) {
3372 if (p)
3373 return log_error_errno(r, "Failed to discard gap after partition %" PRIu64 ".", p->partno);
3374 else
3375 return log_error_errno(r, "Failed to discard gap at beginning of disk.");
3376 }
3377
3378 if (p)
3379 log_info("Successfully discarded gap after partition %" PRIu64 ".", p->partno);
3380 else
3381 log_info("Successfully discarded gap at beginning of disk.");
3382
3383 return 0;
3384 }
3385
3386 static int context_wipe_and_discard(Context *context) {
3387 int r;
3388
3389 assert(context);
3390
3391 if (arg_empty == EMPTY_CREATE) /* If we just created the image, no need to wipe */
3392 return 0;
3393
3394 /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
3395 * we were supposed to start from scratch anyway, as in that case we just discard the whole block
3396 * device in one go early on. */
3397
3398 LIST_FOREACH(partitions, p, context->partitions) {
3399
3400 if (!p->allocated_to_area)
3401 continue;
3402
3403 if (partition_type_defer(&p->type))
3404 continue;
3405
3406 r = context_wipe_partition(context, p);
3407 if (r < 0)
3408 return r;
3409
3410 if (!context->from_scratch) {
3411 r = context_discard_partition(context, p);
3412 if (r < 0)
3413 return r;
3414
3415 r = context_discard_gap_after(context, p);
3416 if (r < 0)
3417 return r;
3418 }
3419 }
3420
3421 if (!context->from_scratch) {
3422 r = context_discard_gap_after(context, NULL);
3423 if (r < 0)
3424 return r;
3425 }
3426
3427 return 0;
3428 }
3429
3430 typedef struct DecryptedPartitionTarget {
3431 int fd;
3432 char *dm_name;
3433 char *volume;
3434 struct crypt_device *device;
3435 } DecryptedPartitionTarget;
3436
3437 static DecryptedPartitionTarget* decrypted_partition_target_free(DecryptedPartitionTarget *t) {
3438 #if HAVE_LIBCRYPTSETUP
3439 int r;
3440
3441 if (!t)
3442 return NULL;
3443
3444 safe_close(t->fd);
3445
3446 /* udev or so might access out block device in the background while we are done. Let's hence
3447 * force detach the volume. We sync'ed before, hence this should be safe. */
3448 r = sym_crypt_deactivate_by_name(t->device, t->dm_name, CRYPT_DEACTIVATE_FORCE);
3449 if (r < 0)
3450 log_warning_errno(r, "Failed to deactivate LUKS device, ignoring: %m");
3451
3452 sym_crypt_free(t->device);
3453 free(t->dm_name);
3454 free(t->volume);
3455 free(t);
3456 #endif
3457 return NULL;
3458 }
3459
3460 typedef struct {
3461 LoopDevice *loop;
3462 int fd;
3463 char *path;
3464 int whole_fd;
3465 DecryptedPartitionTarget *decrypted;
3466 } PartitionTarget;
3467
3468 static int partition_target_fd(PartitionTarget *t) {
3469 assert(t);
3470 assert(t->loop || t->fd >= 0 || t->whole_fd >= 0);
3471
3472 if (t->decrypted)
3473 return t->decrypted->fd;
3474
3475 if (t->loop)
3476 return t->loop->fd;
3477
3478 if (t->fd >= 0)
3479 return t->fd;
3480
3481 return t->whole_fd;
3482 }
3483
3484 static const char* partition_target_path(PartitionTarget *t) {
3485 assert(t);
3486 assert(t->loop || t->path);
3487
3488 if (t->decrypted)
3489 return t->decrypted->volume;
3490
3491 if (t->loop)
3492 return t->loop->node;
3493
3494 return t->path;
3495 }
3496
3497 static PartitionTarget *partition_target_free(PartitionTarget *t) {
3498 if (!t)
3499 return NULL;
3500
3501 decrypted_partition_target_free(t->decrypted);
3502 loop_device_unref(t->loop);
3503 safe_close(t->fd);
3504 unlink_and_free(t->path);
3505
3506 return mfree(t);
3507 }
3508
3509 DEFINE_TRIVIAL_CLEANUP_FUNC(PartitionTarget*, partition_target_free);
3510
3511 static int prepare_temporary_file(PartitionTarget *t, uint64_t size) {
3512 _cleanup_(unlink_and_freep) char *temp = NULL;
3513 _cleanup_close_ int fd = -EBADF;
3514 const char *vt;
3515 int r;
3516
3517 assert(t);
3518
3519 r = var_tmp_dir(&vt);
3520 if (r < 0)
3521 return log_error_errno(r, "Could not determine temporary directory: %m");
3522
3523 temp = path_join(vt, "repart-XXXXXX");
3524 if (!temp)
3525 return log_oom();
3526
3527 fd = mkostemp_safe(temp);
3528 if (fd < 0)
3529 return log_error_errno(fd, "Failed to create temporary file: %m");
3530
3531 if (ftruncate(fd, size) < 0)
3532 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m",
3533 FORMAT_BYTES(size));
3534
3535 t->fd = TAKE_FD(fd);
3536 t->path = TAKE_PTR(temp);
3537
3538 return 0;
3539 }
3540
3541 static int partition_target_prepare(
3542 Context *context,
3543 Partition *p,
3544 uint64_t size,
3545 bool need_path,
3546 PartitionTarget **ret) {
3547
3548 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
3549 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
3550 int whole_fd, r;
3551
3552 assert(context);
3553 assert(p);
3554 assert(ret);
3555
3556 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3557
3558 t = new(PartitionTarget, 1);
3559 if (!t)
3560 return log_oom();
3561 *t = (PartitionTarget) {
3562 .fd = -EBADF,
3563 .whole_fd = -EBADF,
3564 };
3565
3566 if (!need_path) {
3567 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
3568 return log_error_errno(errno, "Failed to seek to partition offset: %m");
3569
3570 t->whole_fd = whole_fd;
3571 *ret = TAKE_PTR(t);
3572 return 0;
3573 }
3574
3575 /* Loopback block devices are not only useful to turn regular files into block devices, but
3576 * also to cut out sections of block devices into new block devices. */
3577
3578 if (arg_offline <= 0) {
3579 r = loop_device_make(whole_fd, O_RDWR, p->offset, size, context->sector_size, 0, LOCK_EX, &d);
3580 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
3581 return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
3582 if (r >= 0) {
3583 t->loop = TAKE_PTR(d);
3584 *ret = TAKE_PTR(t);
3585 return 0;
3586 }
3587
3588 log_debug_errno(r, "No access to loop devices, falling back to a regular file");
3589 }
3590
3591 /* If we can't allocate a loop device, let's write to a regular file that we copy into the final
3592 * image so we can run in containers and without needing root privileges. On filesystems with
3593 * reflinking support, we can take advantage of this and just reflink the result into the image.
3594 */
3595
3596 r = prepare_temporary_file(t, size);
3597 if (r < 0)
3598 return r;
3599
3600 *ret = TAKE_PTR(t);
3601
3602 return 0;
3603 }
3604
3605 static int partition_target_grow(PartitionTarget *t, uint64_t size) {
3606 int r;
3607
3608 assert(t);
3609 assert(!t->decrypted);
3610
3611 if (t->loop) {
3612 r = loop_device_refresh_size(t->loop, UINT64_MAX, size);
3613 if (r < 0)
3614 return log_error_errno(r, "Failed to refresh loopback device size: %m");
3615 } else if (t->fd >= 0) {
3616 if (ftruncate(t->fd, size) < 0)
3617 return log_error_errno(errno, "Failed to grow '%s' to %s by truncation: %m",
3618 t->path, FORMAT_BYTES(size));
3619 }
3620
3621 return 0;
3622 }
3623
3624 static int partition_target_sync(Context *context, Partition *p, PartitionTarget *t) {
3625 int whole_fd, r;
3626
3627 assert(context);
3628 assert(p);
3629 assert(t);
3630
3631 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3632
3633 if (t->decrypted && fsync(t->decrypted->fd) < 0)
3634 return log_error_errno(errno, "Failed to sync changes to '%s': %m", t->decrypted->volume);
3635
3636 if (t->loop) {
3637 r = loop_device_sync(t->loop);
3638 if (r < 0)
3639 return log_error_errno(r, "Failed to sync loopback device: %m");
3640 } else if (t->fd >= 0) {
3641 struct stat st;
3642
3643 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
3644 return log_error_errno(errno, "Failed to seek to partition offset: %m");
3645
3646 if (lseek(t->fd, 0, SEEK_SET) < 0)
3647 return log_error_errno(errno, "Failed to seek to start of temporary file: %m");
3648
3649 if (fstat(t->fd, &st) < 0)
3650 return log_error_errno(errno, "Failed to stat temporary file: %m");
3651
3652 if (st.st_size > (off_t) p->new_size)
3653 return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
3654 "Partition %" PRIu64 "'s contents (%s) don't fit in the partition (%s)",
3655 p->partno, FORMAT_BYTES(st.st_size), FORMAT_BYTES(p->new_size));
3656
3657 r = copy_bytes(t->fd, whole_fd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_FSYNC);
3658 if (r < 0)
3659 return log_error_errno(r, "Failed to copy bytes to partition: %m");
3660 } else {
3661 if (fsync(t->whole_fd) < 0)
3662 return log_error_errno(errno, "Failed to sync changes: %m");
3663 }
3664
3665 return 0;
3666 }
3667
3668 static int partition_encrypt(Context *context, Partition *p, PartitionTarget *target, bool offline) {
3669 #if HAVE_LIBCRYPTSETUP && HAVE_CRYPT_SET_DATA_OFFSET && HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE && HAVE_CRYPT_REENCRYPT
3670 const char *node = partition_target_path(target);
3671 struct crypt_params_luks2 luks_params = {
3672 .label = strempty(ASSERT_PTR(p)->new_label),
3673 .sector_size = ASSERT_PTR(context)->fs_sector_size,
3674 .data_device = offline ? node : NULL,
3675 };
3676 struct crypt_params_reencrypt reencrypt_params = {
3677 .mode = CRYPT_REENCRYPT_ENCRYPT,
3678 .direction = CRYPT_REENCRYPT_BACKWARD,
3679 .resilience = "datashift",
3680 .data_shift = LUKS2_METADATA_SIZE / 512,
3681 .luks2 = &luks_params,
3682 .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY|CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT,
3683 };
3684 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
3685 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
3686 _cleanup_fclose_ FILE *h = NULL;
3687 _cleanup_free_ char *hp = NULL, *vol = NULL, *dm_name = NULL;
3688 const char *passphrase = NULL;
3689 size_t passphrase_size = 0;
3690 const char *vt;
3691 int r;
3692
3693 assert(context);
3694 assert(p);
3695 assert(p->encrypt != ENCRYPT_OFF);
3696
3697 r = dlopen_cryptsetup();
3698 if (r < 0)
3699 return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m");
3700
3701 log_info("Encrypting future partition %" PRIu64 "...", p->partno);
3702
3703 if (offline) {
3704 r = var_tmp_dir(&vt);
3705 if (r < 0)
3706 return log_error_errno(r, "Failed to determine temporary files directory: %m");
3707
3708 r = fopen_temporary_child(vt, &h, &hp);
3709 if (r < 0)
3710 return log_error_errno(r, "Failed to create temporary LUKS header file: %m");
3711
3712 /* Weird cryptsetup requirement which requires the header file to be the size of at least one
3713 * sector. */
3714 if (ftruncate(fileno(h), luks_params.sector_size) < 0)
3715 return log_error_errno(errno, "Failed to grow temporary LUKS header file: %m");
3716 } else {
3717 if (asprintf(&dm_name, "luks-repart-%08" PRIx64, random_u64()) < 0)
3718 return log_oom();
3719
3720 vol = path_join("/dev/mapper/", dm_name);
3721 if (!vol)
3722 return log_oom();
3723 }
3724
3725 r = sym_crypt_init(&cd, offline ? hp : node);
3726 if (r < 0)
3727 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", hp);
3728
3729 cryptsetup_enable_logging(cd);
3730
3731 if (offline) {
3732 /* Disable kernel keyring usage by libcryptsetup as a workaround for
3733 * https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/273. This makes sure that we can
3734 * do offline encryption even when repart is running in a container. */
3735 r = sym_crypt_volume_key_keyring(cd, false);
3736 if (r < 0)
3737 return log_error_errno(r, "Failed to disable kernel keyring: %m");
3738
3739 r = sym_crypt_metadata_locking(cd, false);
3740 if (r < 0)
3741 return log_error_errno(r, "Failed to disable metadata locking: %m");
3742
3743 r = sym_crypt_set_data_offset(cd, LUKS2_METADATA_SIZE / 512);
3744 if (r < 0)
3745 return log_error_errno(r, "Failed to set data offset: %m");
3746 }
3747
3748 r = sym_crypt_format(
3749 cd,
3750 CRYPT_LUKS2,
3751 "aes",
3752 "xts-plain64",
3753 SD_ID128_TO_UUID_STRING(p->luks_uuid),
3754 NULL,
3755 VOLUME_KEY_SIZE,
3756 &luks_params);
3757 if (r < 0)
3758 return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
3759
3760 if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
3761 r = sym_crypt_keyslot_add_by_volume_key(
3762 cd,
3763 CRYPT_ANY_SLOT,
3764 NULL,
3765 VOLUME_KEY_SIZE,
3766 strempty(arg_key),
3767 arg_key_size);
3768 if (r < 0)
3769 return log_error_errno(r, "Failed to add LUKS2 key: %m");
3770
3771 passphrase = strempty(arg_key);
3772 passphrase_size = arg_key_size;
3773 }
3774
3775 if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
3776 #if HAVE_TPM2
3777 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
3778 _cleanup_(erase_and_freep) void *secret = NULL;
3779 _cleanup_free_ void *pubkey = NULL;
3780 _cleanup_free_ void *blob = NULL, *srk_buf = NULL;
3781 size_t secret_size, blob_size, pubkey_size = 0, srk_buf_size = 0;
3782 ssize_t base64_encoded_size;
3783 int keyslot;
3784 TPM2Flags flags = 0;
3785
3786 if (arg_tpm2_public_key_pcr_mask != 0) {
3787 r = tpm2_load_pcr_public_key(arg_tpm2_public_key, &pubkey, &pubkey_size);
3788 if (r < 0) {
3789 if (arg_tpm2_public_key || r != -ENOENT)
3790 return log_error_errno(r, "Failed to read TPM PCR public key: %m");
3791
3792 log_debug_errno(r, "Failed to read TPM2 PCR public key, proceeding without: %m");
3793 arg_tpm2_public_key_pcr_mask = 0;
3794 }
3795 }
3796
3797 TPM2B_PUBLIC public;
3798 if (pubkey) {
3799 r = tpm2_tpm2b_public_from_pem(pubkey, pubkey_size, &public);
3800 if (r < 0)
3801 return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m");
3802 }
3803
3804 _cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
3805 if (arg_tpm2_pcrlock) {
3806 r = tpm2_pcrlock_policy_load(arg_tpm2_pcrlock, &pcrlock_policy);
3807 if (r < 0)
3808 return r;
3809
3810 flags |= TPM2_FLAGS_USE_PCRLOCK;
3811 }
3812
3813 _cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
3814 TPM2B_PUBLIC device_key_public = {};
3815 if (arg_tpm2_device_key) {
3816 r = tpm2_load_public_key_file(arg_tpm2_device_key, &device_key_public);
3817 if (r < 0)
3818 return r;
3819
3820 if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values))
3821 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3822 "Must provide all PCR values when using TPM2 device key.");
3823 } else {
3824 r = tpm2_context_new(arg_tpm2_device, &tpm2_context);
3825 if (r < 0)
3826 return log_error_errno(r, "Failed to create TPM2 context: %m");
3827
3828 if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values)) {
3829 r = tpm2_pcr_read_missing_values(tpm2_context, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values);
3830 if (r < 0)
3831 return log_error_errno(r, "Could not read pcr values: %m");
3832 }
3833 }
3834
3835 uint16_t hash_pcr_bank = 0;
3836 uint32_t hash_pcr_mask = 0;
3837 if (arg_tpm2_n_hash_pcr_values > 0) {
3838 size_t hash_count;
3839 r = tpm2_pcr_values_hash_count(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, &hash_count);
3840 if (r < 0)
3841 return log_error_errno(r, "Could not get hash count: %m");
3842
3843 if (hash_count > 1)
3844 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
3845
3846 hash_pcr_bank = arg_tpm2_hash_pcr_values[0].hash;
3847 r = tpm2_pcr_values_to_mask(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, hash_pcr_bank, &hash_pcr_mask);
3848 if (r < 0)
3849 return log_error_errno(r, "Could not get hash mask: %m");
3850 }
3851
3852 TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
3853 r = tpm2_calculate_sealing_policy(
3854 arg_tpm2_hash_pcr_values,
3855 arg_tpm2_n_hash_pcr_values,
3856 pubkey ? &public : NULL,
3857 /* use_pin= */ false,
3858 arg_tpm2_pcrlock ? &pcrlock_policy : NULL,
3859 &policy);
3860 if (r < 0)
3861 return log_error_errno(r, "Could not calculate sealing policy digest: %m");
3862
3863 if (arg_tpm2_device_key)
3864 r = tpm2_calculate_seal(
3865 arg_tpm2_seal_key_handle,
3866 &device_key_public,
3867 /* attributes= */ NULL,
3868 /* secret= */ NULL, /* secret_size= */ 0,
3869 &policy,
3870 /* pin= */ NULL,
3871 &secret, &secret_size,
3872 &blob, &blob_size,
3873 &srk_buf, &srk_buf_size);
3874 else
3875 r = tpm2_seal(tpm2_context,
3876 arg_tpm2_seal_key_handle,
3877 &policy,
3878 /* pin= */ NULL,
3879 &secret, &secret_size,
3880 &blob, &blob_size,
3881 /* ret_primary_alg= */ NULL,
3882 &srk_buf, &srk_buf_size);
3883 if (r < 0)
3884 return log_error_errno(r, "Failed to seal to TPM2: %m");
3885
3886 base64_encoded_size = base64mem(secret, secret_size, &base64_encoded);
3887 if (base64_encoded_size < 0)
3888 return log_error_errno(base64_encoded_size, "Failed to base64 encode secret key: %m");
3889
3890 r = cryptsetup_set_minimal_pbkdf(cd);
3891 if (r < 0)
3892 return log_error_errno(r, "Failed to set minimal PBKDF: %m");
3893
3894 keyslot = sym_crypt_keyslot_add_by_volume_key(
3895 cd,
3896 CRYPT_ANY_SLOT,
3897 /* volume_key= */ NULL,
3898 /* volume_key_size= */ VOLUME_KEY_SIZE,
3899 base64_encoded,
3900 base64_encoded_size);
3901 if (keyslot < 0)
3902 return log_error_errno(keyslot, "Failed to add new TPM2 key: %m");
3903
3904 r = tpm2_make_luks2_json(
3905 keyslot,
3906 hash_pcr_mask,
3907 hash_pcr_bank,
3908 pubkey, pubkey_size,
3909 arg_tpm2_public_key_pcr_mask,
3910 /* primary_alg= */ 0,
3911 blob, blob_size,
3912 policy.buffer, policy.size,
3913 NULL, 0, /* no salt because tpm2_seal has no pin */
3914 srk_buf, srk_buf_size,
3915 flags,
3916 &v);
3917 if (r < 0)
3918 return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
3919
3920 r = cryptsetup_add_token_json(cd, v);
3921 if (r < 0)
3922 return log_error_errno(r, "Failed to add TPM2 JSON token to LUKS2 header: %m");
3923
3924 passphrase = base64_encoded;
3925 passphrase_size = strlen(base64_encoded);
3926 #else
3927 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3928 "Support for TPM2 enrollment not enabled.");
3929 #endif
3930 }
3931
3932 if (offline) {
3933 r = sym_crypt_reencrypt_init_by_passphrase(
3934 cd,
3935 NULL,
3936 passphrase,
3937 passphrase_size,
3938 CRYPT_ANY_SLOT,
3939 0,
3940 sym_crypt_get_cipher(cd),
3941 sym_crypt_get_cipher_mode(cd),
3942 &reencrypt_params);
3943 if (r < 0)
3944 return log_error_errno(r, "Failed to prepare for reencryption: %m");
3945
3946 /* crypt_reencrypt_init_by_passphrase() doesn't actually put the LUKS header at the front, we
3947 * have to do that ourselves. */
3948
3949 sym_crypt_free(cd);
3950 cd = NULL;
3951
3952 r = sym_crypt_init(&cd, node);
3953 if (r < 0)
3954 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", node);
3955
3956 r = sym_crypt_header_restore(cd, CRYPT_LUKS2, hp);
3957 if (r < 0)
3958 return log_error_errno(r, "Failed to place new LUKS header at head of %s: %m", node);
3959
3960 reencrypt_params.flags &= ~CRYPT_REENCRYPT_INITIALIZE_ONLY;
3961
3962 r = sym_crypt_reencrypt_init_by_passphrase(
3963 cd,
3964 NULL,
3965 passphrase,
3966 passphrase_size,
3967 CRYPT_ANY_SLOT,
3968 0,
3969 NULL,
3970 NULL,
3971 &reencrypt_params);
3972 if (r < 0)
3973 return log_error_errno(r, "Failed to load reencryption context: %m");
3974
3975 r = sym_crypt_reencrypt(cd, NULL);
3976 if (r < 0)
3977 return log_error_errno(r, "Failed to encrypt %s: %m", node);
3978 } else {
3979 _cleanup_free_ DecryptedPartitionTarget *t = NULL;
3980 _cleanup_close_ int dev_fd = -1;
3981
3982 r = sym_crypt_activate_by_volume_key(
3983 cd,
3984 dm_name,
3985 NULL,
3986 VOLUME_KEY_SIZE,
3987 arg_discard ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0);
3988 if (r < 0)
3989 return log_error_errno(r, "Failed to activate LUKS superblock: %m");
3990
3991 dev_fd = open(vol, O_RDWR|O_CLOEXEC|O_NOCTTY);
3992 if (dev_fd < 0)
3993 return log_error_errno(errno, "Failed to open LUKS volume '%s': %m", vol);
3994
3995 if (flock(dev_fd, LOCK_EX) < 0)
3996 return log_error_errno(errno, "Failed to lock '%s': %m", vol);
3997
3998 t = new(DecryptedPartitionTarget, 1);
3999 if (!t)
4000 return log_oom();
4001
4002 *t = (DecryptedPartitionTarget) {
4003 .fd = TAKE_FD(dev_fd),
4004 .dm_name = TAKE_PTR(dm_name),
4005 .volume = TAKE_PTR(vol),
4006 .device = TAKE_PTR(cd),
4007 };
4008
4009 target->decrypted = TAKE_PTR(t);
4010 }
4011
4012 log_info("Successfully encrypted future partition %" PRIu64 ".", p->partno);
4013
4014 return 0;
4015 #else
4016 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4017 "libcryptsetup is not supported or is missing required symbols, cannot encrypt: %m");
4018 #endif
4019 }
4020
4021 static int partition_format_verity_hash(
4022 Context *context,
4023 Partition *p,
4024 const char *node,
4025 const char *data_node) {
4026
4027 #if HAVE_LIBCRYPTSETUP
4028 Partition *dp;
4029 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4030 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
4031 _cleanup_free_ char *hint = NULL;
4032 int r;
4033
4034 assert(context);
4035 assert(p);
4036 assert(p->verity == VERITY_HASH);
4037 assert(data_node);
4038
4039 if (p->dropped)
4040 return 0;
4041
4042 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
4043 return 0;
4044
4045 /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
4046 if (p->copy_blocks_fd >= 0)
4047 return 0;
4048
4049 assert_se(dp = p->siblings[VERITY_DATA]);
4050 assert(!dp->dropped);
4051
4052 (void) partition_hint(p, node, &hint);
4053
4054 r = dlopen_cryptsetup();
4055 if (r < 0)
4056 return log_error_errno(r, "libcryptsetup not found, cannot setup verity: %m");
4057
4058 if (!node) {
4059 r = partition_target_prepare(context, p, p->new_size, /*need_path=*/ true, &t);
4060 if (r < 0)
4061 return r;
4062
4063 node = partition_target_path(t);
4064 }
4065
4066 if (p->verity_data_block_size == UINT64_MAX)
4067 p->verity_data_block_size = context->fs_sector_size;
4068 if (p->verity_hash_block_size == UINT64_MAX)
4069 p->verity_hash_block_size = context->fs_sector_size;
4070
4071 r = sym_crypt_init(&cd, node);
4072 if (r < 0)
4073 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", node);
4074
4075 cryptsetup_enable_logging(cd);
4076
4077 r = sym_crypt_format(
4078 cd, CRYPT_VERITY, NULL, NULL, SD_ID128_TO_UUID_STRING(p->verity_uuid), NULL, 0,
4079 &(struct crypt_params_verity){
4080 .data_device = data_node,
4081 .flags = CRYPT_VERITY_CREATE_HASH,
4082 .hash_name = "sha256",
4083 .hash_type = 1,
4084 .data_block_size = p->verity_data_block_size,
4085 .hash_block_size = p->verity_hash_block_size,
4086 .salt_size = sizeof(p->verity_salt),
4087 .salt = (const char*)p->verity_salt,
4088 });
4089 if (r < 0) {
4090 /* libcryptsetup reports non-descriptive EIO errors for every I/O failure. Luckily, it
4091 * doesn't clobber errno so let's check for ENOSPC so we can report a better error if the
4092 * partition is too small. */
4093 if (r == -EIO && errno == ENOSPC)
4094 return log_error_errno(errno,
4095 "Verity hash data does not fit in partition %s with size %s",
4096 strna(hint), FORMAT_BYTES(p->new_size));
4097
4098 return log_error_errno(r, "Failed to setup verity hash data of partition %s: %m", strna(hint));
4099 }
4100
4101 if (t) {
4102 r = partition_target_sync(context, p, t);
4103 if (r < 0)
4104 return r;
4105 }
4106
4107 r = sym_crypt_get_volume_key_size(cd);
4108 if (r < 0)
4109 return log_error_errno(r, "Failed to determine verity root hash size of partition %s: %m", strna(hint));
4110
4111 _cleanup_(iovec_done) struct iovec rh = {
4112 .iov_base = malloc(r),
4113 .iov_len = r,
4114 };
4115 if (!rh.iov_base)
4116 return log_oom();
4117
4118 r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, (char *) rh.iov_base, &rh.iov_len, NULL, 0);
4119 if (r < 0)
4120 return log_error_errno(r, "Failed to get verity root hash of partition %s: %m", strna(hint));
4121
4122 assert(rh.iov_len >= sizeof(sd_id128_t) * 2);
4123
4124 if (!dp->new_uuid_is_set) {
4125 memcpy_safe(dp->new_uuid.bytes, rh.iov_base, sizeof(sd_id128_t));
4126 dp->new_uuid_is_set = true;
4127 }
4128
4129 if (!p->new_uuid_is_set) {
4130 memcpy_safe(p->new_uuid.bytes, (uint8_t*) rh.iov_base + (rh.iov_len - sizeof(sd_id128_t)), sizeof(sd_id128_t));
4131 p->new_uuid_is_set = true;
4132 }
4133
4134 p->roothash = TAKE_STRUCT(rh);
4135
4136 return 0;
4137 #else
4138 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libcryptsetup is not supported, cannot setup verity hashes: %m");
4139 #endif
4140 }
4141
4142 static int sign_verity_roothash(
4143 const struct iovec *roothash,
4144 struct iovec *ret_signature) {
4145
4146 #if HAVE_OPENSSL
4147 _cleanup_(BIO_freep) BIO *rb = NULL;
4148 _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
4149 _cleanup_free_ char *hex = NULL;
4150 _cleanup_free_ uint8_t *sig = NULL;
4151 int sigsz;
4152
4153 assert(roothash);
4154 assert(iovec_is_set(roothash));
4155 assert(ret_signature);
4156
4157 hex = hexmem(roothash->iov_base, roothash->iov_len);
4158 if (!hex)
4159 return log_oom();
4160
4161 rb = BIO_new_mem_buf(hex, -1);
4162 if (!rb)
4163 return log_oom();
4164
4165 p7 = PKCS7_sign(arg_certificate, arg_private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
4166 if (!p7)
4167 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
4168 ERR_error_string(ERR_get_error(), NULL));
4169
4170 sigsz = i2d_PKCS7(p7, &sig);
4171 if (sigsz < 0)
4172 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s",
4173 ERR_error_string(ERR_get_error(), NULL));
4174
4175 *ret_signature = IOVEC_MAKE(TAKE_PTR(sig), sigsz);
4176
4177 return 0;
4178 #else
4179 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot setup verity signature: %m");
4180 #endif
4181 }
4182
4183 static int partition_format_verity_sig(Context *context, Partition *p) {
4184 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
4185 _cleanup_(iovec_done) struct iovec sig = {};
4186 _cleanup_free_ char *text = NULL, *hint = NULL;
4187 Partition *hp;
4188 uint8_t fp[X509_FINGERPRINT_SIZE];
4189 int whole_fd, r;
4190
4191 assert(p->verity == VERITY_SIG);
4192
4193 if (p->dropped)
4194 return 0;
4195
4196 if (PARTITION_EXISTS(p))
4197 return 0;
4198
4199 (void) partition_hint(p, context->node, &hint);
4200
4201 assert_se(hp = p->siblings[VERITY_HASH]);
4202 assert(!hp->dropped);
4203
4204 assert(arg_certificate);
4205
4206 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
4207
4208 r = sign_verity_roothash(&hp->roothash, &sig);
4209 if (r < 0)
4210 return r;
4211
4212 r = x509_fingerprint(arg_certificate, fp);
4213 if (r < 0)
4214 return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
4215
4216 r = json_build(&v,
4217 JSON_BUILD_OBJECT(
4218 JSON_BUILD_PAIR("rootHash", JSON_BUILD_HEX(hp->roothash.iov_base, hp->roothash.iov_len)),
4219 JSON_BUILD_PAIR(
4220 "certificateFingerprint",
4221 JSON_BUILD_HEX(fp, sizeof(fp))
4222 ),
4223 JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(&sig))
4224 )
4225 );
4226 if (r < 0)
4227 return log_error_errno(r, "Failed to build verity signature JSON object: %m");
4228
4229 r = json_variant_format(v, 0, &text);
4230 if (r < 0)
4231 return log_error_errno(r, "Failed to format verity signature JSON object: %m");
4232
4233 if (strlen(text)+1 > p->new_size)
4234 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Verity signature too long for partition: %m");
4235
4236 r = strgrowpad0(&text, p->new_size);
4237 if (r < 0)
4238 return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(p->new_size));
4239
4240 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
4241 return log_error_errno(errno, "Failed to seek to partition %s offset: %m", strna(hint));
4242
4243 r = loop_write(whole_fd, text, p->new_size);
4244 if (r < 0)
4245 return log_error_errno(r, "Failed to write verity signature to partition %s: %m", strna(hint));
4246
4247 if (fsync(whole_fd) < 0)
4248 return log_error_errno(errno, "Failed to synchronize partition %s: %m", strna(hint));
4249
4250 return 0;
4251 }
4252
4253 static int context_copy_blocks(Context *context) {
4254 int r;
4255
4256 assert(context);
4257
4258 /* Copy in file systems on the block level */
4259
4260 LIST_FOREACH(partitions, p, context->partitions) {
4261 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4262
4263 if (p->copy_blocks_fd < 0)
4264 continue;
4265
4266 if (p->dropped)
4267 continue;
4268
4269 if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */
4270 continue;
4271
4272 if (partition_type_defer(&p->type))
4273 continue;
4274
4275 assert(p->new_size != UINT64_MAX);
4276 assert(p->copy_blocks_size != UINT64_MAX);
4277 assert(p->new_size >= p->copy_blocks_size + (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
4278
4279 usec_t start_timestamp = now(CLOCK_MONOTONIC);
4280
4281 r = partition_target_prepare(context, p, p->new_size,
4282 /*need_path=*/ p->encrypt != ENCRYPT_OFF || p->siblings[VERITY_HASH],
4283 &t);
4284 if (r < 0)
4285 return r;
4286
4287 if (p->encrypt != ENCRYPT_OFF && t->loop) {
4288 r = partition_encrypt(context, p, t, /* offline = */ false);
4289 if (r < 0)
4290 return r;
4291 }
4292
4293 if (p->copy_blocks_offset == UINT64_MAX)
4294 log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64 ".",
4295 p->copy_blocks_path, FORMAT_BYTES(p->copy_blocks_size), p->partno);
4296 else {
4297 log_info("Copying in '%s' @ %" PRIu64 " (%s) on block level into future partition %" PRIu64 ".",
4298 p->copy_blocks_path, p->copy_blocks_offset, FORMAT_BYTES(p->copy_blocks_size), p->partno);
4299
4300 if (lseek(p->copy_blocks_fd, p->copy_blocks_offset, SEEK_SET) < 0)
4301 return log_error_errno(errno, "Failed to seek to copy blocks offset in %s: %m", p->copy_blocks_path);
4302 }
4303
4304 r = copy_bytes(p->copy_blocks_fd, partition_target_fd(t), p->copy_blocks_size, COPY_REFLINK);
4305 if (r < 0)
4306 return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
4307
4308 log_info("Copying in of '%s' on block level completed.", p->copy_blocks_path);
4309
4310 if (p->encrypt != ENCRYPT_OFF && !t->loop) {
4311 r = partition_encrypt(context, p, t, /* offline = */ true);
4312 if (r < 0)
4313 return r;
4314 }
4315
4316 r = partition_target_sync(context, p, t);
4317 if (r < 0)
4318 return r;
4319
4320 usec_t time_spent = usec_sub_unsigned(now(CLOCK_MONOTONIC), start_timestamp);
4321 if (time_spent > 250 * USEC_PER_MSEC) /* Show throughput, but not if we spent too little time on it, since it's just noise then */
4322 log_info("Block level copying and synchronization of partition %" PRIu64 " complete in %s (%s/s).",
4323 p->partno, FORMAT_TIMESPAN(time_spent, 0), FORMAT_BYTES((uint64_t) ((double) p->copy_blocks_size / time_spent * USEC_PER_SEC)));
4324 else
4325 log_info("Block level copying and synchronization of partition %" PRIu64 " complete in %s.",
4326 p->partno, FORMAT_TIMESPAN(time_spent, 0));
4327
4328 if (p->siblings[VERITY_HASH] && !partition_type_defer(&p->siblings[VERITY_HASH]->type)) {
4329 r = partition_format_verity_hash(context, p->siblings[VERITY_HASH],
4330 /* node = */ NULL, partition_target_path(t));
4331 if (r < 0)
4332 return r;
4333 }
4334
4335 if (p->siblings[VERITY_SIG] && !partition_type_defer(&p->siblings[VERITY_SIG]->type)) {
4336 r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
4337 if (r < 0)
4338 return r;
4339 }
4340 }
4341
4342 return 0;
4343 }
4344
4345 static int add_exclude_path(const char *path, Hashmap **denylist, DenyType type) {
4346 _cleanup_free_ struct stat *st = NULL;
4347 int r;
4348
4349 assert(path);
4350 assert(denylist);
4351
4352 st = new(struct stat, 1);
4353 if (!st)
4354 return log_oom();
4355
4356 r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
4357 if (r == -ENOENT)
4358 return 0;
4359 if (r < 0)
4360 return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
4361
4362 r = hashmap_ensure_put(denylist, &inode_hash_ops, st, INT_TO_PTR(type));
4363 if (r == -EEXIST)
4364 return 0;
4365 if (r < 0)
4366 return log_oom();
4367 if (r > 0)
4368 TAKE_PTR(st);
4369
4370 return 0;
4371 }
4372
4373 static int make_copy_files_denylist(
4374 Context *context,
4375 const Partition *p,
4376 const char *source,
4377 const char *target,
4378 Hashmap **ret) {
4379
4380 _cleanup_hashmap_free_ Hashmap *denylist = NULL;
4381 int r;
4382
4383 assert(context);
4384 assert(p);
4385 assert(source);
4386 assert(target);
4387 assert(ret);
4388
4389 /* Always exclude the top level APIVFS and temporary directories since the contents of these
4390 * directories are almost certainly not intended to end up in an image. */
4391
4392 NULSTR_FOREACH(s, APIVFS_TMP_DIRS_NULSTR) {
4393 r = add_exclude_path(s, &denylist, DENY_CONTENTS);
4394 if (r < 0)
4395 return r;
4396 }
4397
4398 /* Add the user configured excludes. */
4399
4400 STRV_FOREACH(e, p->exclude_files_source) {
4401 r = add_exclude_path(*e, &denylist, endswith(*e, "/") ? DENY_CONTENTS : DENY_INODE);
4402 if (r < 0)
4403 return r;
4404 }
4405
4406 STRV_FOREACH(e, p->exclude_files_target) {
4407 _cleanup_free_ char *path = NULL;
4408
4409 const char *s = path_startswith(*e, target);
4410 if (!s)
4411 continue;
4412
4413 path = path_join(source, s);
4414 if (!path)
4415 return log_oom();
4416
4417 r = add_exclude_path(path, &denylist, endswith(*e, "/") ? DENY_CONTENTS : DENY_INODE);
4418 if (r < 0)
4419 return r;
4420 }
4421
4422 /* If we're populating a root partition, we don't want any files to end up under the APIVFS mount
4423 * points. While we already exclude <source>/proc, users could still do something such as
4424 * "CopyFiles=/abc:/". Now, if /abc has a proc subdirectory with files in it, those will end up in
4425 * the top level proc directory in the root partition, which we want to avoid. To deal with these
4426 * cases, whenever we're populating a root partition and the target of CopyFiles= is the root
4427 * directory of the root partition, we exclude all directories under the source that are named after
4428 * APIVFS directories or named after mount points of other partitions that are also going to be part
4429 * of the image. */
4430
4431 if (p->type.designator == PARTITION_ROOT && empty_or_root(target)) {
4432 LIST_FOREACH(partitions, q, context->partitions) {
4433 if (q->type.designator == PARTITION_ROOT)
4434 continue;
4435
4436 const char *sources = gpt_partition_type_mountpoint_nulstr(q->type);
4437 if (!sources)
4438 continue;
4439
4440 NULSTR_FOREACH(s, sources) {
4441 _cleanup_free_ char *path = NULL;
4442
4443 /* Exclude only the children of partition mount points so that the nested
4444 * partition mount point itself still ends up in the upper partition. */
4445
4446 path = path_join(source, s);
4447 if (!path)
4448 return -ENOMEM;
4449
4450 r = add_exclude_path(path, &denylist, DENY_CONTENTS);
4451 if (r < 0)
4452 return r;
4453 }
4454 }
4455
4456 NULSTR_FOREACH(s, APIVFS_TMP_DIRS_NULSTR) {
4457 _cleanup_free_ char *path = NULL;
4458
4459 path = path_join(source, s);
4460 if (!path)
4461 return -ENOMEM;
4462
4463 r = add_exclude_path(path, &denylist, DENY_CONTENTS);
4464 if (r < 0)
4465 return r;
4466 }
4467 }
4468
4469 *ret = TAKE_PTR(denylist);
4470 return 0;
4471 }
4472
4473 static int add_subvolume_path(const char *path, Set **subvolumes) {
4474 _cleanup_free_ struct stat *st = NULL;
4475 int r;
4476
4477 assert(path);
4478 assert(subvolumes);
4479
4480 st = new(struct stat, 1);
4481 if (!st)
4482 return log_oom();
4483
4484 r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
4485 if (r == -ENOENT)
4486 return 0;
4487 if (r < 0)
4488 return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
4489
4490 r = set_ensure_consume(subvolumes, &inode_hash_ops, TAKE_PTR(st));
4491 if (r < 0)
4492 return log_oom();
4493
4494 return 0;
4495 }
4496
4497 static int make_subvolumes_set(
4498 Context *context,
4499 const Partition *p,
4500 const char *source,
4501 const char *target,
4502 Set **ret) {
4503 _cleanup_set_free_ Set *subvolumes = NULL;
4504 int r;
4505
4506 assert(context);
4507 assert(p);
4508 assert(target);
4509 assert(ret);
4510
4511 STRV_FOREACH(subvolume, p->subvolumes) {
4512 _cleanup_free_ char *path = NULL;
4513
4514 const char *s = path_startswith(*subvolume, target);
4515 if (!s)
4516 continue;
4517
4518 path = path_join(source, s);
4519 if (!path)
4520 return log_oom();
4521
4522 r = add_subvolume_path(path, &subvolumes);
4523 if (r < 0)
4524 return r;
4525 }
4526
4527 *ret = TAKE_PTR(subvolumes);
4528 return 0;
4529 }
4530
4531 static int do_copy_files(Context *context, Partition *p, const char *root) {
4532 int r;
4533
4534 assert(p);
4535 assert(root);
4536
4537 /* copy_tree_at() automatically copies the permissions of source directories to target directories if
4538 * it created them. However, the root directory is created by us, so we have to manually take care
4539 * that it is initialized. We use the first source directory targeting "/" as the metadata source for
4540 * the root directory. */
4541 STRV_FOREACH_PAIR(source, target, p->copy_files) {
4542 _cleanup_close_ int rfd = -EBADF, sfd = -EBADF;
4543
4544 if (!path_equal(*target, "/"))
4545 continue;
4546
4547 rfd = open(root, O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
4548 if (rfd < 0)
4549 return -errno;
4550
4551 sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_PATH|O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
4552 if (sfd < 0)
4553 return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
4554
4555 (void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS);
4556 (void) copy_access(sfd, rfd);
4557 (void) copy_times(sfd, rfd, 0);
4558
4559 break;
4560 }
4561
4562 STRV_FOREACH_PAIR(source, target, p->copy_files) {
4563 _cleanup_hashmap_free_ Hashmap *denylist = NULL;
4564 _cleanup_set_free_ Set *subvolumes_by_source_inode = NULL;
4565 _cleanup_close_ int sfd = -EBADF, pfd = -EBADF, tfd = -EBADF;
4566
4567 r = make_copy_files_denylist(context, p, *source, *target, &denylist);
4568 if (r < 0)
4569 return r;
4570
4571 r = make_subvolumes_set(context, p, *source, *target, &subvolumes_by_source_inode);
4572 if (r < 0)
4573 return r;
4574
4575 sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_CLOEXEC|O_NOCTTY, NULL);
4576 if (sfd == -ENOENT) {
4577 log_notice_errno(sfd, "Failed to open source file '%s%s', skipping: %m", strempty(arg_copy_source), *source);
4578 continue;
4579 }
4580 if (sfd < 0)
4581 return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
4582
4583 r = fd_verify_regular(sfd);
4584 if (r < 0) {
4585 if (r != -EISDIR)
4586 return log_error_errno(r, "Failed to check type of source file '%s': %m", *source);
4587
4588 /* We are looking at a directory */
4589 tfd = chase_and_open(*target, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4590 if (tfd < 0) {
4591 _cleanup_free_ char *dn = NULL, *fn = NULL;
4592
4593 if (tfd != -ENOENT)
4594 return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
4595
4596 r = path_extract_filename(*target, &fn);
4597 if (r < 0)
4598 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
4599
4600 r = path_extract_directory(*target, &dn);
4601 if (r < 0)
4602 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
4603
4604 r = mkdir_p_root(root, dn, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4605 if (r < 0)
4606 return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
4607
4608 pfd = chase_and_open(dn, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4609 if (pfd < 0)
4610 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
4611
4612 r = copy_tree_at(
4613 sfd, ".",
4614 pfd, fn,
4615 UID_INVALID, GID_INVALID,
4616 COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
4617 denylist, subvolumes_by_source_inode);
4618 } else
4619 r = copy_tree_at(
4620 sfd, ".",
4621 tfd, ".",
4622 UID_INVALID, GID_INVALID,
4623 COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
4624 denylist, subvolumes_by_source_inode);
4625 if (r < 0)
4626 return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m",
4627 strempty(arg_copy_source), *source, strempty(root), *target);
4628 } else {
4629 _cleanup_free_ char *dn = NULL, *fn = NULL;
4630
4631 /* We are looking at a regular file */
4632
4633 r = path_extract_filename(*target, &fn);
4634 if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
4635 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
4636 "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
4637 if (r < 0)
4638 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
4639
4640 r = path_extract_directory(*target, &dn);
4641 if (r < 0)
4642 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
4643
4644 r = mkdir_p_root(root, dn, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4645 if (r < 0)
4646 return log_error_errno(r, "Failed to create parent directory: %m");
4647
4648 pfd = chase_and_open(dn, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4649 if (pfd < 0)
4650 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
4651
4652 tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
4653 if (tfd < 0)
4654 return log_error_errno(errno, "Failed to create target file '%s': %m", *target);
4655
4656 r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_SIGINT|COPY_TRUNCATE);
4657 if (r < 0)
4658 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_copy_source), *target);
4659
4660 (void) copy_xattr(sfd, NULL, tfd, NULL, COPY_ALL_XATTRS);
4661 (void) copy_access(sfd, tfd);
4662 (void) copy_times(sfd, tfd, 0);
4663 }
4664 }
4665
4666 return 0;
4667 }
4668
4669 static int do_make_directories(Partition *p, const char *root) {
4670 int r;
4671
4672 assert(p);
4673 assert(root);
4674
4675 STRV_FOREACH(d, p->make_directories) {
4676 r = mkdir_p_root(root, *d, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4677 if (r < 0)
4678 return log_error_errno(r, "Failed to create directory '%s' in file system: %m", *d);
4679 }
4680
4681 return 0;
4682 }
4683
4684 static bool partition_needs_populate(Partition *p) {
4685 assert(p);
4686 return !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories);
4687 }
4688
4689 static int partition_populate_directory(Context *context, Partition *p, char **ret) {
4690 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
4691 const char *vt;
4692 int r;
4693
4694 assert(ret);
4695
4696 log_info("Populating %s filesystem.", p->format);
4697
4698 r = var_tmp_dir(&vt);
4699 if (r < 0)
4700 return log_error_errno(r, "Could not determine temporary directory: %m");
4701
4702 r = tempfn_random_child(vt, "repart", &root);
4703 if (r < 0)
4704 return log_error_errno(r, "Failed to generate temporary directory: %m");
4705
4706 r = mkdir(root, 0755);
4707 if (r < 0)
4708 return log_error_errno(errno, "Failed to create temporary directory: %m");
4709
4710 r = do_copy_files(context, p, root);
4711 if (r < 0)
4712 return r;
4713
4714 r = do_make_directories(p, root);
4715 if (r < 0)
4716 return r;
4717
4718 log_info("Successfully populated %s filesystem.", p->format);
4719
4720 *ret = TAKE_PTR(root);
4721 return 0;
4722 }
4723
4724 static int partition_populate_filesystem(Context *context, Partition *p, const char *node) {
4725 int r;
4726
4727 assert(p);
4728 assert(node);
4729
4730 log_info("Populating %s filesystem.", p->format);
4731
4732 /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to
4733 * appear in the host namespace. Hence we fork a child that has its own file system namespace and
4734 * detached mount propagation. */
4735
4736 r = safe_fork("(sd-copy)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
4737 if (r < 0)
4738 return r;
4739 if (r == 0) {
4740 static const char fs[] = "/run/systemd/mount-root";
4741 /* This is a child process with its own mount namespace and propagation to host turned off */
4742
4743 r = mkdir_p(fs, 0700);
4744 if (r < 0) {
4745 log_error_errno(r, "Failed to create mount point: %m");
4746 _exit(EXIT_FAILURE);
4747 }
4748
4749 if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0)
4750 _exit(EXIT_FAILURE);
4751
4752 if (do_copy_files(context, p, fs) < 0)
4753 _exit(EXIT_FAILURE);
4754
4755 if (do_make_directories(p, fs) < 0)
4756 _exit(EXIT_FAILURE);
4757
4758 r = syncfs_path(AT_FDCWD, fs);
4759 if (r < 0) {
4760 log_error_errno(r, "Failed to synchronize written files: %m");
4761 _exit(EXIT_FAILURE);
4762 }
4763
4764 _exit(EXIT_SUCCESS);
4765 }
4766
4767 log_info("Successfully populated %s filesystem.", p->format);
4768 return 0;
4769 }
4770
4771 static int context_mkfs(Context *context) {
4772 int r;
4773
4774 assert(context);
4775
4776 /* Make a file system */
4777
4778 LIST_FOREACH(partitions, p, context->partitions) {
4779 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
4780 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4781 _cleanup_strv_free_ char **extra_mkfs_options = NULL;
4782
4783 if (p->dropped)
4784 continue;
4785
4786 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
4787 continue;
4788
4789 if (!p->format)
4790 continue;
4791
4792 /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
4793 if (p->copy_blocks_fd >= 0)
4794 continue;
4795
4796 if (partition_type_defer(&p->type))
4797 continue;
4798
4799 assert(p->offset != UINT64_MAX);
4800 assert(p->new_size != UINT64_MAX);
4801 assert(p->new_size >= (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
4802
4803 /* If we're doing encryption, we make sure we keep free space at the end which is required
4804 * for cryptsetup's offline encryption. */
4805 r = partition_target_prepare(context, p,
4806 p->new_size - (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0),
4807 /*need_path=*/ true,
4808 &t);
4809 if (r < 0)
4810 return r;
4811
4812 if (p->encrypt != ENCRYPT_OFF && t->loop) {
4813 r = partition_target_grow(t, p->new_size);
4814 if (r < 0)
4815 return r;
4816
4817 r = partition_encrypt(context, p, t, /* offline = */ false);
4818 if (r < 0)
4819 return log_error_errno(r, "Failed to encrypt device: %m");
4820 }
4821
4822 log_info("Formatting future partition %" PRIu64 ".", p->partno);
4823
4824 /* If we're not writing to a loop device or if we're populating a read-only filesystem, we
4825 * have to populate using the filesystem's mkfs's --root (or equivalent) option. To do that,
4826 * we need to set up the final directory tree beforehand. */
4827
4828 if (partition_needs_populate(p) && (!t->loop || fstype_is_ro(p->format))) {
4829 if (!mkfs_supports_root_option(p->format))
4830 return log_error_errno(SYNTHETIC_ERRNO(ENODEV),
4831 "Loop device access is required to populate %s filesystems.",
4832 p->format);
4833
4834 r = partition_populate_directory(context, p, &root);
4835 if (r < 0)
4836 return r;
4837 }
4838
4839 r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options);
4840 if (r < 0)
4841 return log_error_errno(r,
4842 "Failed to determine mkfs command line options for '%s': %m",
4843 p->format);
4844
4845 r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root,
4846 p->fs_uuid, arg_discard, /* quiet = */ false,
4847 context->fs_sector_size, extra_mkfs_options);
4848 if (r < 0)
4849 return r;
4850
4851 /* The mkfs binary we invoked might have removed our temporary file when we're not operating
4852 * on a loop device, so let's make sure we open the file again to make sure our file
4853 * descriptor points to any potential new file. */
4854
4855 if (t->fd >= 0 && t->path && !t->loop) {
4856 safe_close(t->fd);
4857 t->fd = open(t->path, O_RDWR|O_CLOEXEC);
4858 if (t->fd < 0)
4859 return log_error_errno(errno, "Failed to reopen temporary file: %m");
4860 }
4861
4862 log_info("Successfully formatted future partition %" PRIu64 ".", p->partno);
4863
4864 /* If we're writing to a loop device, we can now mount the empty filesystem and populate it. */
4865 if (partition_needs_populate(p) && !root) {
4866 assert(t->loop);
4867
4868 r = partition_populate_filesystem(context, p, partition_target_path(t));
4869 if (r < 0)
4870 return r;
4871 }
4872
4873 if (p->encrypt != ENCRYPT_OFF && !t->loop) {
4874 r = partition_target_grow(t, p->new_size);
4875 if (r < 0)
4876 return r;
4877
4878 r = partition_encrypt(context, p, t, /* offline = */ true);
4879 if (r < 0)
4880 return log_error_errno(r, "Failed to encrypt device: %m");
4881 }
4882
4883 /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and
4884 * if we don't sync before detaching a block device the in-flight sectors possibly won't hit
4885 * the disk. */
4886
4887 r = partition_target_sync(context, p, t);
4888 if (r < 0)
4889 return r;
4890
4891 if (p->siblings[VERITY_HASH] && !partition_type_defer(&p->siblings[VERITY_HASH]->type)) {
4892 r = partition_format_verity_hash(context, p->siblings[VERITY_HASH],
4893 /* node = */ NULL, partition_target_path(t));
4894 if (r < 0)
4895 return r;
4896 }
4897
4898 if (p->siblings[VERITY_SIG] && !partition_type_defer(&p->siblings[VERITY_SIG]->type)) {
4899 r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
4900 if (r < 0)
4901 return r;
4902 }
4903 }
4904
4905 return 0;
4906 }
4907
4908 static int parse_x509_certificate(const char *certificate, size_t certificate_size, X509 **ret) {
4909 #if HAVE_OPENSSL
4910 _cleanup_(X509_freep) X509 *cert = NULL;
4911 _cleanup_(BIO_freep) BIO *cb = NULL;
4912
4913 assert(certificate);
4914 assert(certificate_size > 0);
4915 assert(ret);
4916
4917 cb = BIO_new_mem_buf(certificate, certificate_size);
4918 if (!cb)
4919 return log_oom();
4920
4921 cert = PEM_read_bio_X509(cb, NULL, NULL, NULL);
4922 if (!cert)
4923 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s",
4924 ERR_error_string(ERR_get_error(), NULL));
4925
4926 if (ret)
4927 *ret = TAKE_PTR(cert);
4928
4929 return 0;
4930 #else
4931 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot parse X509 certificate.");
4932 #endif
4933 }
4934
4935 static int parse_private_key(const char *key, size_t key_size, EVP_PKEY **ret) {
4936 #if HAVE_OPENSSL
4937 _cleanup_(BIO_freep) BIO *kb = NULL;
4938 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
4939
4940 assert(key);
4941 assert(key_size > 0);
4942 assert(ret);
4943
4944 kb = BIO_new_mem_buf(key, key_size);
4945 if (!kb)
4946 return log_oom();
4947
4948 pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL);
4949 if (!pk)
4950 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s",
4951 ERR_error_string(ERR_get_error(), NULL));
4952
4953 if (ret)
4954 *ret = TAKE_PTR(pk);
4955
4956 return 0;
4957 #else
4958 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot parse private key.");
4959 #endif
4960 }
4961
4962 static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
4963 struct {
4964 sd_id128_t type_uuid;
4965 uint64_t counter;
4966 } _packed_ plaintext = {};
4967 union {
4968 uint8_t md[SHA256_DIGEST_SIZE];
4969 sd_id128_t id;
4970 } result;
4971
4972 uint64_t k = 0;
4973 int r;
4974
4975 assert(context);
4976 assert(p);
4977 assert(ret);
4978
4979 /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
4980 * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
4981 * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
4982 * installation we are processing, but if random behaviour is desired can be random, too. We use the
4983 * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
4984 * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
4985 * second and later partition of the same type) if we have more than one partition of the same
4986 * time. Or in other words:
4987 *
4988 * With:
4989 * SEED := /etc/machine-id
4990 *
4991 * If first partition instance of type TYPE_UUID:
4992 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
4993 *
4994 * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
4995 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
4996 */
4997
4998 LIST_FOREACH(partitions, q, context->partitions) {
4999 if (p == q)
5000 break;
5001
5002 if (!sd_id128_equal(p->type.uuid, q->type.uuid))
5003 continue;
5004
5005 k++;
5006 }
5007
5008 plaintext.type_uuid = p->type.uuid;
5009 plaintext.counter = htole64(k);
5010
5011 hmac_sha256(context->seed.bytes, sizeof(context->seed.bytes),
5012 &plaintext,
5013 k == 0 ? sizeof(sd_id128_t) : sizeof(plaintext),
5014 result.md);
5015
5016 /* Take the first half, mark it as v4 UUID */
5017 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
5018 result.id = id128_make_v4_uuid(result.id);
5019
5020 /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
5021 LIST_FOREACH(partitions, q, context->partitions) {
5022 if (p == q)
5023 continue;
5024
5025 if (sd_id128_in_set(result.id, q->current_uuid, q->new_uuid)) {
5026 log_warning("Partition UUID calculated from seed for partition %" PRIu64 " already used, reverting to randomized UUID.", p->partno);
5027
5028 r = sd_id128_randomize(&result.id);
5029 if (r < 0)
5030 return log_error_errno(r, "Failed to generate randomized UUID: %m");
5031
5032 break;
5033 }
5034 }
5035
5036 *ret = result.id;
5037 return 0;
5038 }
5039
5040 static int partition_acquire_label(Context *context, Partition *p, char **ret) {
5041 _cleanup_free_ char *label = NULL;
5042 const char *prefix;
5043 unsigned k = 1;
5044
5045 assert(context);
5046 assert(p);
5047 assert(ret);
5048
5049 prefix = gpt_partition_type_uuid_to_string(p->type.uuid);
5050 if (!prefix)
5051 prefix = "linux";
5052
5053 for (;;) {
5054 const char *ll = label ?: prefix;
5055 bool retry = false;
5056
5057 LIST_FOREACH(partitions, q, context->partitions) {
5058 if (p == q)
5059 break;
5060
5061 if (streq_ptr(ll, q->current_label) ||
5062 streq_ptr(ll, q->new_label)) {
5063 retry = true;
5064 break;
5065 }
5066 }
5067
5068 if (!retry)
5069 break;
5070
5071 label = mfree(label);
5072 if (asprintf(&label, "%s-%u", prefix, ++k) < 0)
5073 return log_oom();
5074 }
5075
5076 if (!label) {
5077 label = strdup(prefix);
5078 if (!label)
5079 return log_oom();
5080 }
5081
5082 *ret = TAKE_PTR(label);
5083 return 0;
5084 }
5085
5086 static int context_acquire_partition_uuids_and_labels(Context *context) {
5087 int r;
5088
5089 assert(context);
5090
5091 LIST_FOREACH(partitions, p, context->partitions) {
5092 sd_id128_t uuid;
5093
5094 /* Never touch foreign partitions */
5095 if (PARTITION_IS_FOREIGN(p)) {
5096 p->new_uuid = p->current_uuid;
5097
5098 if (p->current_label) {
5099 r = free_and_strdup_warn(&p->new_label, strempty(p->current_label));
5100 if (r < 0)
5101 return r;
5102 }
5103
5104 continue;
5105 }
5106
5107 if (!sd_id128_is_null(p->current_uuid))
5108 p->new_uuid = uuid = p->current_uuid; /* Never change initialized UUIDs */
5109 else if (p->new_uuid_is_set)
5110 uuid = p->new_uuid;
5111 else {
5112 /* Not explicitly set by user! */
5113 r = partition_acquire_uuid(context, p, &uuid);
5114 if (r < 0)
5115 return r;
5116
5117 /* The final verity hash/data UUIDs can only be determined after formatting the
5118 * verity hash partition. However, we still want to use the generated partition UUID
5119 * to derive other UUIDs to keep things unique and reproducible, so we always
5120 * generate a UUID if none is set, but we only use it as the actual partition UUID if
5121 * verity is not configured. */
5122 if (!IN_SET(p->verity, VERITY_DATA, VERITY_HASH)) {
5123 p->new_uuid = uuid;
5124 p->new_uuid_is_set = true;
5125 }
5126 }
5127
5128 /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid",
5129 * keyed off the partition UUID. */
5130 r = derive_uuid(uuid, "file-system-uuid", &p->fs_uuid);
5131 if (r < 0)
5132 return r;
5133
5134 if (p->encrypt != ENCRYPT_OFF) {
5135 r = derive_uuid(uuid, "luks-uuid", &p->luks_uuid);
5136 if (r < 0)
5137 return r;
5138 }
5139
5140 /* Derive the verity salt and verity superblock UUID from the seed to keep them reproducible */
5141 if (p->verity == VERITY_HASH) {
5142 derive_salt(context->seed, "verity-salt", p->verity_salt);
5143
5144 r = derive_uuid(context->seed, "verity-uuid", &p->verity_uuid);
5145 if (r < 0)
5146 return log_error_errno(r, "Failed to acquire verity uuid: %m");
5147 }
5148
5149 if (!isempty(p->current_label)) {
5150 /* never change initialized labels */
5151 r = free_and_strdup_warn(&p->new_label, p->current_label);
5152 if (r < 0)
5153 return r;
5154 } else if (!p->new_label) {
5155 /* Not explicitly set by user! */
5156
5157 r = partition_acquire_label(context, p, &p->new_label);
5158 if (r < 0)
5159 return r;
5160 }
5161 }
5162
5163 return 0;
5164 }
5165
5166 static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
5167 _cleanup_free_ char *a = NULL;
5168
5169 for (unsigned i = 0; i < sizeof(flags) * 8; i++) {
5170 uint64_t bit = UINT64_C(1) << i;
5171 char buf[DECIMAL_STR_MAX(unsigned)+1];
5172
5173 if (!FLAGS_SET(flags, bit))
5174 continue;
5175
5176 xsprintf(buf, "%u", i);
5177 if (!strextend_with_separator(&a, ",", buf))
5178 return -ENOMEM;
5179 }
5180
5181 return fdisk_partition_set_attrs(q, a);
5182 }
5183
5184 static uint64_t partition_merge_flags(Partition *p) {
5185 uint64_t f;
5186
5187 assert(p);
5188
5189 f = p->gpt_flags;
5190
5191 if (p->no_auto >= 0) {
5192 if (gpt_partition_type_knows_no_auto(p->type))
5193 SET_FLAG(f, SD_GPT_FLAG_NO_AUTO, p->no_auto);
5194 else {
5195 char buffer[SD_ID128_UUID_STRING_MAX];
5196 log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
5197 yes_no(p->no_auto),
5198 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5199 }
5200 }
5201
5202 if (p->read_only >= 0) {
5203 if (gpt_partition_type_knows_read_only(p->type))
5204 SET_FLAG(f, SD_GPT_FLAG_READ_ONLY, p->read_only);
5205 else {
5206 char buffer[SD_ID128_UUID_STRING_MAX];
5207 log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
5208 yes_no(p->read_only),
5209 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5210 }
5211 }
5212
5213 if (p->growfs >= 0) {
5214 if (gpt_partition_type_knows_growfs(p->type))
5215 SET_FLAG(f, SD_GPT_FLAG_GROWFS, p->growfs);
5216 else {
5217 char buffer[SD_ID128_UUID_STRING_MAX];
5218 log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
5219 yes_no(p->growfs),
5220 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5221 }
5222 }
5223
5224 return f;
5225 }
5226
5227 static int context_mangle_partitions(Context *context) {
5228 int r;
5229
5230 assert(context);
5231
5232 LIST_FOREACH(partitions, p, context->partitions) {
5233 if (p->dropped)
5234 continue;
5235
5236 if (partition_type_defer(&p->type))
5237 continue;
5238
5239 assert(p->new_size != UINT64_MAX);
5240 assert(p->offset != UINT64_MAX);
5241 assert(p->partno != UINT64_MAX);
5242
5243 if (PARTITION_EXISTS(p)) {
5244 bool changed = false;
5245
5246 assert(p->current_partition);
5247
5248 if (p->new_size != p->current_size) {
5249 assert(p->new_size >= p->current_size);
5250 assert(p->new_size % context->sector_size == 0);
5251
5252 r = fdisk_partition_size_explicit(p->current_partition, true);
5253 if (r < 0)
5254 return log_error_errno(r, "Failed to enable explicit sizing: %m");
5255
5256 r = fdisk_partition_set_size(p->current_partition, p->new_size / context->sector_size);
5257 if (r < 0)
5258 return log_error_errno(r, "Failed to grow partition: %m");
5259
5260 log_info("Growing existing partition %" PRIu64 ".", p->partno);
5261 changed = true;
5262 }
5263
5264 if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
5265 r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
5266 if (r < 0)
5267 return log_error_errno(r, "Failed to set partition UUID: %m");
5268
5269 log_info("Initializing UUID of existing partition %" PRIu64 ".", p->partno);
5270 changed = true;
5271 }
5272
5273 if (!streq_ptr(p->new_label, p->current_label)) {
5274 r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
5275 if (r < 0)
5276 return log_error_errno(r, "Failed to set partition label: %m");
5277
5278 log_info("Setting partition label of existing partition %" PRIu64 ".", p->partno);
5279 changed = true;
5280 }
5281
5282 if (changed) {
5283 assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
5284
5285 r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
5286 if (r < 0)
5287 return log_error_errno(r, "Failed to update partition: %m");
5288 }
5289 } else {
5290 _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
5291 _cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
5292
5293 assert(!p->new_partition);
5294 assert(p->offset % context->sector_size == 0);
5295 assert(p->new_size % context->sector_size == 0);
5296 assert(p->new_label);
5297
5298 t = fdisk_new_parttype();
5299 if (!t)
5300 return log_oom();
5301
5302 r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid));
5303 if (r < 0)
5304 return log_error_errno(r, "Failed to initialize partition type: %m");
5305
5306 q = fdisk_new_partition();
5307 if (!q)
5308 return log_oom();
5309
5310 r = fdisk_partition_set_type(q, t);
5311 if (r < 0)
5312 return log_error_errno(r, "Failed to set partition type: %m");
5313
5314 r = fdisk_partition_size_explicit(q, true);
5315 if (r < 0)
5316 return log_error_errno(r, "Failed to enable explicit sizing: %m");
5317
5318 r = fdisk_partition_set_start(q, p->offset / context->sector_size);
5319 if (r < 0)
5320 return log_error_errno(r, "Failed to position partition: %m");
5321
5322 r = fdisk_partition_set_size(q, p->new_size / context->sector_size);
5323 if (r < 0)
5324 return log_error_errno(r, "Failed to grow partition: %m");
5325
5326 r = fdisk_partition_set_partno(q, p->partno);
5327 if (r < 0)
5328 return log_error_errno(r, "Failed to set partition number: %m");
5329
5330 r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
5331 if (r < 0)
5332 return log_error_errno(r, "Failed to set partition UUID: %m");
5333
5334 r = fdisk_partition_set_name(q, strempty(p->new_label));
5335 if (r < 0)
5336 return log_error_errno(r, "Failed to set partition label: %m");
5337
5338 /* Merge the no auto + read only + growfs setting with the literal flags, and set them for the partition */
5339 r = set_gpt_flags(q, partition_merge_flags(p));
5340 if (r < 0)
5341 return log_error_errno(r, "Failed to set GPT partition flags: %m");
5342
5343 log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
5344
5345 r = fdisk_add_partition(context->fdisk_context, q, NULL);
5346 if (r < 0)
5347 return log_error_errno(r, "Failed to add partition: %m");
5348
5349 assert(!p->new_partition);
5350 p->new_partition = TAKE_PTR(q);
5351 }
5352 }
5353
5354 return 0;
5355 }
5356
5357 static int split_name_printf(Partition *p, char **ret) {
5358 assert(p);
5359
5360 const Specifier table[] = {
5361 { 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type.uuid) },
5362 { 'T', specifier_id128, &p->type.uuid },
5363 { 'U', specifier_id128, &p->new_uuid },
5364 { 'n', specifier_uint64, &p->partno },
5365
5366 COMMON_SYSTEM_SPECIFIERS,
5367 {}
5368 };
5369
5370 return specifier_printf(p->split_name_format, NAME_MAX, table, arg_root, p, ret);
5371 }
5372
5373 static int split_node(const char *node, char **ret_base, char **ret_ext) {
5374 _cleanup_free_ char *base = NULL, *ext = NULL;
5375 char *e;
5376 int r;
5377
5378 assert(node);
5379 assert(ret_base);
5380 assert(ret_ext);
5381
5382 r = path_extract_filename(node, &base);
5383 if (r == O_DIRECTORY || r == -EADDRNOTAVAIL)
5384 return log_error_errno(r, "Device node %s cannot be a directory", node);
5385 if (r < 0)
5386 return log_error_errno(r, "Failed to extract filename from %s: %m", node);
5387
5388 e = endswith(base, ".raw");
5389 if (e) {
5390 ext = strdup(e);
5391 if (!ext)
5392 return log_oom();
5393
5394 *e = 0;
5395 }
5396
5397 *ret_base = TAKE_PTR(base);
5398 *ret_ext = TAKE_PTR(ext);
5399
5400 return 0;
5401 }
5402
5403 static int split_name_resolve(Context *context) {
5404 _cleanup_free_ char *parent = NULL, *base = NULL, *ext = NULL;
5405 int r;
5406
5407 assert(context);
5408
5409 r = path_extract_directory(context->node, &parent);
5410 if (r < 0 && r != -EDESTADDRREQ)
5411 return log_error_errno(r, "Failed to extract directory from %s: %m", context->node);
5412
5413 r = split_node(context->node, &base, &ext);
5414 if (r < 0)
5415 return r;
5416
5417 LIST_FOREACH(partitions, p, context->partitions) {
5418 _cleanup_free_ char *resolved = NULL;
5419
5420 if (p->dropped)
5421 continue;
5422
5423 if (!p->split_name_format)
5424 continue;
5425
5426 r = split_name_printf(p, &resolved);
5427 if (r < 0)
5428 return log_error_errno(r, "Failed to resolve specifiers in %s: %m", p->split_name_format);
5429
5430 if (parent)
5431 p->split_path = strjoin(parent, "/", base, ".", resolved, ext);
5432 else
5433 p->split_path = strjoin(base, ".", resolved, ext);
5434 if (!p->split_path)
5435 return log_oom();
5436 }
5437
5438 LIST_FOREACH(partitions, p, context->partitions) {
5439 if (!p->split_path)
5440 continue;
5441
5442 LIST_FOREACH(partitions, q, context->partitions) {
5443 if (p == q)
5444 continue;
5445
5446 if (!q->split_path)
5447 continue;
5448
5449 if (!streq(p->split_path, q->split_path))
5450 continue;
5451
5452 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
5453 "%s and %s have the same resolved split name \"%s\", refusing",
5454 p->definition_path, q->definition_path, p->split_path);
5455 }
5456 }
5457
5458 return 0;
5459 }
5460
5461 static int context_split(Context *context) {
5462 int fd = -EBADF, r;
5463
5464 if (!arg_split)
5465 return 0;
5466
5467 assert(context);
5468
5469 /* We can't do resolution earlier because the partition UUIDs for verity partitions are only filled
5470 * in after they've been generated. */
5471
5472 r = split_name_resolve(context);
5473 if (r < 0)
5474 return r;
5475
5476 LIST_FOREACH(partitions, p, context->partitions) {
5477 _cleanup_close_ int fdt = -EBADF;
5478
5479 if (p->dropped)
5480 continue;
5481
5482 if (!p->split_path)
5483 continue;
5484
5485 if (partition_type_defer(&p->type))
5486 continue;
5487
5488 fdt = open(p->split_path, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL, 0666);
5489 if (fdt < 0)
5490 return log_error_errno(fdt, "Failed to open split partition file %s: %m", p->split_path);
5491
5492 if (fd < 0)
5493 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
5494
5495 if (lseek(fd, p->offset, SEEK_SET) < 0)
5496 return log_error_errno(errno, "Failed to seek to partition offset: %m");
5497
5498 r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
5499 if (r < 0)
5500 return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
5501 }
5502
5503 return 0;
5504 }
5505
5506 static int context_write_partition_table(Context *context) {
5507 _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
5508 int capable, r;
5509
5510 assert(context);
5511
5512 if (!context->from_scratch && !context_changed(context)) {
5513 log_info("No changes.");
5514 return 0;
5515 }
5516
5517 if (arg_dry_run) {
5518 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
5519 return 0;
5520 }
5521
5522 log_info("Applying changes to %s.", context->node);
5523
5524 if (context->from_scratch && arg_empty != EMPTY_CREATE) {
5525 /* Erase everything if we operate from scratch, except if the image was just created anyway, and thus is definitely empty. */
5526 r = context_wipe_range(context, 0, context->total);
5527 if (r < 0)
5528 return r;
5529
5530 log_info("Wiped block device.");
5531
5532 if (arg_discard) {
5533 r = context_discard_range(context, 0, context->total);
5534 if (r == -EOPNOTSUPP)
5535 log_info("Storage does not support discard, not discarding entire block device data.");
5536 else if (r < 0)
5537 return log_error_errno(r, "Failed to discard entire block device: %m");
5538 else if (r > 0)
5539 log_info("Discarded entire block device.");
5540 }
5541 }
5542
5543 r = fdisk_get_partitions(context->fdisk_context, &original_table);
5544 if (r < 0)
5545 return log_error_errno(r, "Failed to acquire partition table: %m");
5546
5547 /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
5548 * gaps between partitions, just to be sure. */
5549 r = context_wipe_and_discard(context);
5550 if (r < 0)
5551 return r;
5552
5553 r = context_copy_blocks(context);
5554 if (r < 0)
5555 return r;
5556
5557 r = context_mkfs(context);
5558 if (r < 0)
5559 return r;
5560
5561 r = context_mangle_partitions(context);
5562 if (r < 0)
5563 return r;
5564
5565 log_info("Writing new partition table.");
5566
5567 r = fdisk_write_disklabel(context->fdisk_context);
5568 if (r < 0)
5569 return log_error_errno(r, "Failed to write partition table: %m");
5570
5571 capable = blockdev_partscan_enabled(fdisk_get_devfd(context->fdisk_context));
5572 if (capable == -ENOTBLK)
5573 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
5574 else if (capable < 0)
5575 return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
5576 else if (capable > 0) {
5577 log_info("Telling kernel to reread partition table.");
5578
5579 if (context->from_scratch)
5580 r = fdisk_reread_partition_table(context->fdisk_context);
5581 else
5582 r = fdisk_reread_changes(context->fdisk_context, original_table);
5583 if (r < 0)
5584 return log_error_errno(r, "Failed to reread partition table: %m");
5585 } else
5586 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
5587
5588 log_info("All done.");
5589
5590 return 0;
5591 }
5592
5593 static int context_read_seed(Context *context, const char *root) {
5594 int r;
5595
5596 assert(context);
5597
5598 if (!sd_id128_is_null(context->seed))
5599 return 0;
5600
5601 if (!arg_randomize) {
5602 r = id128_get_machine(root, &context->seed);
5603 if (r >= 0)
5604 return 0;
5605
5606 if (!ERRNO_IS_MACHINE_ID_UNSET(r))
5607 return log_error_errno(r, "Failed to parse machine ID of image: %m");
5608
5609 log_info("No machine ID set, using randomized partition UUIDs.");
5610 }
5611
5612 r = sd_id128_randomize(&context->seed);
5613 if (r < 0)
5614 return log_error_errno(r, "Failed to generate randomized seed: %m");
5615
5616 return 0;
5617 }
5618
5619 static int context_factory_reset(Context *context) {
5620 size_t n = 0;
5621 int r;
5622
5623 assert(context);
5624
5625 if (arg_factory_reset <= 0)
5626 return 0;
5627
5628 if (context->from_scratch) /* Nothing to reset if we start from scratch */
5629 return 0;
5630
5631 if (arg_dry_run) {
5632 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
5633 return 0;
5634 }
5635
5636 log_info("Applying factory reset.");
5637
5638 LIST_FOREACH(partitions, p, context->partitions) {
5639
5640 if (!p->factory_reset || !PARTITION_EXISTS(p))
5641 continue;
5642
5643 assert(p->partno != UINT64_MAX);
5644
5645 log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
5646
5647 r = fdisk_delete_partition(context->fdisk_context, p->partno);
5648 if (r < 0)
5649 return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
5650
5651 n++;
5652 }
5653
5654 if (n == 0) {
5655 log_info("Factory reset requested, but no partitions to delete found.");
5656 return 0;
5657 }
5658
5659 r = fdisk_write_disklabel(context->fdisk_context);
5660 if (r < 0)
5661 return log_error_errno(r, "Failed to write disk label: %m");
5662
5663 log_info("Successfully deleted %zu partitions.", n);
5664 return 1;
5665 }
5666
5667 static int context_can_factory_reset(Context *context) {
5668 assert(context);
5669
5670 LIST_FOREACH(partitions, p, context->partitions)
5671 if (p->factory_reset && PARTITION_EXISTS(p))
5672 return true;
5673
5674 return false;
5675 }
5676
5677 static int resolve_copy_blocks_auto_candidate(
5678 dev_t partition_devno,
5679 GptPartitionType partition_type,
5680 dev_t restrict_devno,
5681 sd_id128_t *ret_uuid) {
5682
5683 _cleanup_(blkid_free_probep) blkid_probe b = NULL;
5684 _cleanup_close_ int fd = -EBADF;
5685 _cleanup_free_ char *p = NULL;
5686 const char *pttype, *t;
5687 sd_id128_t pt_parsed, u;
5688 blkid_partition pp;
5689 dev_t whole_devno;
5690 blkid_partlist pl;
5691 int r;
5692
5693 /* Checks if the specified partition has the specified GPT type UUID, and is located on the specified
5694 * 'restrict_devno' device. The type check is particularly relevant if we have Verity volume which is
5695 * backed by two separate partitions: the data and the hash partitions, and we need to find the right
5696 * one of the two. */
5697
5698 r = block_get_whole_disk(partition_devno, &whole_devno);
5699 if (r < 0)
5700 return log_error_errno(
5701 r,
5702 "Unable to determine containing block device of partition %u:%u: %m",
5703 major(partition_devno), minor(partition_devno));
5704
5705 if (restrict_devno != (dev_t) -1 &&
5706 restrict_devno != whole_devno)
5707 return log_error_errno(
5708 SYNTHETIC_ERRNO(EPERM),
5709 "Partition %u:%u is located outside of block device %u:%u, refusing.",
5710 major(partition_devno), minor(partition_devno),
5711 major(restrict_devno), minor(restrict_devno));
5712
5713 fd = r = device_open_from_devnum(S_IFBLK, whole_devno, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &p);
5714 if (r < 0)
5715 return log_error_errno(r, "Failed to open block device " DEVNUM_FORMAT_STR ": %m",
5716 DEVNUM_FORMAT_VAL(whole_devno));
5717
5718 b = blkid_new_probe();
5719 if (!b)
5720 return log_oom();
5721
5722 errno = 0;
5723 r = blkid_probe_set_device(b, fd, 0, 0);
5724 if (r != 0)
5725 return log_error_errno(errno_or_else(ENOMEM), "Failed to open block device '%s': %m", p);
5726
5727 (void) blkid_probe_enable_partitions(b, 1);
5728 (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
5729
5730 errno = 0;
5731 r = blkid_do_safeprobe(b);
5732 if (r == _BLKID_SAFEPROBE_ERROR)
5733 return log_error_errno(errno_or_else(EIO), "Unable to probe for partition table of '%s': %m", p);
5734 if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND)) {
5735 log_debug("Didn't find partition table on block device '%s'.", p);
5736 return false;
5737 }
5738
5739 assert(r == _BLKID_SAFEPROBE_FOUND);
5740
5741 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
5742 if (!streq_ptr(pttype, "gpt")) {
5743 log_debug("Didn't find a GPT partition table on '%s'.", p);
5744 return false;
5745 }
5746
5747 errno = 0;
5748 pl = blkid_probe_get_partitions(b);
5749 if (!pl)
5750 return log_error_errno(errno_or_else(EIO), "Unable read partition table of '%s': %m", p);
5751
5752 pp = blkid_partlist_devno_to_partition(pl, partition_devno);
5753 if (!pp) {
5754 log_debug("Partition %u:%u has no matching partition table entry on '%s'.",
5755 major(partition_devno), minor(partition_devno), p);
5756 return false;
5757 }
5758
5759 t = blkid_partition_get_type_string(pp);
5760 if (isempty(t)) {
5761 log_debug("Partition %u:%u has no type on '%s'.",
5762 major(partition_devno), minor(partition_devno), p);
5763 return false;
5764 }
5765
5766 r = sd_id128_from_string(t, &pt_parsed);
5767 if (r < 0) {
5768 log_debug_errno(r, "Failed to parse partition type \"%s\": %m", t);
5769 return false;
5770 }
5771
5772 if (!sd_id128_equal(pt_parsed, partition_type.uuid)) {
5773 log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
5774 major(partition_devno), minor(partition_devno),
5775 SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type.uuid));
5776 return false;
5777 }
5778
5779 r = blkid_partition_get_uuid_id128(pp, &u);
5780 if (r == -ENXIO) {
5781 log_debug_errno(r, "Partition " DEVNUM_FORMAT_STR " has no UUID.", DEVNUM_FORMAT_VAL(partition_devno));
5782 return false;
5783 }
5784 if (r < 0) {
5785 log_debug_errno(r, "Failed to read partition UUID of " DEVNUM_FORMAT_STR ": %m", DEVNUM_FORMAT_VAL(partition_devno));
5786 return false;
5787 }
5788
5789 log_debug("Automatically found partition " DEVNUM_FORMAT_STR " of right type " SD_ID128_FORMAT_STR ".",
5790 DEVNUM_FORMAT_VAL(partition_devno),
5791 SD_ID128_FORMAT_VAL(pt_parsed));
5792
5793 if (ret_uuid)
5794 *ret_uuid = u;
5795
5796 return true;
5797 }
5798
5799 static int find_backing_devno(
5800 const char *path,
5801 const char *root,
5802 dev_t *ret) {
5803
5804 _cleanup_free_ char *resolved = NULL;
5805 int r;
5806
5807 assert(path);
5808
5809 r = chase(path, root, CHASE_PREFIX_ROOT, &resolved, NULL);
5810 if (r < 0)
5811 return r;
5812
5813 r = path_is_mount_point(resolved, NULL, 0);
5814 if (r < 0)
5815 return r;
5816 if (r == 0) /* Not a mount point, then it's not a partition of its own, let's not automatically use it. */
5817 return -ENOENT;
5818
5819 r = get_block_device(resolved, ret);
5820 if (r < 0)
5821 return r;
5822 if (r == 0) /* Not backed by physical file system, we can't use this */
5823 return -ENOENT;
5824
5825 return 0;
5826 }
5827
5828 static int resolve_copy_blocks_auto(
5829 GptPartitionType type,
5830 const char *root,
5831 dev_t restrict_devno,
5832 dev_t *ret_devno,
5833 sd_id128_t *ret_uuid) {
5834
5835 const char *try1 = NULL, *try2 = NULL;
5836 char p[SYS_BLOCK_PATH_MAX("/slaves")];
5837 _cleanup_closedir_ DIR *d = NULL;
5838 sd_id128_t found_uuid = SD_ID128_NULL;
5839 dev_t devno, found = 0;
5840 int r;
5841
5842 /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
5843 * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
5844 * and restrict block device references in the --image= case to loopback block device we set up.
5845 *
5846 * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
5847 * thus declares which device (and its partition subdevices) we shall limit access to. If
5848 * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
5849 * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
5850
5851 if (restrict_devno == 0)
5852 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
5853 "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
5854
5855 /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
5856 * partitions in the host, using the appropriate directory as key and ensuring that the partition
5857 * type matches. */
5858
5859 if (type.designator == PARTITION_ROOT)
5860 try1 = "/";
5861 else if (type.designator == PARTITION_USR)
5862 try1 = "/usr/";
5863 else if (type.designator == PARTITION_ROOT_VERITY)
5864 try1 = "/";
5865 else if (type.designator == PARTITION_USR_VERITY)
5866 try1 = "/usr/";
5867 else if (type.designator == PARTITION_ESP) {
5868 try1 = "/efi/";
5869 try2 = "/boot/";
5870 } else if (type.designator == PARTITION_XBOOTLDR)
5871 try1 = "/boot/";
5872 else
5873 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5874 "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
5875 SD_ID128_FORMAT_VAL(type.uuid));
5876
5877 r = find_backing_devno(try1, root, &devno);
5878 if (r == -ENOENT && try2)
5879 r = find_backing_devno(try2, root, &devno);
5880 if (r < 0)
5881 return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
5882 SD_ID128_FORMAT_VAL(type.uuid));
5883
5884 xsprintf_sys_block_path(p, "/slaves", devno);
5885 d = opendir(p);
5886 if (d) {
5887 struct dirent *de;
5888
5889 for (;;) {
5890 _cleanup_free_ char *q = NULL, *t = NULL;
5891 sd_id128_t u;
5892 dev_t sl;
5893
5894 errno = 0;
5895 de = readdir_no_dot(d);
5896 if (!de) {
5897 if (errno != 0)
5898 return log_error_errno(errno, "Failed to read directory '%s': %m", p);
5899
5900 break;
5901 }
5902
5903 if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
5904 continue;
5905
5906 q = path_join(p, de->d_name, "/dev");
5907 if (!q)
5908 return log_oom();
5909
5910 r = read_one_line_file(q, &t);
5911 if (r < 0)
5912 return log_error_errno(r, "Failed to read %s: %m", q);
5913
5914 r = parse_devnum(t, &sl);
5915 if (r < 0) {
5916 log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
5917 continue;
5918 }
5919 if (major(sl) == 0) {
5920 log_debug("Device backing %s is special, ignoring.", q);
5921 continue;
5922 }
5923
5924 r = resolve_copy_blocks_auto_candidate(sl, type, restrict_devno, &u);
5925 if (r < 0)
5926 return r;
5927 if (r > 0) {
5928 /* We found a matching one! */
5929 if (found != 0)
5930 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
5931 "Multiple matching partitions found, refusing.");
5932
5933 found = sl;
5934 found_uuid = u;
5935 }
5936 }
5937 } else if (errno != ENOENT)
5938 return log_error_errno(errno, "Failed open %s: %m", p);
5939 else {
5940 r = resolve_copy_blocks_auto_candidate(devno, type, restrict_devno, &found_uuid);
5941 if (r < 0)
5942 return r;
5943 if (r > 0)
5944 found = devno;
5945 }
5946
5947 if (found == 0)
5948 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
5949 "Unable to automatically discover suitable partition to copy blocks from.");
5950
5951 if (ret_devno)
5952 *ret_devno = found;
5953
5954 if (ret_uuid)
5955 *ret_uuid = found_uuid;
5956
5957 return 0;
5958 }
5959
5960 static int context_open_copy_block_paths(
5961 Context *context,
5962 dev_t restrict_devno) {
5963
5964 int r;
5965
5966 assert(context);
5967
5968 LIST_FOREACH(partitions, p, context->partitions) {
5969 _cleanup_close_ int source_fd = -EBADF;
5970 _cleanup_free_ char *opened = NULL;
5971 sd_id128_t uuid = SD_ID128_NULL;
5972 uint64_t size;
5973 struct stat st;
5974
5975 if (p->copy_blocks_fd >= 0)
5976 continue;
5977
5978 assert(p->copy_blocks_size == UINT64_MAX);
5979
5980 if (PARTITION_EXISTS(p)) /* Never copy over partitions that already exist! */
5981 continue;
5982
5983 if (p->copy_blocks_path) {
5984
5985 source_fd = chase_and_open(p->copy_blocks_path, p->copy_blocks_root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
5986 if (source_fd < 0)
5987 return log_error_errno(source_fd, "Failed to open '%s': %m", p->copy_blocks_path);
5988
5989 if (fstat(source_fd, &st) < 0)
5990 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
5991
5992 if (!S_ISREG(st.st_mode) && restrict_devno != (dev_t) -1)
5993 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
5994 "Copying from block device node is not permitted in --image=/--root= mode, refusing.");
5995
5996 } else if (p->copy_blocks_auto) {
5997 dev_t devno = 0; /* Fake initialization to appease gcc. */
5998
5999 r = resolve_copy_blocks_auto(p->type, p->copy_blocks_root, restrict_devno, &devno, &uuid);
6000 if (r < 0)
6001 return r;
6002 assert(devno != 0);
6003
6004 source_fd = r = device_open_from_devnum(S_IFBLK, devno, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
6005 if (r < 0)
6006 return log_error_errno(r, "Failed to open automatically determined source block copy device " DEVNUM_FORMAT_STR ": %m",
6007 DEVNUM_FORMAT_VAL(devno));
6008
6009 if (fstat(source_fd, &st) < 0)
6010 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
6011 } else
6012 continue;
6013
6014 if (S_ISDIR(st.st_mode)) {
6015 _cleanup_free_ char *bdev = NULL;
6016 dev_t devt;
6017
6018 /* If the file is a directory, automatically find the backing block device */
6019
6020 if (major(st.st_dev) != 0)
6021 devt = st.st_dev;
6022 else {
6023 /* Special support for btrfs */
6024 r = btrfs_get_block_device_fd(source_fd, &devt);
6025 if (r == -EUCLEAN)
6026 return btrfs_log_dev_root(LOG_ERR, r, opened);
6027 if (r < 0)
6028 return log_error_errno(r, "Unable to determine backing block device of '%s': %m", opened);
6029 }
6030
6031 safe_close(source_fd);
6032
6033 source_fd = r = device_open_from_devnum(S_IFBLK, devt, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &bdev);
6034 if (r < 0)
6035 return log_error_errno(r, "Failed to open block device backing '%s': %m", opened);
6036
6037 if (fstat(source_fd, &st) < 0)
6038 return log_error_errno(errno, "Failed to stat block device '%s': %m", bdev);
6039 }
6040
6041 if (S_ISREG(st.st_mode))
6042 size = st.st_size;
6043 else if (S_ISBLK(st.st_mode)) {
6044 r = blockdev_get_device_size(source_fd, &size);
6045 if (r < 0)
6046 return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
6047 } else
6048 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing: %m", opened);
6049
6050 if (size <= 0)
6051 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
6052 if (size % 512 != 0)
6053 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
6054
6055 p->copy_blocks_fd = TAKE_FD(source_fd);
6056 p->copy_blocks_size = size;
6057
6058 free_and_replace(p->copy_blocks_path, opened);
6059
6060 /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
6061 if (!p->new_uuid_is_set && !sd_id128_is_null(uuid)) {
6062 p->new_uuid = uuid;
6063 p->new_uuid_is_set = true;
6064 }
6065 }
6066
6067 return 0;
6068 }
6069
6070 static int fd_apparent_size(int fd, uint64_t *ret) {
6071 off_t initial = 0;
6072 uint64_t size = 0;
6073
6074 assert(fd >= 0);
6075 assert(ret);
6076
6077 initial = lseek(fd, 0, SEEK_CUR);
6078 if (initial < 0)
6079 return log_error_errno(errno, "Failed to get file offset: %m");
6080
6081 for (off_t off = 0;;) {
6082 off_t r;
6083
6084 r = lseek(fd, off, SEEK_DATA);
6085 if (r < 0 && errno == ENXIO)
6086 /* If errno == ENXIO, that means we've reached the final hole of the file and
6087 * that hole isn't followed by more data. */
6088 break;
6089 if (r < 0)
6090 return log_error_errno(errno, "Failed to seek data in file from offset %"PRIi64": %m", off);
6091
6092 off = r; /* Set the offset to the start of the data segment. */
6093
6094 /* After copying a potential hole, find the end of the data segment by looking for
6095 * the next hole. If we get ENXIO, we're at EOF. */
6096 r = lseek(fd, off, SEEK_HOLE);
6097 if (r < 0) {
6098 if (errno == ENXIO)
6099 break;
6100 return log_error_errno(errno, "Failed to seek hole in file from offset %"PRIi64": %m", off);
6101 }
6102
6103 size += r - off;
6104 off = r;
6105 }
6106
6107 if (lseek(fd, initial, SEEK_SET) < 0)
6108 return log_error_errno(errno, "Failed to reset file offset: %m");
6109
6110 *ret = size;
6111
6112 return 0;
6113 }
6114
6115 static int context_minimize(Context *context) {
6116 const char *vt = NULL;
6117 int r;
6118
6119 assert(context);
6120
6121 LIST_FOREACH(partitions, p, context->partitions) {
6122 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
6123 _cleanup_(unlink_and_freep) char *temp = NULL;
6124 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
6125 _cleanup_strv_free_ char **extra_mkfs_options = NULL;
6126 _cleanup_close_ int fd = -EBADF;
6127 _cleanup_free_ char *hint = NULL;
6128 sd_id128_t fs_uuid;
6129 struct stat st;
6130 uint64_t fsz;
6131
6132 if (p->dropped)
6133 continue;
6134
6135 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
6136 continue;
6137
6138 if (!p->format)
6139 continue;
6140
6141 if (p->copy_blocks_fd >= 0)
6142 continue;
6143
6144 if (p->minimize == MINIMIZE_OFF)
6145 continue;
6146
6147 if (!partition_needs_populate(p))
6148 continue;
6149
6150 assert(!p->copy_blocks_path);
6151
6152 (void) partition_hint(p, context->node, &hint);
6153
6154 log_info("Pre-populating %s filesystem of partition %s twice to calculate minimal partition size",
6155 p->format, strna(hint));
6156
6157 if (!vt) {
6158 r = var_tmp_dir(&vt);
6159 if (r < 0)
6160 return log_error_errno(r, "Could not determine temporary directory: %m");
6161 }
6162
6163 r = tempfn_random_child(vt, "repart", &temp);
6164 if (r < 0)
6165 return log_error_errno(r, "Failed to generate temporary file path: %m");
6166
6167 if (fstype_is_ro(p->format))
6168 fs_uuid = p->fs_uuid;
6169 else {
6170 fd = open(temp, O_CREAT|O_EXCL|O_CLOEXEC|O_RDWR|O_NOCTTY, 0600);
6171 if (fd < 0)
6172 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6173
6174 /* This may seem huge but it will be created sparse so it doesn't take up any space
6175 * on disk until written to. */
6176 if (ftruncate(fd, 1024ULL * 1024ULL * 1024ULL * 1024ULL) < 0)
6177 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m",
6178 FORMAT_BYTES(1024ULL * 1024ULL * 1024ULL * 1024ULL));
6179
6180 if (arg_offline <= 0) {
6181 r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d);
6182 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
6183 return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
6184 }
6185
6186 /* We're going to populate this filesystem twice so use a random UUID the first time
6187 * to avoid UUID conflicts. */
6188 r = sd_id128_randomize(&fs_uuid);
6189 if (r < 0)
6190 return r;
6191 }
6192
6193 if (!d || fstype_is_ro(p->format)) {
6194 if (!mkfs_supports_root_option(p->format))
6195 return log_error_errno(SYNTHETIC_ERRNO(ENODEV),
6196 "Loop device access is required to populate %s filesystems",
6197 p->format);
6198
6199 r = partition_populate_directory(context, p, &root);
6200 if (r < 0)
6201 return r;
6202 }
6203
6204 r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options);
6205 if (r < 0)
6206 return log_error_errno(r,
6207 "Failed to determine mkfs command line options for '%s': %m",
6208 p->format);
6209
6210 r = make_filesystem(d ? d->node : temp,
6211 p->format,
6212 strempty(p->new_label),
6213 root,
6214 fs_uuid,
6215 arg_discard, /* quiet = */ false,
6216 context->fs_sector_size,
6217 extra_mkfs_options);
6218 if (r < 0)
6219 return r;
6220
6221 /* Read-only filesystems are minimal from the first try because they create and size the
6222 * loopback file for us. */
6223 if (fstype_is_ro(p->format)) {
6224 assert(fd < 0);
6225
6226 fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
6227 if (fd < 0)
6228 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6229
6230 if (fstat(fd, &st) < 0)
6231 return log_error_errno(errno, "Failed to stat temporary file: %m");
6232
6233 log_info("Minimal partition size of %s filesystem of partition %s is %s",
6234 p->format, strna(hint), FORMAT_BYTES(st.st_size));
6235
6236 p->copy_blocks_path = TAKE_PTR(temp);
6237 p->copy_blocks_path_is_our_file = true;
6238 p->copy_blocks_fd = TAKE_FD(fd);
6239 p->copy_blocks_size = st.st_size;
6240 continue;
6241 }
6242
6243 if (!root) {
6244 assert(d);
6245
6246 r = partition_populate_filesystem(context, p, d->node);
6247 if (r < 0)
6248 return r;
6249 }
6250
6251 /* Other filesystems need to be provided with a pre-sized loopback file and will adapt to
6252 * fully occupy it. Because we gave the filesystem a 1T sparse file, we need to shrink the
6253 * filesystem down to a reasonable size again to fit it in the disk image. While there are
6254 * some filesystems that support shrinking, it doesn't always work properly (e.g. shrinking
6255 * btrfs gives us a 2.0G filesystem regardless of what we put in it). Instead, let's populate
6256 * the filesystem again, but this time, instead of providing the filesystem with a 1T sparse
6257 * loopback file, let's size the loopback file based on the actual data used by the
6258 * filesystem in the sparse file after the first attempt. This should be a good guess of the
6259 * minimal amount of space needed in the filesystem to fit all the required data.
6260 */
6261 r = fd_apparent_size(fd, &fsz);
6262 if (r < 0)
6263 return r;
6264
6265 /* Massage the size a bit because just going by actual data used in the sparse file isn't
6266 * fool-proof. */
6267 uint64_t heuristic = streq(p->format, "xfs") ? fsz : fsz / 2;
6268 fsz = round_up_size(fsz + heuristic, context->grain_size);
6269 if (minimal_size_by_fs_name(p->format) != UINT64_MAX)
6270 fsz = MAX(minimal_size_by_fs_name(p->format), fsz);
6271
6272 log_info("Minimal partition size of %s filesystem of partition %s is %s",
6273 p->format, strna(hint), FORMAT_BYTES(fsz));
6274
6275 d = loop_device_unref(d);
6276
6277 /* Erase the previous filesystem first. */
6278 if (ftruncate(fd, 0) < 0)
6279 return log_error_errno(errno, "Failed to erase temporary file: %m");
6280
6281 if (ftruncate(fd, fsz) < 0)
6282 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m", FORMAT_BYTES(fsz));
6283
6284 if (arg_offline <= 0) {
6285 r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d);
6286 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
6287 return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
6288 }
6289
6290 r = make_filesystem(d ? d->node : temp,
6291 p->format,
6292 strempty(p->new_label),
6293 root,
6294 p->fs_uuid,
6295 arg_discard,
6296 /* quiet = */ false,
6297 context->fs_sector_size,
6298 extra_mkfs_options);
6299 if (r < 0)
6300 return r;
6301
6302 if (!root) {
6303 assert(d);
6304
6305 r = partition_populate_filesystem(context, p, d->node);
6306 if (r < 0)
6307 return r;
6308 }
6309
6310 if (fstat(fd, &st) < 0)
6311 return log_error_errno(errno, "Failed to stat temporary file: %m");
6312
6313 p->copy_blocks_path = TAKE_PTR(temp);
6314 p->copy_blocks_path_is_our_file = true;
6315 p->copy_blocks_fd = TAKE_FD(fd);
6316 p->copy_blocks_size = st.st_size;
6317 }
6318
6319 /* Now that we've done the data partitions, do the verity hash partitions. We do these in a separate
6320 * step because they might depend on data generated in the previous step. */
6321
6322 LIST_FOREACH(partitions, p, context->partitions) {
6323 _cleanup_(unlink_and_freep) char *temp = NULL;
6324 _cleanup_free_ char *hint = NULL;
6325 _cleanup_close_ int fd = -EBADF;
6326 struct stat st;
6327 Partition *dp;
6328
6329 if (p->dropped)
6330 continue;
6331
6332 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
6333 continue;
6334
6335 if (p->minimize == MINIMIZE_OFF)
6336 continue;
6337
6338 if (p->verity != VERITY_HASH)
6339 continue;
6340
6341 assert_se(dp = p->siblings[VERITY_DATA]);
6342 assert(!dp->dropped);
6343 assert(dp->copy_blocks_path);
6344
6345 (void) partition_hint(p, context->node, &hint);
6346
6347 log_info("Pre-populating verity hash data of partition %s to calculate minimal partition size",
6348 strna(hint));
6349
6350 if (!vt) {
6351 r = var_tmp_dir(&vt);
6352 if (r < 0)
6353 return log_error_errno(r, "Could not determine temporary directory: %m");
6354 }
6355
6356 r = tempfn_random_child(vt, "repart", &temp);
6357 if (r < 0)
6358 return log_error_errno(r, "Failed to generate temporary file path: %m");
6359
6360 r = touch(temp);
6361 if (r < 0)
6362 return log_error_errno(r, "Failed to create temporary file: %m");
6363
6364 r = partition_format_verity_hash(context, p, temp, dp->copy_blocks_path);
6365 if (r < 0)
6366 return r;
6367
6368 fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
6369 if (fd < 0)
6370 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6371
6372 if (fstat(fd, &st) < 0)
6373 return log_error_errno(errno, "Failed to stat temporary file: %m");
6374
6375 log_info("Minimal partition size of verity hash partition %s is %s",
6376 strna(hint), FORMAT_BYTES(st.st_size));
6377
6378 p->copy_blocks_path = TAKE_PTR(temp);
6379 p->copy_blocks_path_is_our_file = true;
6380 p->copy_blocks_fd = TAKE_FD(fd);
6381 p->copy_blocks_size = st.st_size;
6382 }
6383
6384 return 0;
6385 }
6386
6387 static int parse_partition_types(const char *p, GptPartitionType **partitions, size_t *n_partitions) {
6388 int r;
6389
6390 assert(partitions);
6391 assert(n_partitions);
6392
6393 for (;;) {
6394 _cleanup_free_ char *name = NULL;
6395 GptPartitionType type;
6396
6397 r = extract_first_word(&p, &name, ",", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
6398 if (r == 0)
6399 break;
6400 if (r < 0)
6401 return log_error_errno(r, "Failed to extract partition type identifier or GUID: %s", p);
6402
6403 r = gpt_partition_type_from_string(name, &type);
6404 if (r < 0)
6405 return log_error_errno(r, "'%s' is not a valid partition type identifier or GUID", name);
6406
6407 if (!GREEDY_REALLOC(*partitions, *n_partitions + 1))
6408 return log_oom();
6409
6410 (*partitions)[(*n_partitions)++] = type;
6411 }
6412
6413 return 0;
6414 }
6415
6416 static int help(void) {
6417 _cleanup_free_ char *link = NULL;
6418 int r;
6419
6420 r = terminal_urlify_man("systemd-repart", "8", &link);
6421 if (r < 0)
6422 return log_oom();
6423
6424 printf("%s [OPTIONS...] [DEVICE]\n"
6425 "\n%sGrow and add partitions to partition table.%s\n\n"
6426 " -h --help Show this help\n"
6427 " --version Show package version\n"
6428 " --no-pager Do not pipe output into a pager\n"
6429 " --no-legend Do not show the headers and footers\n"
6430 " --dry-run=BOOL Whether to run dry-run operation\n"
6431 " --empty=MODE One of refuse, allow, require, force, create; controls\n"
6432 " how to handle empty disks lacking partition tables\n"
6433 " --discard=BOOL Whether to discard backing blocks for new partitions\n"
6434 " --pretty=BOOL Whether to show pretty summary before doing changes\n"
6435 " --factory-reset=BOOL Whether to remove data partitions before recreating\n"
6436 " them\n"
6437 " --can-factory-reset Test whether factory reset is defined\n"
6438 " --root=PATH Operate relative to root path\n"
6439 " --image=PATH Operate relative to image file\n"
6440 " --image-policy=POLICY\n"
6441 " Specify disk image dissection policy\n"
6442 " --definitions=DIR Find partition definitions in specified directory\n"
6443 " --key-file=PATH Key to use when encrypting partitions\n"
6444 " --private-key=PATH Private key to use when generating verity roothash\n"
6445 " signatures\n"
6446 " --certificate=PATH PEM certificate to use when generating verity\n"
6447 " roothash signatures\n"
6448 " --tpm2-device=PATH Path to TPM2 device node to use\n"
6449 " --tpm2-device-key=PATH\n"
6450 " Enroll a TPM2 device using its public key\n"
6451 " --tpm2-seal-key-handle=HANDLE\n"
6452 " Specify handle of key to use for sealing\n"
6453 " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
6454 " TPM2 PCR indexes to use for TPM2 enrollment\n"
6455 " --tpm2-public-key=PATH\n"
6456 " Enroll signed TPM2 PCR policy against PEM public key\n"
6457 " --tpm2-public-key-pcrs=PCR1+PCR2+PCR3+…\n"
6458 " Enroll signed TPM2 PCR policy for specified TPM2 PCRs\n"
6459 " --tpm2-pcrlock=PATH\n"
6460 " Specify pcrlock policy to lock against\n"
6461 " --seed=UUID 128-bit seed UUID to derive all UUIDs from\n"
6462 " --size=BYTES Grow loopback file to specified size\n"
6463 " --json=pretty|short|off\n"
6464 " Generate JSON output\n"
6465 " --split=BOOL Whether to generate split artifacts\n"
6466 " --include-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6467 " Ignore partitions not of the specified types\n"
6468 " --exclude-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6469 " Ignore partitions of the specified types\n"
6470 " --defer-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6471 " Take partitions of the specified types into account\n"
6472 " but don't populate them yet\n"
6473 " --sector-size=SIZE Set the logical sector size for the image\n"
6474 " --architecture=ARCH Set the generic architecture for the image\n"
6475 " --offline=BOOL Whether to build the image offline\n"
6476 " -s --copy-source=PATH Specify the primary source tree to copy files from\n"
6477 " --copy-from=IMAGE Copy partitions from the given image(s)\n"
6478 " -S --make-ddi=sysext Make a system extension DDI\n"
6479 " -C --make-ddi=confext Make a configuration extension DDI\n"
6480 " -P --make-ddi=portable Make a portable service DDI\n"
6481 "\nSee the %s for details.\n",
6482 program_invocation_short_name,
6483 ansi_highlight(),
6484 ansi_normal(),
6485 link);
6486
6487 return 0;
6488 }
6489
6490 static int parse_argv(int argc, char *argv[]) {
6491
6492 enum {
6493 ARG_VERSION = 0x100,
6494 ARG_NO_PAGER,
6495 ARG_NO_LEGEND,
6496 ARG_DRY_RUN,
6497 ARG_EMPTY,
6498 ARG_DISCARD,
6499 ARG_FACTORY_RESET,
6500 ARG_CAN_FACTORY_RESET,
6501 ARG_ROOT,
6502 ARG_IMAGE,
6503 ARG_IMAGE_POLICY,
6504 ARG_SEED,
6505 ARG_PRETTY,
6506 ARG_DEFINITIONS,
6507 ARG_SIZE,
6508 ARG_JSON,
6509 ARG_KEY_FILE,
6510 ARG_PRIVATE_KEY,
6511 ARG_CERTIFICATE,
6512 ARG_TPM2_DEVICE,
6513 ARG_TPM2_DEVICE_KEY,
6514 ARG_TPM2_SEAL_KEY_HANDLE,
6515 ARG_TPM2_PCRS,
6516 ARG_TPM2_PUBLIC_KEY,
6517 ARG_TPM2_PUBLIC_KEY_PCRS,
6518 ARG_TPM2_PCRLOCK,
6519 ARG_SPLIT,
6520 ARG_INCLUDE_PARTITIONS,
6521 ARG_EXCLUDE_PARTITIONS,
6522 ARG_DEFER_PARTITIONS,
6523 ARG_SECTOR_SIZE,
6524 ARG_SKIP_PARTITIONS,
6525 ARG_ARCHITECTURE,
6526 ARG_OFFLINE,
6527 ARG_COPY_FROM,
6528 ARG_MAKE_DDI,
6529 };
6530
6531 static const struct option options[] = {
6532 { "help", no_argument, NULL, 'h' },
6533 { "version", no_argument, NULL, ARG_VERSION },
6534 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6535 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6536 { "dry-run", required_argument, NULL, ARG_DRY_RUN },
6537 { "empty", required_argument, NULL, ARG_EMPTY },
6538 { "discard", required_argument, NULL, ARG_DISCARD },
6539 { "factory-reset", required_argument, NULL, ARG_FACTORY_RESET },
6540 { "can-factory-reset", no_argument, NULL, ARG_CAN_FACTORY_RESET },
6541 { "root", required_argument, NULL, ARG_ROOT },
6542 { "image", required_argument, NULL, ARG_IMAGE },
6543 { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
6544 { "seed", required_argument, NULL, ARG_SEED },
6545 { "pretty", required_argument, NULL, ARG_PRETTY },
6546 { "definitions", required_argument, NULL, ARG_DEFINITIONS },
6547 { "size", required_argument, NULL, ARG_SIZE },
6548 { "json", required_argument, NULL, ARG_JSON },
6549 { "key-file", required_argument, NULL, ARG_KEY_FILE },
6550 { "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
6551 { "certificate", required_argument, NULL, ARG_CERTIFICATE },
6552 { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
6553 { "tpm2-device-key", required_argument, NULL, ARG_TPM2_DEVICE_KEY },
6554 { "tpm2-seal-key-handle", required_argument, NULL, ARG_TPM2_SEAL_KEY_HANDLE },
6555 { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
6556 { "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
6557 { "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
6558 { "tpm2-pcrlock", required_argument, NULL, ARG_TPM2_PCRLOCK },
6559 { "split", required_argument, NULL, ARG_SPLIT },
6560 { "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS },
6561 { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS },
6562 { "defer-partitions", required_argument, NULL, ARG_DEFER_PARTITIONS },
6563 { "sector-size", required_argument, NULL, ARG_SECTOR_SIZE },
6564 { "architecture", required_argument, NULL, ARG_ARCHITECTURE },
6565 { "offline", required_argument, NULL, ARG_OFFLINE },
6566 { "copy-from", required_argument, NULL, ARG_COPY_FROM },
6567 { "copy-source", required_argument, NULL, 's' },
6568 { "make-ddi", required_argument, NULL, ARG_MAKE_DDI },
6569 {}
6570 };
6571
6572 bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true, auto_pcrlock = true;
6573 int c, r;
6574
6575 assert(argc >= 0);
6576 assert(argv);
6577
6578 while ((c = getopt_long(argc, argv, "hs:SCP", options, NULL)) >= 0)
6579
6580 switch (c) {
6581
6582 case 'h':
6583 return help();
6584
6585 case ARG_VERSION:
6586 return version();
6587
6588 case ARG_NO_PAGER:
6589 arg_pager_flags |= PAGER_DISABLE;
6590 break;
6591
6592 case ARG_NO_LEGEND:
6593 arg_legend = false;
6594 break;
6595
6596 case ARG_DRY_RUN:
6597 r = parse_boolean_argument("--dry-run=", optarg, &arg_dry_run);
6598 if (r < 0)
6599 return r;
6600 break;
6601
6602 case ARG_EMPTY:
6603 if (isempty(optarg)) {
6604 arg_empty = EMPTY_UNSET;
6605 break;
6606 }
6607
6608 arg_empty = empty_mode_from_string(optarg);
6609 if (arg_empty < 0)
6610 return log_error_errno(arg_empty, "Failed to parse --empty= parameter: %s", optarg);
6611
6612 break;
6613
6614 case ARG_DISCARD:
6615 r = parse_boolean_argument("--discard=", optarg, &arg_discard);
6616 if (r < 0)
6617 return r;
6618 break;
6619
6620 case ARG_FACTORY_RESET:
6621 r = parse_boolean_argument("--factory-reset=", optarg, NULL);
6622 if (r < 0)
6623 return r;
6624 arg_factory_reset = r;
6625 break;
6626
6627 case ARG_CAN_FACTORY_RESET:
6628 arg_can_factory_reset = true;
6629 break;
6630
6631 case ARG_ROOT:
6632 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
6633 if (r < 0)
6634 return r;
6635 break;
6636
6637 case ARG_IMAGE:
6638 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
6639 if (r < 0)
6640 return r;
6641 break;
6642
6643 case ARG_IMAGE_POLICY:
6644 r = parse_image_policy_argument(optarg, &arg_image_policy);
6645 if (r < 0)
6646 return r;
6647 break;
6648
6649 case ARG_SEED:
6650 if (isempty(optarg)) {
6651 arg_seed = SD_ID128_NULL;
6652 arg_randomize = false;
6653 } else if (streq(optarg, "random"))
6654 arg_randomize = true;
6655 else {
6656 r = sd_id128_from_string(optarg, &arg_seed);
6657 if (r < 0)
6658 return log_error_errno(r, "Failed to parse seed: %s", optarg);
6659
6660 arg_randomize = false;
6661 }
6662
6663 break;
6664
6665 case ARG_PRETTY:
6666 r = parse_boolean_argument("--pretty=", optarg, NULL);
6667 if (r < 0)
6668 return r;
6669 arg_pretty = r;
6670 break;
6671
6672 case ARG_DEFINITIONS: {
6673 _cleanup_free_ char *path = NULL;
6674 r = parse_path_argument(optarg, false, &path);
6675 if (r < 0)
6676 return r;
6677 if (strv_consume(&arg_definitions, TAKE_PTR(path)) < 0)
6678 return log_oom();
6679 break;
6680 }
6681
6682 case ARG_SIZE: {
6683 uint64_t parsed, rounded;
6684
6685 if (streq(optarg, "auto")) {
6686 arg_size = UINT64_MAX;
6687 arg_size_auto = true;
6688 break;
6689 }
6690
6691 r = parse_size(optarg, 1024, &parsed);
6692 if (r < 0)
6693 return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg);
6694
6695 rounded = round_up_size(parsed, 4096);
6696 if (rounded == 0)
6697 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too small, refusing.");
6698 if (rounded == UINT64_MAX)
6699 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too large, refusing.");
6700
6701 if (rounded != parsed)
6702 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64 " %s %" PRIu64 ")",
6703 parsed, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), rounded);
6704
6705 arg_size = rounded;
6706 arg_size_auto = false;
6707 break;
6708 }
6709
6710 case ARG_JSON:
6711 r = parse_json_argument(optarg, &arg_json_format_flags);
6712 if (r <= 0)
6713 return r;
6714
6715 break;
6716
6717 case ARG_KEY_FILE: {
6718 _cleanup_(erase_and_freep) char *k = NULL;
6719 size_t n = 0;
6720
6721 r = read_full_file_full(
6722 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6723 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
6724 NULL,
6725 &k, &n);
6726 if (r < 0)
6727 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
6728
6729 erase_and_free(arg_key);
6730 arg_key = TAKE_PTR(k);
6731 arg_key_size = n;
6732 break;
6733 }
6734
6735 case ARG_PRIVATE_KEY: {
6736 _cleanup_(erase_and_freep) char *k = NULL;
6737 size_t n = 0;
6738
6739 r = read_full_file_full(
6740 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6741 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
6742 NULL,
6743 &k, &n);
6744 if (r < 0)
6745 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
6746
6747 EVP_PKEY_free(arg_private_key);
6748 arg_private_key = NULL;
6749 r = parse_private_key(k, n, &arg_private_key);
6750 if (r < 0)
6751 return r;
6752 break;
6753 }
6754
6755 case ARG_CERTIFICATE: {
6756 _cleanup_free_ char *cert = NULL;
6757 size_t n = 0;
6758
6759 r = read_full_file_full(
6760 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6761 READ_FULL_FILE_CONNECT_SOCKET,
6762 NULL,
6763 &cert, &n);
6764 if (r < 0)
6765 return log_error_errno(r, "Failed to read certificate file '%s': %m", optarg);
6766
6767 X509_free(arg_certificate);
6768 arg_certificate = NULL;
6769 r = parse_x509_certificate(cert, n, &arg_certificate);
6770 if (r < 0)
6771 return r;
6772 break;
6773 }
6774
6775 case ARG_TPM2_DEVICE: {
6776 _cleanup_free_ char *device = NULL;
6777
6778 if (streq(optarg, "list"))
6779 return tpm2_list_devices();
6780
6781 if (!streq(optarg, "auto")) {
6782 device = strdup(optarg);
6783 if (!device)
6784 return log_oom();
6785 }
6786
6787 free(arg_tpm2_device);
6788 arg_tpm2_device = TAKE_PTR(device);
6789 break;
6790 }
6791
6792 case ARG_TPM2_DEVICE_KEY:
6793 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_device_key);
6794 if (r < 0)
6795 return r;
6796
6797 break;
6798
6799 case ARG_TPM2_SEAL_KEY_HANDLE:
6800 r = safe_atou32_full(optarg, 16, &arg_tpm2_seal_key_handle);
6801 if (r < 0)
6802 return log_error_errno(r, "Could not parse TPM2 seal key handle index '%s': %m", optarg);
6803
6804 break;
6805
6806 case ARG_TPM2_PCRS:
6807 auto_hash_pcr_values = false;
6808 r = tpm2_parse_pcr_argument_append(optarg, &arg_tpm2_hash_pcr_values, &arg_tpm2_n_hash_pcr_values);
6809 if (r < 0)
6810 return r;
6811
6812 break;
6813
6814 case ARG_TPM2_PUBLIC_KEY:
6815 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key);
6816 if (r < 0)
6817 return r;
6818
6819 break;
6820
6821 case ARG_TPM2_PUBLIC_KEY_PCRS:
6822 auto_public_key_pcr_mask = false;
6823 r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
6824 if (r < 0)
6825 return r;
6826
6827 break;
6828
6829 case ARG_TPM2_PCRLOCK:
6830 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_pcrlock);
6831 if (r < 0)
6832 return r;
6833
6834 auto_pcrlock = false;
6835 break;
6836
6837 case ARG_SPLIT:
6838 r = parse_boolean_argument("--split=", optarg, NULL);
6839 if (r < 0)
6840 return r;
6841
6842 arg_split = r;
6843 break;
6844
6845 case ARG_INCLUDE_PARTITIONS:
6846 if (arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE)
6847 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6848 "Combination of --include-partitions= and --exclude-partitions= is invalid.");
6849
6850 r = parse_partition_types(optarg, &arg_filter_partitions, &arg_n_filter_partitions);
6851 if (r < 0)
6852 return r;
6853
6854 arg_filter_partitions_type = FILTER_PARTITIONS_INCLUDE;
6855
6856 break;
6857
6858 case ARG_EXCLUDE_PARTITIONS:
6859 if (arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE)
6860 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6861 "Combination of --include-partitions= and --exclude-partitions= is invalid.");
6862
6863 r = parse_partition_types(optarg, &arg_filter_partitions, &arg_n_filter_partitions);
6864 if (r < 0)
6865 return r;
6866
6867 arg_filter_partitions_type = FILTER_PARTITIONS_EXCLUDE;
6868
6869 break;
6870
6871 case ARG_DEFER_PARTITIONS:
6872 r = parse_partition_types(optarg, &arg_defer_partitions, &arg_n_defer_partitions);
6873 if (r < 0)
6874 return r;
6875
6876 break;
6877
6878 case ARG_SECTOR_SIZE:
6879 r = parse_sector_size(optarg, &arg_sector_size);
6880 if (r < 0)
6881 return r;
6882
6883 break;
6884
6885 case ARG_ARCHITECTURE:
6886 r = architecture_from_string(optarg);
6887 if (r < 0)
6888 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid architecture '%s'", optarg);
6889
6890 arg_architecture = r;
6891 break;
6892
6893 case ARG_OFFLINE:
6894 if (streq(optarg, "auto"))
6895 arg_offline = -1;
6896 else {
6897 r = parse_boolean_argument("--offline=", optarg, NULL);
6898 if (r < 0)
6899 return r;
6900
6901 arg_offline = r;
6902 }
6903
6904 break;
6905
6906 case ARG_COPY_FROM: {
6907 _cleanup_free_ char *p = NULL;
6908
6909 r = parse_path_argument(optarg, /* suppress_root= */ false, &p);
6910 if (r < 0)
6911 return r;
6912
6913 if (strv_consume(&arg_copy_from, TAKE_PTR(p)) < 0)
6914 return log_oom();
6915
6916 break;
6917 }
6918
6919 case 's':
6920 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_copy_source);
6921 if (r < 0)
6922 return r;
6923 break;
6924
6925 case ARG_MAKE_DDI:
6926 if (!filename_is_valid(optarg))
6927 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid DDI type: %s", optarg);
6928
6929 r = free_and_strdup_warn(&arg_make_ddi, optarg);
6930 if (r < 0)
6931 return r;
6932 break;
6933
6934 case 'S':
6935 r = free_and_strdup_warn(&arg_make_ddi, "sysext");
6936 if (r < 0)
6937 return r;
6938 break;
6939
6940 case 'C':
6941 r = free_and_strdup_warn(&arg_make_ddi, "confext");
6942 if (r < 0)
6943 return r;
6944 break;
6945
6946 case 'P':
6947 r = free_and_strdup_warn(&arg_make_ddi, "portable");
6948 if (r < 0)
6949 return r;
6950 break;
6951
6952 case '?':
6953 return -EINVAL;
6954
6955 default:
6956 assert_not_reached();
6957 }
6958
6959 if (argc - optind > 1)
6960 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6961 "Expected at most one argument, the path to the block device or image file.");
6962
6963 if (arg_make_ddi) {
6964 if (arg_definitions)
6965 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --definitions= is not supported.");
6966 if (!IN_SET(arg_empty, EMPTY_UNSET, EMPTY_CREATE))
6967 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --empty=%s is not supported.", empty_mode_to_string(arg_empty));
6968
6969 /* Imply automatic sizing in DDI mode */
6970 if (arg_size == UINT64_MAX)
6971 arg_size_auto = true;
6972
6973 if (!arg_copy_source)
6974 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --copy-source= specified, refusing.");
6975
6976 r = dir_is_empty(arg_copy_source, /* ignore_hidden_or_backup= */ false);
6977 if (r < 0)
6978 return log_error_errno(r, "Failed to determine if '%s' is empty: %m", arg_copy_source);
6979 if (r > 0)
6980 return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Source directory '%s' is empty, refusing to create empty image.", arg_copy_source);
6981
6982 if (sd_id128_is_null(arg_seed) && !arg_randomize) {
6983 /* We don't want that /etc/machine-id leaks into any image built this way, hence
6984 * let's randomize the seed if not specified explicitly */
6985 log_notice("No seed value specified, randomizing generated UUIDs, resulting image will not be reproducible.");
6986 arg_randomize = true;
6987 }
6988
6989 arg_empty = EMPTY_CREATE;
6990 }
6991
6992 if (arg_empty == EMPTY_UNSET) /* default to refuse mode, if not otherwise specified */
6993 arg_empty = EMPTY_REFUSE;
6994
6995 if (arg_factory_reset > 0 && IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE))
6996 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6997 "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
6998
6999 if (arg_can_factory_reset)
7000 arg_dry_run = true; /* When --can-factory-reset is specified we don't make changes, hence
7001 * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
7002 * open things strictly read-only. */
7003 else if (arg_empty == EMPTY_CREATE)
7004 arg_dry_run = false; /* Imply --dry-run=no if we create the loopback file anew. After all we
7005 * cannot really break anyone's partition tables that way. */
7006
7007 /* Disable pager once we are not just reviewing, but doing things. */
7008 if (!arg_dry_run)
7009 arg_pager_flags |= PAGER_DISABLE;
7010
7011 if (arg_empty == EMPTY_CREATE && arg_size == UINT64_MAX && !arg_size_auto)
7012 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7013 "If --empty=create is specified, --size= must be specified, too.");
7014
7015 if (arg_image && arg_root)
7016 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
7017 else if (!arg_image && !arg_root && in_initrd()) {
7018
7019 /* By default operate on /sysusr/ or /sysroot/ when invoked in the initrd. We prefer the
7020 * former, if it is mounted, so that we have deterministic behaviour on systems where /usr/
7021 * is vendor-supplied but the root fs formatted on first boot. */
7022 r = path_is_mount_point("/sysusr/usr", NULL, 0);
7023 if (r <= 0) {
7024 if (r < 0 && r != -ENOENT)
7025 log_debug_errno(r, "Unable to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
7026
7027 arg_root = strdup("/sysroot");
7028 } else
7029 arg_root = strdup("/sysusr");
7030 if (!arg_root)
7031 return log_oom();
7032 }
7033
7034 arg_node = argc > optind ? argv[optind] : NULL;
7035
7036 if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node && !arg_image)
7037 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7038 "A path to a device node or image file must be specified when --make-ddi=, --empty=force, --empty=require or --empty=create are used.");
7039
7040 if (arg_split && !arg_node)
7041 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7042 "A path to an image file must be specified when --split is used.");
7043
7044 if (auto_pcrlock) {
7045 assert(!arg_tpm2_pcrlock);
7046
7047 r = tpm2_pcrlock_search_file(NULL, NULL, &arg_tpm2_pcrlock);
7048 if (r < 0) {
7049 if (r != -ENOENT)
7050 log_warning_errno(r, "Search for pcrlock.json failed, assuming it does not exist: %m");
7051 } else
7052 log_debug("Automatically using pcrlock policy '%s'.", arg_tpm2_pcrlock);
7053 }
7054
7055 if (auto_public_key_pcr_mask) {
7056 assert(arg_tpm2_public_key_pcr_mask == 0);
7057 arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
7058 }
7059
7060 if (auto_hash_pcr_values && !arg_tpm2_pcrlock) { /* Only lock to PCR 7 if no pcr policy is specified. */
7061 assert(arg_tpm2_n_hash_pcr_values == 0);
7062
7063 if (!GREEDY_REALLOC_APPEND(
7064 arg_tpm2_hash_pcr_values,
7065 arg_tpm2_n_hash_pcr_values,
7066 &TPM2_PCR_VALUE_MAKE(TPM2_PCR_INDEX_DEFAULT, /* hash= */ 0, /* value= */ {}),
7067 1))
7068 return log_oom();
7069 }
7070
7071 if (arg_pretty < 0 && isatty(STDOUT_FILENO))
7072 arg_pretty = true;
7073
7074 if (arg_architecture >= 0) {
7075 FOREACH_ARRAY(p, arg_filter_partitions, arg_n_filter_partitions)
7076 *p = gpt_partition_type_override_architecture(*p, arg_architecture);
7077
7078 FOREACH_ARRAY(p, arg_defer_partitions, arg_n_defer_partitions)
7079 *p = gpt_partition_type_override_architecture(*p, arg_architecture);
7080 }
7081
7082 return 1;
7083 }
7084
7085 static int parse_proc_cmdline_factory_reset(void) {
7086 bool b;
7087 int r;
7088
7089 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
7090 return 0;
7091
7092 if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
7093 return 0;
7094
7095 r = proc_cmdline_get_bool("systemd.factory_reset", /* flags = */ 0, &b);
7096 if (r < 0)
7097 return log_error_errno(r, "Failed to parse systemd.factory_reset kernel command line argument: %m");
7098 if (r > 0) {
7099 arg_factory_reset = b;
7100
7101 if (b)
7102 log_notice("Honouring factory reset requested via kernel command line.");
7103 }
7104
7105 return 0;
7106 }
7107
7108 static int parse_efi_variable_factory_reset(void) {
7109 _cleanup_free_ char *value = NULL;
7110 int r;
7111
7112 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
7113 return 0;
7114
7115 if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
7116 return 0;
7117
7118 r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(FactoryReset), &value);
7119 if (r < 0) {
7120 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
7121 return 0;
7122 return log_error_errno(r, "Failed to read EFI variable FactoryReset: %m");
7123 }
7124
7125 r = parse_boolean(value);
7126 if (r < 0)
7127 return log_error_errno(r, "Failed to parse EFI variable FactoryReset: %m");
7128
7129 arg_factory_reset = r;
7130 if (r)
7131 log_notice("Factory reset requested via EFI variable FactoryReset.");
7132
7133 return 0;
7134 }
7135
7136 static int remove_efi_variable_factory_reset(void) {
7137 int r;
7138
7139 r = efi_set_variable(EFI_SYSTEMD_VARIABLE(FactoryReset), NULL, 0);
7140 if (r < 0) {
7141 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
7142 return 0;
7143 return log_error_errno(r, "Failed to remove EFI variable FactoryReset: %m");
7144 }
7145
7146 log_info("Successfully unset EFI variable FactoryReset.");
7147 return 0;
7148 }
7149
7150 static int acquire_root_devno(
7151 const char *p,
7152 const char *root,
7153 int mode,
7154 char **ret,
7155 int *ret_fd) {
7156
7157 _cleanup_free_ char *found_path = NULL, *node = NULL;
7158 dev_t devno, fd_devno = MODE_INVALID;
7159 _cleanup_close_ int fd = -EBADF;
7160 struct stat st;
7161 int r;
7162
7163 assert(p);
7164 assert(ret);
7165 assert(ret_fd);
7166
7167 fd = chase_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
7168 if (fd < 0)
7169 return fd;
7170
7171 if (fstat(fd, &st) < 0)
7172 return -errno;
7173
7174 if (S_ISREG(st.st_mode)) {
7175 *ret = TAKE_PTR(found_path);
7176 *ret_fd = TAKE_FD(fd);
7177 return 0;
7178 }
7179
7180 if (S_ISBLK(st.st_mode)) {
7181 /* Refuse referencing explicit block devices if a root dir is specified, after all we should
7182 * not be able to leave the image the root path constrains us to. */
7183 if (root)
7184 return -EPERM;
7185
7186 fd_devno = devno = st.st_rdev;
7187 } else if (S_ISDIR(st.st_mode)) {
7188
7189 devno = st.st_dev;
7190 if (major(devno) == 0) {
7191 r = btrfs_get_block_device_fd(fd, &devno);
7192 if (r == -ENOTTY) /* not btrfs */
7193 return -ENODEV;
7194 if (r < 0)
7195 return r;
7196 }
7197 } else
7198 return -ENOTBLK;
7199
7200 /* From dm-crypt to backing partition */
7201 r = block_get_originating(devno, &devno);
7202 if (r == -ENOENT)
7203 log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
7204 else if (r < 0)
7205 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
7206
7207 /* From partition to whole disk containing it */
7208 r = block_get_whole_disk(devno, &devno);
7209 if (r < 0)
7210 log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
7211
7212 r = devname_from_devnum(S_IFBLK, devno, &node);
7213 if (r < 0)
7214 return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
7215
7216 /* Only if we still look at the same block device we can reuse the fd. Otherwise return an
7217 * invalidated fd. */
7218 if (fd_devno != MODE_INVALID && fd_devno == devno) {
7219 /* Tell udev not to interfere while we are processing the device */
7220 if (flock(fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
7221 return log_error_errno(errno, "Failed to lock device '%s': %m", node);
7222
7223 *ret_fd = TAKE_FD(fd);
7224 } else
7225 *ret_fd = -EBADF;
7226
7227 *ret = TAKE_PTR(node);
7228 return 0;
7229 }
7230
7231 static int find_root(Context *context) {
7232 _cleanup_free_ char *device = NULL;
7233 int r;
7234
7235 assert(context);
7236
7237 if (arg_node) {
7238 if (arg_empty == EMPTY_CREATE) {
7239 _cleanup_close_ int fd = -EBADF;
7240 _cleanup_free_ char *s = NULL;
7241
7242 s = strdup(arg_node);
7243 if (!s)
7244 return log_oom();
7245
7246 fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
7247 if (fd < 0)
7248 return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
7249
7250 context->node = TAKE_PTR(s);
7251 context->node_is_our_file = true;
7252 context->backing_fd = TAKE_FD(fd);
7253 return 0;
7254 }
7255
7256 /* Note that we don't specify a root argument here: if the user explicitly configured a node
7257 * we'll take it relative to the host, not the image */
7258 r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
7259 if (r == -EUCLEAN)
7260 return btrfs_log_dev_root(LOG_ERR, r, arg_node);
7261 if (r < 0)
7262 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node);
7263
7264 return 0;
7265 }
7266
7267 assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
7268
7269 /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
7270 * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
7271 * here. */
7272 r = readlink_malloc("/run/systemd/volatile-root", &device);
7273 if (r == -ENOENT) { /* volatile-root not found */
7274 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
7275 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
7276 * (think: volatile setups) */
7277
7278 FOREACH_STRING(p, "/", "/usr") {
7279
7280 r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, &context->node,
7281 &context->backing_fd);
7282 if (r < 0) {
7283 if (r == -EUCLEAN)
7284 return btrfs_log_dev_root(LOG_ERR, r, p);
7285 if (r != -ENODEV)
7286 return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
7287 } else
7288 return 0;
7289 }
7290 } else if (r < 0)
7291 return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
7292 else {
7293 r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
7294 if (r == -EUCLEAN)
7295 return btrfs_log_dev_root(LOG_ERR, r, device);
7296 if (r < 0)
7297 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", device);
7298
7299 return 0;
7300 }
7301
7302 return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
7303 }
7304
7305 static int resize_pt(int fd, uint64_t sector_size) {
7306 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
7307 int r;
7308
7309 /* After resizing the backing file we need to resize the partition table itself too, so that it takes
7310 * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
7311 * immediately write it again, with no changes. */
7312
7313 r = fdisk_new_context_at(fd, /* path= */ NULL, /* read_only= */ false, sector_size, &c);
7314 if (r < 0)
7315 return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
7316
7317 r = fdisk_has_label(c);
7318 if (r < 0)
7319 return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd));
7320 if (r == 0) {
7321 log_debug("Not resizing partition table, as there currently is none.");
7322 return 0;
7323 }
7324
7325 r = fdisk_write_disklabel(c);
7326 if (r < 0)
7327 return log_error_errno(r, "Failed to write resized partition table: %m");
7328
7329 log_info("Resized partition table.");
7330 return 1;
7331 }
7332
7333 static int resize_backing_fd(
7334 const char *node, /* The primary way we access the disk image to operate on */
7335 int *fd, /* An O_RDONLY fd referring to that inode */
7336 const char *backing_file, /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
7337 LoopDevice *loop_device,
7338 uint64_t sector_size) {
7339
7340 _cleanup_close_ int writable_fd = -EBADF;
7341 uint64_t current_size;
7342 struct stat st;
7343 int r;
7344
7345 assert(node);
7346 assert(fd);
7347
7348 if (arg_size == UINT64_MAX) /* Nothing to do */
7349 return 0;
7350
7351 if (*fd < 0) {
7352 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
7353 * keep a reference to the file we can pass around. */
7354 *fd = open(node, O_RDONLY|O_CLOEXEC);
7355 if (*fd < 0)
7356 return log_error_errno(errno, "Failed to open '%s' in order to adjust size: %m", node);
7357 }
7358
7359 if (fstat(*fd, &st) < 0)
7360 return log_error_errno(errno, "Failed to stat '%s': %m", node);
7361
7362 if (S_ISBLK(st.st_mode)) {
7363 if (!backing_file)
7364 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot resize block device '%s'.", node);
7365
7366 assert(loop_device);
7367
7368 r = blockdev_get_device_size(*fd, &current_size);
7369 if (r < 0)
7370 return log_error_errno(r, "Failed to determine size of block device %s: %m", node);
7371 } else {
7372 r = stat_verify_regular(&st);
7373 if (r < 0)
7374 return log_error_errno(r, "Specified path '%s' is not a regular file or loopback block device, cannot resize: %m", node);
7375
7376 assert(!backing_file);
7377 assert(!loop_device);
7378 current_size = st.st_size;
7379 }
7380
7381 if (current_size >= arg_size) {
7382 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)",
7383 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7384 return 0;
7385 }
7386
7387 if (S_ISBLK(st.st_mode)) {
7388 assert(backing_file);
7389
7390 /* This is a loopback device. We can't really grow those directly, but we can grow the
7391 * backing file, hence let's do that. */
7392
7393 writable_fd = open(backing_file, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
7394 if (writable_fd < 0)
7395 return log_error_errno(errno, "Failed to open backing file '%s': %m", backing_file);
7396
7397 if (fstat(writable_fd, &st) < 0)
7398 return log_error_errno(errno, "Failed to stat() backing file '%s': %m", backing_file);
7399
7400 r = stat_verify_regular(&st);
7401 if (r < 0)
7402 return log_error_errno(r, "Backing file '%s' of block device is not a regular file: %m", backing_file);
7403
7404 if ((uint64_t) st.st_size != current_size)
7405 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7406 "Size of backing file '%s' of loopback block device '%s' don't match, refusing.",
7407 node, backing_file);
7408 } else {
7409 assert(S_ISREG(st.st_mode));
7410 assert(!backing_file);
7411
7412 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
7413 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
7414 * as fdisk can't accept it anyway. */
7415
7416 writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
7417 if (writable_fd < 0)
7418 return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
7419 }
7420
7421 if (!arg_discard) {
7422 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
7423 if (!ERRNO_IS_NOT_SUPPORTED(errno))
7424 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by allocation: %m",
7425 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7426
7427 /* Fallback to truncation, if fallocate() is not supported. */
7428 log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
7429 } else {
7430 if (current_size == 0) /* Likely regular file just created by us */
7431 log_info("Allocated %s for '%s'.", FORMAT_BYTES(arg_size), node);
7432 else
7433 log_info("File '%s' grown from %s to %s by allocation.",
7434 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7435
7436 goto done;
7437 }
7438 }
7439
7440 if (ftruncate(writable_fd, arg_size) < 0)
7441 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
7442 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7443
7444 if (current_size == 0) /* Likely regular file just created by us */
7445 log_info("Sized '%s' to %s.", node, FORMAT_BYTES(arg_size));
7446 else
7447 log_info("File '%s' grown from %s to %s by truncation.",
7448 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7449
7450 done:
7451 r = resize_pt(writable_fd, sector_size);
7452 if (r < 0)
7453 return r;
7454
7455 if (loop_device) {
7456 r = loop_device_refresh_size(loop_device, UINT64_MAX, arg_size);
7457 if (r < 0)
7458 return log_error_errno(r, "Failed to update loop device size: %m");
7459 }
7460
7461 return 1;
7462 }
7463
7464 static int determine_auto_size(Context *c) {
7465 uint64_t sum;
7466
7467 assert(c);
7468
7469 sum = round_up_size(GPT_METADATA_SIZE, 4096);
7470
7471 LIST_FOREACH(partitions, p, c->partitions) {
7472 uint64_t m;
7473
7474 if (p->dropped)
7475 continue;
7476
7477 m = partition_min_size_with_padding(c, p);
7478 if (m > UINT64_MAX - sum)
7479 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Image would grow too large, refusing.");
7480
7481 sum += m;
7482 }
7483
7484 if (c->total != UINT64_MAX)
7485 /* Image already allocated? Then show its size. */
7486 log_info("Automatically determined minimal disk image size as %s, current image size is %s.",
7487 FORMAT_BYTES(sum), FORMAT_BYTES(c->total));
7488 else
7489 /* If the image is being created right now, then it has no previous size, suppress any comment about it hence. */
7490 log_info("Automatically determined minimal disk image size as %s.",
7491 FORMAT_BYTES(sum));
7492
7493 arg_size = sum;
7494 return 0;
7495 }
7496
7497 static int run(int argc, char *argv[]) {
7498 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
7499 _cleanup_(umount_and_freep) char *mounted_dir = NULL;
7500 _cleanup_(context_freep) Context* context = NULL;
7501 bool node_is_our_loop = false;
7502 int r;
7503
7504 log_show_color(true);
7505 log_parse_environment();
7506 log_open();
7507
7508 r = parse_argv(argc, argv);
7509 if (r <= 0)
7510 return r;
7511
7512 r = parse_proc_cmdline_factory_reset();
7513 if (r < 0)
7514 return r;
7515
7516 r = parse_efi_variable_factory_reset();
7517 if (r < 0)
7518 return r;
7519
7520 #if HAVE_LIBCRYPTSETUP
7521 cryptsetup_enable_logging(NULL);
7522 #endif
7523
7524 if (arg_image) {
7525 assert(!arg_root);
7526
7527 /* Mount this strictly read-only: we shall modify the partition table, not the file
7528 * systems */
7529 r = mount_image_privately_interactively(
7530 arg_image,
7531 arg_image_policy,
7532 DISSECT_IMAGE_MOUNT_READ_ONLY |
7533 (arg_node ? DISSECT_IMAGE_DEVICE_READ_ONLY : 0) | /* If a different node to make changes to is specified let's open the device in read-only mode) */
7534 DISSECT_IMAGE_GPT_ONLY |
7535 DISSECT_IMAGE_RELAX_VAR_CHECK |
7536 DISSECT_IMAGE_USR_NO_ROOT |
7537 DISSECT_IMAGE_REQUIRE_ROOT,
7538 &mounted_dir,
7539 /* ret_dir_fd= */ NULL,
7540 &loop_device);
7541 if (r < 0)
7542 return r;
7543
7544 arg_root = strdup(mounted_dir);
7545 if (!arg_root)
7546 return log_oom();
7547
7548 if (!arg_node) {
7549 arg_node = strdup(loop_device->node);
7550 if (!arg_node)
7551 return log_oom();
7552
7553 /* Remember that the device we are about to manipulate is actually the one we
7554 * allocated here, and thus to increase its backing file we know what to do */
7555 node_is_our_loop = true;
7556 }
7557 }
7558
7559 if (!arg_copy_source && arg_root) {
7560 /* If no explicit copy source is specified, then use --root=/--image= */
7561 arg_copy_source = strdup(arg_root);
7562 if (!arg_copy_source)
7563 return log_oom();
7564 }
7565
7566 context = context_new(arg_seed);
7567 if (!context)
7568 return log_oom();
7569
7570 r = context_copy_from(context);
7571 if (r < 0)
7572 return r;
7573
7574 if (arg_make_ddi) {
7575 _cleanup_free_ char *d = NULL, *dp = NULL;
7576 assert(!arg_definitions);
7577
7578 d = strjoin(arg_make_ddi, ".repart.d/");
7579 if (!d)
7580 return log_oom();
7581
7582 r = search_and_access(d, F_OK, NULL, CONF_PATHS_USR_STRV("systemd/repart/definitions"), &dp);
7583 if (r < 0)
7584 return log_error_errno(r, "DDI type '%s' is not defined: %m", arg_make_ddi);
7585
7586 if (strv_consume(&arg_definitions, TAKE_PTR(dp)) < 0)
7587 return log_oom();
7588 } else
7589 strv_uniq(arg_definitions);
7590
7591 r = context_read_definitions(context);
7592 if (r < 0)
7593 return r;
7594
7595 r = find_root(context);
7596 if (r == -ENODEV)
7597 return 76; /* Special return value which means "Root block device not found, so not doing
7598 * anything". This isn't really an error when called at boot. */
7599 if (r < 0)
7600 return r;
7601
7602 if (arg_size != UINT64_MAX) {
7603 r = resize_backing_fd(
7604 context->node,
7605 &context->backing_fd,
7606 node_is_our_loop ? arg_image : NULL,
7607 node_is_our_loop ? loop_device : NULL,
7608 context->sector_size);
7609 if (r < 0)
7610 return r;
7611 }
7612
7613 r = context_load_partition_table(context);
7614 if (r == -EHWPOISON)
7615 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
7616 * really an error when called at boot. */
7617 if (r < 0)
7618 return r;
7619 context->from_scratch = r > 0; /* Starting from scratch */
7620
7621 if (arg_can_factory_reset) {
7622 r = context_can_factory_reset(context);
7623 if (r < 0)
7624 return r;
7625 if (r == 0)
7626 return EXIT_FAILURE;
7627
7628 return 0;
7629 }
7630
7631 r = context_factory_reset(context);
7632 if (r < 0)
7633 return r;
7634 if (r > 0) {
7635 /* We actually did a factory reset! */
7636 r = remove_efi_variable_factory_reset();
7637 if (r < 0)
7638 return r;
7639
7640 /* Reload the reduced partition table */
7641 context_unload_partition_table(context);
7642 r = context_load_partition_table(context);
7643 if (r < 0)
7644 return r;
7645 }
7646
7647 r = context_read_seed(context, arg_root);
7648 if (r < 0)
7649 return r;
7650
7651 /* Make sure each partition has a unique UUID and unique label */
7652 r = context_acquire_partition_uuids_and_labels(context);
7653 if (r < 0)
7654 return r;
7655
7656 /* Open all files to copy blocks from now, since we want to take their size into consideration */
7657 r = context_open_copy_block_paths(
7658 context,
7659 loop_device ? loop_device->devno : /* if --image= is specified, only allow partitions on the loopback device */
7660 arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
7661 (dev_t) -1); /* if neither is specified, make no restrictions */
7662 if (r < 0)
7663 return r;
7664
7665 r = context_minimize(context);
7666 if (r < 0)
7667 return r;
7668
7669 if (arg_size_auto) {
7670 r = determine_auto_size(context);
7671 if (r < 0)
7672 return r;
7673
7674 /* Flush out everything again, and let's grow the file first, then start fresh */
7675 context_unload_partition_table(context);
7676
7677 assert(arg_size != UINT64_MAX);
7678 r = resize_backing_fd(
7679 context->node,
7680 &context->backing_fd,
7681 node_is_our_loop ? arg_image : NULL,
7682 node_is_our_loop ? loop_device : NULL,
7683 context->sector_size);
7684 if (r < 0)
7685 return r;
7686
7687 r = context_load_partition_table(context);
7688 if (r < 0)
7689 return r;
7690 }
7691
7692 /* First try to fit new partitions in, dropping by priority until it fits */
7693 for (;;) {
7694 uint64_t largest_free_area;
7695
7696 if (context_allocate_partitions(context, &largest_free_area))
7697 break; /* Success! */
7698
7699 if (!context_drop_or_foreignize_one_priority(context)) {
7700 r = log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
7701 "Can't fit requested partitions into available free space (%s), refusing.",
7702 FORMAT_BYTES(largest_free_area));
7703 determine_auto_size(context);
7704 return r;
7705 }
7706 }
7707
7708 /* Now assign free space according to the weight logic */
7709 r = context_grow_partitions(context);
7710 if (r < 0)
7711 return r;
7712
7713 /* Now calculate where each new partition gets placed */
7714 context_place_partitions(context);
7715
7716 (void) context_dump(context, /*late=*/ false);
7717
7718 r = context_write_partition_table(context);
7719 if (r < 0)
7720 return r;
7721
7722 r = context_split(context);
7723 if (r < 0)
7724 return r;
7725
7726 (void) context_dump(context, /*late=*/ true);
7727
7728 context->node = mfree(context->node);
7729
7730 LIST_FOREACH(partitions, p, context->partitions)
7731 p->split_path = mfree(p->split_path);
7732
7733 return 0;
7734 }
7735
7736 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);