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