]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/partition/repart.c
Merge pull request #30809 from yuwata/resolve-fix-EDE-handling
[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(context->node, arg_dry_run ? LOCK_SH : LOCK_EX,
2330 &context->backing_fd);
2331 if (r < 0)
2332 return r;
2333
2334 if (fstat(context->backing_fd, &st) < 0)
2335 return log_error_errno(errno, "Failed to stat %s: %m", context->node);
2336
2337 /* Auto-detect sector size if not specified. */
2338 r = probe_sector_size_prefer_ioctl(context->backing_fd, &ssz);
2339 if (r < 0)
2340 return log_error_errno(r, "Failed to probe sector size of '%s': %m", context->node);
2341
2342 /* If we found the sector size and we're operating on a block device, use it as the file
2343 * system sector size as well, as we know its the sector size of the actual block device and
2344 * not just the offset at which we found the GPT header. */
2345 if (r > 0 && S_ISBLK(st.st_mode))
2346 fs_secsz = ssz;
2347
2348 r = fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
2349 }
2350 if (r < 0)
2351 return log_error_errno(r, "Failed to set sector size: %m");
2352
2353 /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
2354 * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
2355 r = fdisk_assign_device(
2356 c,
2357 context->backing_fd >= 0 ? FORMAT_PROC_FD_PATH(context->backing_fd) : context->node,
2358 arg_dry_run);
2359 if (r == -EINVAL && arg_size_auto) {
2360 struct stat st;
2361
2362 /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept
2363 * it if automatic sizing is requested. */
2364
2365 if (context->backing_fd < 0)
2366 r = stat(context->node, &st);
2367 else
2368 r = fstat(context->backing_fd, &st);
2369 if (r < 0)
2370 return log_error_errno(errno, "Failed to stat block device '%s': %m", context->node);
2371
2372 if (S_ISREG(st.st_mode) && st.st_size == 0) {
2373 /* Use the fallback values if we have no better idea */
2374 context->sector_size = fdisk_get_sector_size(c);
2375 context->fs_sector_size = fs_secsz;
2376 context->grain_size = 4096;
2377 return /* from_scratch = */ true;
2378 }
2379
2380 r = -EINVAL;
2381 }
2382 if (r < 0)
2383 return log_error_errno(r, "Failed to open device '%s': %m", context->node);
2384
2385 if (context->backing_fd < 0) {
2386 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
2387 r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)),
2388 arg_dry_run ? LOCK_SH : LOCK_EX,
2389 &context->backing_fd);
2390 if (r < 0)
2391 return r;
2392 }
2393
2394 /* The offsets/sizes libfdisk returns to us will be in multiple of the sector size of the
2395 * device. This is typically 512, and sometimes 4096. Let's query libfdisk once for it, and then use
2396 * it for all our needs. Note that the values we use ourselves always are in bytes though, thus mean
2397 * the same thing universally. Also note that regardless what kind of sector size is in use we'll
2398 * place partitions at multiples of 4K. */
2399 secsz = fdisk_get_sector_size(c);
2400
2401 /* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
2402 if (secsz < 512 || !ISPOWEROF2(secsz))
2403 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
2404
2405 /* Use at least 4K, and ensure it's a multiple of the sector size, regardless if that is smaller or
2406 * larger */
2407 grainsz = secsz < 4096 ? 4096 : secsz;
2408
2409 log_debug("Sector size of device is %lu bytes. Using grain size of %" PRIu64 ".", secsz, grainsz);
2410
2411 switch (arg_empty) {
2412
2413 case EMPTY_REFUSE:
2414 /* Refuse empty disks, insist on an existing GPT partition table */
2415 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
2416 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", context->node);
2417
2418 break;
2419
2420 case EMPTY_REQUIRE:
2421 /* Require an empty disk, refuse any existing partition table */
2422 r = fdisk_has_label(c);
2423 if (r < 0)
2424 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
2425 if (r > 0)
2426 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", context->node);
2427
2428 from_scratch = true;
2429 break;
2430
2431 case EMPTY_ALLOW:
2432 /* Allow both an empty disk and an existing partition table, but only GPT */
2433 r = fdisk_has_label(c);
2434 if (r < 0)
2435 return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
2436 if (r > 0) {
2437 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
2438 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", context->node);
2439 } else
2440 from_scratch = true;
2441
2442 break;
2443
2444 case EMPTY_FORCE:
2445 case EMPTY_CREATE:
2446 /* Always reinitiaize the disk, don't consider what there was on the disk before */
2447 from_scratch = true;
2448 break;
2449
2450 default:
2451 assert_not_reached();
2452 }
2453
2454 if (from_scratch) {
2455 r = fdisk_create_disklabel(c, "gpt");
2456 if (r < 0)
2457 return log_error_errno(r, "Failed to create GPT disk label: %m");
2458
2459 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
2460 if (r < 0)
2461 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
2462
2463 r = fdisk_set_disklabel_id_by_uuid(c, disk_uuid);
2464 if (r < 0)
2465 return log_error_errno(r, "Failed to set GPT disk label: %m");
2466
2467 goto add_initial_free_area;
2468 }
2469
2470 r = fdisk_get_disklabel_id(c, &disk_uuid_string);
2471 if (r < 0)
2472 return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
2473
2474 r = id128_from_string_nonzero(disk_uuid_string, &disk_uuid);
2475 if (r == -ENXIO) {
2476 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
2477 if (r < 0)
2478 return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
2479
2480 r = fdisk_set_disklabel_id(c);
2481 if (r < 0)
2482 return log_error_errno(r, "Failed to set GPT disk label: %m");
2483 } else if (r < 0)
2484 return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
2485
2486 r = fdisk_get_partitions(c, &t);
2487 if (r < 0)
2488 return log_error_errno(r, "Failed to acquire partition table: %m");
2489
2490 n_partitions = fdisk_table_get_nents(t);
2491 for (size_t i = 0; i < n_partitions; i++) {
2492 _cleanup_free_ char *label_copy = NULL;
2493 Partition *last = NULL;
2494 struct fdisk_partition *p;
2495 const char *label;
2496 uint64_t sz, start;
2497 bool found = false;
2498 sd_id128_t ptid, id;
2499 size_t partno;
2500
2501 p = fdisk_table_get_partition(t, i);
2502 if (!p)
2503 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
2504
2505 if (fdisk_partition_is_used(p) <= 0)
2506 continue;
2507
2508 if (fdisk_partition_has_start(p) <= 0 ||
2509 fdisk_partition_has_size(p) <= 0 ||
2510 fdisk_partition_has_partno(p) <= 0)
2511 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
2512
2513 r = fdisk_partition_get_type_as_id128(p, &ptid);
2514 if (r < 0)
2515 return log_error_errno(r, "Failed to query partition type UUID: %m");
2516
2517 r = fdisk_partition_get_uuid_as_id128(p, &id);
2518 if (r < 0)
2519 return log_error_errno(r, "Failed to query partition UUID: %m");
2520
2521 label = fdisk_partition_get_name(p);
2522 if (!isempty(label)) {
2523 label_copy = strdup(label);
2524 if (!label_copy)
2525 return log_oom();
2526 }
2527
2528 sz = fdisk_partition_get_size(p);
2529 assert(sz <= UINT64_MAX/secsz);
2530 sz *= secsz;
2531
2532 start = fdisk_partition_get_start(p);
2533 assert(start <= UINT64_MAX/secsz);
2534 start *= secsz;
2535
2536 partno = fdisk_partition_get_partno(p);
2537
2538 if (left_boundary == UINT64_MAX || left_boundary > start)
2539 left_boundary = start;
2540
2541 /* Assign this existing partition to the first partition of the right type that doesn't have
2542 * an existing one assigned yet. */
2543 LIST_FOREACH(partitions, pp, context->partitions) {
2544 last = pp;
2545
2546 if (!sd_id128_equal(pp->type.uuid, ptid))
2547 continue;
2548
2549 if (!pp->current_partition) {
2550 pp->current_uuid = id;
2551 pp->current_size = sz;
2552 pp->offset = start;
2553 pp->partno = partno;
2554 pp->current_label = TAKE_PTR(label_copy);
2555
2556 pp->current_partition = p;
2557 fdisk_ref_partition(p);
2558
2559 r = determine_current_padding(c, t, p, secsz, grainsz, &pp->current_padding);
2560 if (r < 0)
2561 return r;
2562
2563 if (pp->current_padding > 0) {
2564 r = context_add_free_area(context, pp->current_padding, pp);
2565 if (r < 0)
2566 return r;
2567 }
2568
2569 found = true;
2570 break;
2571 }
2572 }
2573
2574 /* If we have no matching definition, create a new one. */
2575 if (!found) {
2576 _cleanup_(partition_freep) Partition *np = NULL;
2577
2578 np = partition_new();
2579 if (!np)
2580 return log_oom();
2581
2582 np->current_uuid = id;
2583 np->type = gpt_partition_type_from_uuid(ptid);
2584 np->current_size = sz;
2585 np->offset = start;
2586 np->partno = partno;
2587 np->current_label = TAKE_PTR(label_copy);
2588
2589 np->current_partition = p;
2590 fdisk_ref_partition(p);
2591
2592 r = determine_current_padding(c, t, p, secsz, grainsz, &np->current_padding);
2593 if (r < 0)
2594 return r;
2595
2596 if (np->current_padding > 0) {
2597 r = context_add_free_area(context, np->current_padding, np);
2598 if (r < 0)
2599 return r;
2600 }
2601
2602 LIST_INSERT_AFTER(partitions, context->partitions, last, TAKE_PTR(np));
2603 context->n_partitions++;
2604 }
2605 }
2606
2607 add_initial_free_area:
2608 nsectors = fdisk_get_nsectors(c);
2609 assert(nsectors <= UINT64_MAX/secsz);
2610 nsectors *= secsz;
2611
2612 first_lba = fdisk_get_first_lba(c);
2613 assert(first_lba <= UINT64_MAX/secsz);
2614 first_lba *= secsz;
2615
2616 last_lba = fdisk_get_last_lba(c);
2617 assert(last_lba < UINT64_MAX);
2618 last_lba++;
2619 assert(last_lba <= UINT64_MAX/secsz);
2620 last_lba *= secsz;
2621
2622 assert(last_lba >= first_lba);
2623
2624 if (left_boundary == UINT64_MAX) {
2625 /* No partitions at all? Then the whole disk is up for grabs. */
2626
2627 first_lba = round_up_size(first_lba, grainsz);
2628 last_lba = round_down_size(last_lba, grainsz);
2629
2630 if (last_lba > first_lba) {
2631 r = context_add_free_area(context, last_lba - first_lba, NULL);
2632 if (r < 0)
2633 return r;
2634 }
2635 } else {
2636 /* Add space left of first partition */
2637 assert(left_boundary >= first_lba);
2638
2639 first_lba = round_up_size(first_lba, grainsz);
2640 left_boundary = round_down_size(left_boundary, grainsz);
2641 last_lba = round_down_size(last_lba, grainsz);
2642
2643 if (left_boundary > first_lba) {
2644 r = context_add_free_area(context, left_boundary - first_lba, NULL);
2645 if (r < 0)
2646 return r;
2647 }
2648 }
2649
2650 context->start = first_lba;
2651 context->end = last_lba;
2652 context->total = nsectors;
2653 context->sector_size = secsz;
2654 context->fs_sector_size = fs_secsz;
2655 context->grain_size = grainsz;
2656 context->fdisk_context = TAKE_PTR(c);
2657
2658 return from_scratch;
2659 }
2660
2661 static void context_unload_partition_table(Context *context) {
2662 assert(context);
2663
2664 LIST_FOREACH(partitions, p, context->partitions) {
2665
2666 /* Entirely remove partitions that have no configuration */
2667 if (PARTITION_IS_FOREIGN(p)) {
2668 partition_unlink_and_free(context, p);
2669 continue;
2670 }
2671
2672 /* Otherwise drop all data we read off the block device and everything we might have
2673 * calculated based on it */
2674
2675 p->dropped = false;
2676 p->current_size = UINT64_MAX;
2677 p->new_size = UINT64_MAX;
2678 p->current_padding = UINT64_MAX;
2679 p->new_padding = UINT64_MAX;
2680 p->partno = UINT64_MAX;
2681 p->offset = UINT64_MAX;
2682
2683 if (p->current_partition) {
2684 fdisk_unref_partition(p->current_partition);
2685 p->current_partition = NULL;
2686 }
2687
2688 if (p->new_partition) {
2689 fdisk_unref_partition(p->new_partition);
2690 p->new_partition = NULL;
2691 }
2692
2693 p->padding_area = NULL;
2694 p->allocated_to_area = NULL;
2695
2696 p->current_uuid = SD_ID128_NULL;
2697 p->current_label = mfree(p->current_label);
2698 }
2699
2700 context->start = UINT64_MAX;
2701 context->end = UINT64_MAX;
2702 context->total = UINT64_MAX;
2703
2704 if (context->fdisk_context) {
2705 fdisk_unref_context(context->fdisk_context);
2706 context->fdisk_context = NULL;
2707 }
2708
2709 context_free_free_areas(context);
2710 }
2711
2712 static int format_size_change(uint64_t from, uint64_t to, char **ret) {
2713 char *t;
2714
2715 if (from != UINT64_MAX) {
2716 if (from == to || to == UINT64_MAX)
2717 t = strdup(FORMAT_BYTES(from));
2718 else
2719 t = strjoin(FORMAT_BYTES(from), " ", special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
2720 } else if (to != UINT64_MAX)
2721 t = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
2722 else {
2723 *ret = NULL;
2724 return 0;
2725 }
2726
2727 if (!t)
2728 return log_oom();
2729
2730 *ret = t;
2731 return 1;
2732 }
2733
2734 static const char *partition_label(const Partition *p) {
2735 assert(p);
2736
2737 if (p->new_label)
2738 return p->new_label;
2739
2740 if (p->current_label)
2741 return p->current_label;
2742
2743 return gpt_partition_type_uuid_to_string(p->type.uuid);
2744 }
2745
2746 static int context_dump_partitions(Context *context) {
2747 _cleanup_(table_unrefp) Table *t = NULL;
2748 uint64_t sum_padding = 0, sum_size = 0;
2749 int r;
2750 const size_t roothash_col = 14, dropin_files_col = 15, split_path_col = 16;
2751 bool has_roothash = false, has_dropin_files = false, has_split_path = false;
2752
2753 if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) {
2754 log_info("Empty partition table.");
2755 return 0;
2756 }
2757
2758 t = table_new("type",
2759 "label",
2760 "uuid",
2761 "partno",
2762 "file",
2763 "node",
2764 "offset",
2765 "old size",
2766 "raw size",
2767 "size",
2768 "old padding",
2769 "raw padding",
2770 "padding",
2771 "activity",
2772 "roothash",
2773 "drop-in files",
2774 "split path");
2775 if (!t)
2776 return log_oom();
2777
2778 if (!DEBUG_LOGGING) {
2779 if (arg_json_format_flags & JSON_FORMAT_OFF)
2780 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2781 (size_t) 8, (size_t) 9, (size_t) 12, roothash_col, dropin_files_col,
2782 split_path_col);
2783 else
2784 (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2785 (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 8, (size_t) 10,
2786 (size_t) 11, (size_t) 13, roothash_col, dropin_files_col,
2787 split_path_col);
2788 }
2789
2790 (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
2791 (void) table_set_align_percent(t, table_get_cell(t, 0, 6), 100);
2792 (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100);
2793 (void) table_set_align_percent(t, table_get_cell(t, 0, 8), 100);
2794 (void) table_set_align_percent(t, table_get_cell(t, 0, 9), 100);
2795 (void) table_set_align_percent(t, table_get_cell(t, 0, 10), 100);
2796 (void) table_set_align_percent(t, table_get_cell(t, 0, 11), 100);
2797
2798 LIST_FOREACH(partitions, p, context->partitions) {
2799 _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL, *rh = NULL;
2800 char uuid_buffer[SD_ID128_UUID_STRING_MAX];
2801 const char *label, *activity = NULL;
2802
2803 if (p->dropped)
2804 continue;
2805
2806 if (p->current_size == UINT64_MAX)
2807 activity = "create";
2808 else if (p->current_size != p->new_size)
2809 activity = "resize";
2810
2811 label = partition_label(p);
2812 partname = p->partno != UINT64_MAX ? fdisk_partname(context->node, p->partno+1) : NULL;
2813
2814 r = format_size_change(p->current_size, p->new_size, &size_change);
2815 if (r < 0)
2816 return r;
2817
2818 r = format_size_change(p->current_padding, p->new_padding, &padding_change);
2819 if (r < 0)
2820 return r;
2821
2822 if (p->new_size != UINT64_MAX)
2823 sum_size += p->new_size;
2824 if (p->new_padding != UINT64_MAX)
2825 sum_padding += p->new_padding;
2826
2827 if (p->verity != VERITY_OFF) {
2828 Partition *hp = p->verity == VERITY_HASH ? p : p->siblings[VERITY_HASH];
2829
2830 rh = iovec_is_set(&hp->roothash) ? hexmem(hp->roothash.iov_base, hp->roothash.iov_len) : strdup("TBD");
2831 if (!rh)
2832 return log_oom();
2833 }
2834
2835 r = table_add_many(
2836 t,
2837 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type.uuid, uuid_buffer),
2838 TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
2839 TABLE_UUID, p->new_uuid_is_set ? p->new_uuid : p->current_uuid,
2840 TABLE_UINT64, p->partno,
2841 TABLE_PATH_BASENAME, p->definition_path, TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
2842 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
2843 TABLE_UINT64, p->offset,
2844 TABLE_UINT64, p->current_size == UINT64_MAX ? 0 : p->current_size,
2845 TABLE_UINT64, p->new_size,
2846 TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL,
2847 TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding,
2848 TABLE_UINT64, p->new_padding,
2849 TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL,
2850 TABLE_STRING, activity ?: "unchanged",
2851 TABLE_STRING, rh,
2852 TABLE_STRV, p->drop_in_files,
2853 TABLE_STRING, empty_to_null(p->split_path) ?: "-");
2854 if (r < 0)
2855 return table_log_add_error(r);
2856
2857 has_roothash = has_roothash || !isempty(rh);
2858 has_dropin_files = has_dropin_files || !strv_isempty(p->drop_in_files);
2859 has_split_path = has_split_path || !isempty(p->split_path);
2860 }
2861
2862 if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) {
2863 const char *a, *b;
2864
2865 a = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_size));
2866 b = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_padding));
2867
2868 r = table_add_many(
2869 t,
2870 TABLE_EMPTY,
2871 TABLE_EMPTY,
2872 TABLE_EMPTY,
2873 TABLE_EMPTY,
2874 TABLE_EMPTY,
2875 TABLE_EMPTY,
2876 TABLE_EMPTY,
2877 TABLE_EMPTY,
2878 TABLE_EMPTY,
2879 TABLE_STRING, a,
2880 TABLE_EMPTY,
2881 TABLE_EMPTY,
2882 TABLE_STRING, b,
2883 TABLE_EMPTY,
2884 TABLE_EMPTY,
2885 TABLE_EMPTY,
2886 TABLE_EMPTY);
2887 if (r < 0)
2888 return table_log_add_error(r);
2889 }
2890
2891 if (!has_roothash) {
2892 r = table_hide_column_from_display(t, roothash_col);
2893 if (r < 0)
2894 return log_error_errno(r, "Failed to set columns to display: %m");
2895 }
2896
2897 if (!has_dropin_files) {
2898 r = table_hide_column_from_display(t, dropin_files_col);
2899 if (r < 0)
2900 return log_error_errno(r, "Failed to set columns to display: %m");
2901 }
2902
2903 if (!has_split_path) {
2904 r = table_hide_column_from_display(t, split_path_col);
2905 if (r < 0)
2906 return log_error_errno(r, "Failed to set columns to display: %m");
2907 }
2908
2909 return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
2910 }
2911
2912 static int context_bar_char_process_partition(
2913 Context *context,
2914 Partition *bar[],
2915 size_t n,
2916 Partition *p,
2917 size_t **start_array,
2918 size_t *n_start_array) {
2919
2920 uint64_t from, to, total;
2921 size_t x, y;
2922
2923 assert(context);
2924 assert(bar);
2925 assert(n > 0);
2926 assert(p);
2927 assert(start_array);
2928 assert(n_start_array);
2929
2930 if (p->dropped)
2931 return 0;
2932
2933 assert(p->offset != UINT64_MAX);
2934 assert(p->new_size != UINT64_MAX);
2935
2936 from = p->offset;
2937 to = from + p->new_size;
2938
2939 assert(context->total > 0);
2940 total = context->total;
2941
2942 assert(from <= total);
2943 x = from * n / total;
2944
2945 assert(to <= total);
2946 y = to * n / total;
2947
2948 assert(x <= y);
2949 assert(y <= n);
2950
2951 for (size_t i = x; i < y; i++)
2952 bar[i] = p;
2953
2954 if (!GREEDY_REALLOC_APPEND(*start_array, *n_start_array, &x, 1))
2955 return log_oom();
2956
2957 return 1;
2958 }
2959
2960 static int partition_hint(const Partition *p, const char *node, char **ret) {
2961 _cleanup_free_ char *buf = NULL;
2962 const char *label;
2963 sd_id128_t id;
2964
2965 /* Tries really hard to find a suitable description for this partition */
2966
2967 if (p->definition_path)
2968 return path_extract_filename(p->definition_path, ret);
2969
2970 label = partition_label(p);
2971 if (!isempty(label)) {
2972 buf = strdup(label);
2973 goto done;
2974 }
2975
2976 if (p->partno != UINT64_MAX) {
2977 buf = fdisk_partname(node, p->partno+1);
2978 goto done;
2979 }
2980
2981 if (p->new_uuid_is_set)
2982 id = p->new_uuid;
2983 else if (!sd_id128_is_null(p->current_uuid))
2984 id = p->current_uuid;
2985 else
2986 id = p->type.uuid;
2987
2988 buf = strdup(SD_ID128_TO_UUID_STRING(id));
2989
2990 done:
2991 if (!buf)
2992 return -ENOMEM;
2993
2994 *ret = TAKE_PTR(buf);
2995 return 0;
2996 }
2997
2998 static int context_dump_partition_bar(Context *context) {
2999 _cleanup_free_ Partition **bar = NULL;
3000 _cleanup_free_ size_t *start_array = NULL;
3001 size_t n_start_array = 0;
3002 Partition *last = NULL;
3003 bool z = false;
3004 size_t c, j = 0;
3005 int r;
3006
3007 assert_se((c = columns()) >= 2);
3008 c -= 2; /* We do not use the leftmost and rightmost character cell */
3009
3010 bar = new0(Partition*, c);
3011 if (!bar)
3012 return log_oom();
3013
3014 LIST_FOREACH(partitions, p, context->partitions) {
3015 r = context_bar_char_process_partition(context, bar, c, p, &start_array, &n_start_array);
3016 if (r < 0)
3017 return r;
3018 }
3019
3020 putc(' ', stdout);
3021
3022 for (size_t i = 0; i < c; i++) {
3023 if (bar[i]) {
3024 if (last != bar[i])
3025 z = !z;
3026
3027 fputs(z ? ansi_green() : ansi_yellow(), stdout);
3028 fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE), stdout);
3029 } else {
3030 fputs(ansi_normal(), stdout);
3031 fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), stdout);
3032 }
3033
3034 last = bar[i];
3035 }
3036
3037 fputs(ansi_normal(), stdout);
3038 putc('\n', stdout);
3039
3040 for (size_t i = 0; i < n_start_array; i++) {
3041 _cleanup_free_ char **line = NULL;
3042
3043 line = new0(char*, c);
3044 if (!line)
3045 return log_oom();
3046
3047 j = 0;
3048 LIST_FOREACH(partitions, p, context->partitions) {
3049 _cleanup_free_ char *d = NULL;
3050
3051 if (p->dropped)
3052 continue;
3053
3054 j++;
3055
3056 if (i < n_start_array - j) {
3057
3058 if (line[start_array[j-1]]) {
3059 const char *e;
3060
3061 /* Upgrade final corner to the right with a branch to the right */
3062 e = startswith(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
3063 if (e) {
3064 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), e);
3065 if (!d)
3066 return log_oom();
3067 }
3068 }
3069
3070 if (!d) {
3071 d = strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
3072 if (!d)
3073 return log_oom();
3074 }
3075
3076 } else if (i == n_start_array - j) {
3077 _cleanup_free_ char *hint = NULL;
3078
3079 (void) partition_hint(p, context->node, &hint);
3080
3081 if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)))
3082 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint));
3083 else
3084 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT), " ", strna(hint));
3085
3086 if (!d)
3087 return log_oom();
3088 }
3089
3090 if (d)
3091 free_and_replace(line[start_array[j-1]], d);
3092 }
3093
3094 putc(' ', stdout);
3095
3096 j = 0;
3097 while (j < c) {
3098 if (line[j]) {
3099 fputs(line[j], stdout);
3100 j += utf8_console_width(line[j]);
3101 } else {
3102 putc(' ', stdout);
3103 j++;
3104 }
3105 }
3106
3107 putc('\n', stdout);
3108
3109 for (j = 0; j < c; j++)
3110 free(line[j]);
3111 }
3112
3113 return 0;
3114 }
3115
3116 static bool context_has_roothash(Context *context) {
3117 LIST_FOREACH(partitions, p, context->partitions)
3118 if (iovec_is_set(&p->roothash))
3119 return true;
3120
3121 return false;
3122 }
3123
3124 static int context_dump(Context *context, bool late) {
3125 int r;
3126
3127 assert(context);
3128
3129 if (arg_pretty == 0 && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
3130 return 0;
3131
3132 /* If we're outputting JSON, only dump after doing all operations so we can include the roothashes
3133 * in the output. */
3134 if (!late && !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
3135 return 0;
3136
3137 /* If we're not outputting JSON, only dump again after doing all operations if there are any
3138 * roothashes that we need to communicate to the user. */
3139 if (late && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !context_has_roothash(context))
3140 return 0;
3141
3142 r = context_dump_partitions(context);
3143 if (r < 0)
3144 return r;
3145
3146 /* Make sure we only write the partition bar once, even if we're writing the partition table twice to
3147 * communicate roothashes. */
3148 if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !late) {
3149 putc('\n', stdout);
3150
3151 r = context_dump_partition_bar(context);
3152 if (r < 0)
3153 return r;
3154
3155 putc('\n', stdout);
3156 }
3157
3158 fflush(stdout);
3159
3160 return 0;
3161 }
3162
3163
3164 static bool context_changed(const Context *context) {
3165 assert(context);
3166
3167 LIST_FOREACH(partitions, p, context->partitions) {
3168 if (p->dropped)
3169 continue;
3170
3171 if (p->allocated_to_area)
3172 return true;
3173
3174 if (p->new_size != p->current_size)
3175 return true;
3176 }
3177
3178 return false;
3179 }
3180
3181 static int context_wipe_range(Context *context, uint64_t offset, uint64_t size) {
3182 _cleanup_(blkid_free_probep) blkid_probe probe = NULL;
3183 int r;
3184
3185 assert(context);
3186 assert(offset != UINT64_MAX);
3187 assert(size != UINT64_MAX);
3188
3189 probe = blkid_new_probe();
3190 if (!probe)
3191 return log_oom();
3192
3193 errno = 0;
3194 r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size);
3195 if (r < 0)
3196 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping.");
3197
3198 errno = 0;
3199 if (blkid_probe_enable_superblocks(probe, true) < 0 ||
3200 blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 ||
3201 blkid_probe_enable_partitions(probe, true) < 0 ||
3202 blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0)
3203 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing.");
3204
3205 for (;;) {
3206 errno = 0;
3207 r = blkid_do_probe(probe);
3208 if (r < 0)
3209 return log_error_errno(errno_or_else(EIO), "Failed to probe for file systems.");
3210 if (r > 0)
3211 break;
3212
3213 errno = 0;
3214 if (blkid_do_wipe(probe, false) < 0)
3215 return log_error_errno(errno_or_else(EIO), "Failed to wipe file system signature.");
3216 }
3217
3218 return 0;
3219 }
3220
3221 static int context_wipe_partition(Context *context, Partition *p) {
3222 int r;
3223
3224 assert(context);
3225 assert(p);
3226 assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */
3227
3228 assert(p->offset != UINT64_MAX);
3229 assert(p->new_size != UINT64_MAX);
3230
3231 r = context_wipe_range(context, p->offset, p->new_size);
3232 if (r < 0)
3233 return r;
3234
3235 log_info("Successfully wiped file system signatures from future partition %" PRIu64 ".", p->partno);
3236 return 0;
3237 }
3238
3239 static int context_discard_range(
3240 Context *context,
3241 uint64_t offset,
3242 uint64_t size) {
3243
3244 struct stat st;
3245 int fd;
3246
3247 assert(context);
3248 assert(offset != UINT64_MAX);
3249 assert(size != UINT64_MAX);
3250
3251 if (size <= 0)
3252 return 0;
3253
3254 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3255
3256 if (fstat(fd, &st) < 0)
3257 return -errno;
3258
3259 if (S_ISREG(st.st_mode)) {
3260 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, size) < 0) {
3261 if (ERRNO_IS_NOT_SUPPORTED(errno))
3262 return -EOPNOTSUPP;
3263
3264 return -errno;
3265 }
3266
3267 return 1;
3268 }
3269
3270 if (S_ISBLK(st.st_mode)) {
3271 uint64_t range[2], end;
3272
3273 range[0] = round_up_size(offset, context->sector_size);
3274
3275 if (offset > UINT64_MAX - size)
3276 return -ERANGE;
3277
3278 end = offset + size;
3279 if (end <= range[0])
3280 return 0;
3281
3282 range[1] = round_down_size(end - range[0], context->sector_size);
3283 if (range[1] <= 0)
3284 return 0;
3285
3286 if (ioctl(fd, BLKDISCARD, range) < 0) {
3287 if (ERRNO_IS_NOT_SUPPORTED(errno))
3288 return -EOPNOTSUPP;
3289
3290 return -errno;
3291 }
3292
3293 return 1;
3294 }
3295
3296 return -EOPNOTSUPP;
3297 }
3298
3299 static int context_discard_partition(Context *context, Partition *p) {
3300 int r;
3301
3302 assert(context);
3303 assert(p);
3304
3305 assert(p->offset != UINT64_MAX);
3306 assert(p->new_size != UINT64_MAX);
3307 assert(!PARTITION_EXISTS(p)); /* Safety check: never discard existing partitions */
3308
3309 if (!arg_discard)
3310 return 0;
3311
3312 r = context_discard_range(context, p->offset, p->new_size);
3313 if (r == -EOPNOTSUPP) {
3314 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno);
3315 return 0;
3316 }
3317 if (r == -EBUSY) {
3318 /* Let's handle this gracefully: https://bugzilla.kernel.org/show_bug.cgi?id=211167 */
3319 log_info("Block device is busy, not discarding partition %" PRIu64 " because it probably is mounted.", p->partno);
3320 return 0;
3321 }
3322 if (r == 0) {
3323 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
3324 return 0;
3325 }
3326 if (r < 0)
3327 return log_error_errno(r, "Failed to discard data for future partition %" PRIu64 ".", p->partno);
3328
3329 log_info("Successfully discarded data from future partition %" PRIu64 ".", p->partno);
3330 return 1;
3331 }
3332
3333 static int context_discard_gap_after(Context *context, Partition *p) {
3334 uint64_t gap, next = UINT64_MAX;
3335 int r;
3336
3337 assert(context);
3338 assert(!p || (p->offset != UINT64_MAX && p->new_size != UINT64_MAX));
3339
3340 if (!arg_discard)
3341 return 0;
3342
3343 if (p)
3344 gap = p->offset + p->new_size;
3345 else
3346 /* The context start gets rounded up to grain_size, however
3347 * existing partitions may be before that so ensure the gap
3348 * starts at the first actually usable lba
3349 */
3350 gap = fdisk_get_first_lba(context->fdisk_context) * context->sector_size;
3351
3352 LIST_FOREACH(partitions, q, context->partitions) {
3353 if (q->dropped)
3354 continue;
3355
3356 assert(q->offset != UINT64_MAX);
3357 assert(q->new_size != UINT64_MAX);
3358
3359 if (q->offset < gap)
3360 continue;
3361
3362 if (next == UINT64_MAX || q->offset < next)
3363 next = q->offset;
3364 }
3365
3366 if (next == UINT64_MAX) {
3367 next = (fdisk_get_last_lba(context->fdisk_context) + 1) * context->sector_size;
3368 if (gap > next)
3369 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
3370 }
3371
3372 assert(next >= gap);
3373 r = context_discard_range(context, gap, next - gap);
3374 if (r == -EOPNOTSUPP) {
3375 if (p)
3376 log_info("Storage does not support discard, not discarding gap after partition %" PRIu64 ".", p->partno);
3377 else
3378 log_info("Storage does not support discard, not discarding gap at beginning of disk.");
3379 return 0;
3380 }
3381 if (r == 0) /* Too short */
3382 return 0;
3383 if (r < 0) {
3384 if (p)
3385 return log_error_errno(r, "Failed to discard gap after partition %" PRIu64 ".", p->partno);
3386 else
3387 return log_error_errno(r, "Failed to discard gap at beginning of disk.");
3388 }
3389
3390 if (p)
3391 log_info("Successfully discarded gap after partition %" PRIu64 ".", p->partno);
3392 else
3393 log_info("Successfully discarded gap at beginning of disk.");
3394
3395 return 0;
3396 }
3397
3398 static int context_wipe_and_discard(Context *context) {
3399 int r;
3400
3401 assert(context);
3402
3403 if (arg_empty == EMPTY_CREATE) /* If we just created the image, no need to wipe */
3404 return 0;
3405
3406 /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
3407 * we were supposed to start from scratch anyway, as in that case we just discard the whole block
3408 * device in one go early on. */
3409
3410 LIST_FOREACH(partitions, p, context->partitions) {
3411
3412 if (!p->allocated_to_area)
3413 continue;
3414
3415 if (partition_type_defer(&p->type))
3416 continue;
3417
3418 r = context_wipe_partition(context, p);
3419 if (r < 0)
3420 return r;
3421
3422 if (!context->from_scratch) {
3423 r = context_discard_partition(context, p);
3424 if (r < 0)
3425 return r;
3426
3427 r = context_discard_gap_after(context, p);
3428 if (r < 0)
3429 return r;
3430 }
3431 }
3432
3433 if (!context->from_scratch) {
3434 r = context_discard_gap_after(context, NULL);
3435 if (r < 0)
3436 return r;
3437 }
3438
3439 return 0;
3440 }
3441
3442 typedef struct DecryptedPartitionTarget {
3443 int fd;
3444 char *dm_name;
3445 char *volume;
3446 struct crypt_device *device;
3447 } DecryptedPartitionTarget;
3448
3449 static DecryptedPartitionTarget* decrypted_partition_target_free(DecryptedPartitionTarget *t) {
3450 #if HAVE_LIBCRYPTSETUP
3451 int r;
3452
3453 if (!t)
3454 return NULL;
3455
3456 safe_close(t->fd);
3457
3458 /* udev or so might access out block device in the background while we are done. Let's hence
3459 * force detach the volume. We sync'ed before, hence this should be safe. */
3460 r = sym_crypt_deactivate_by_name(t->device, t->dm_name, CRYPT_DEACTIVATE_FORCE);
3461 if (r < 0)
3462 log_warning_errno(r, "Failed to deactivate LUKS device, ignoring: %m");
3463
3464 sym_crypt_free(t->device);
3465 free(t->dm_name);
3466 free(t->volume);
3467 free(t);
3468 #endif
3469 return NULL;
3470 }
3471
3472 typedef struct {
3473 LoopDevice *loop;
3474 int fd;
3475 char *path;
3476 int whole_fd;
3477 DecryptedPartitionTarget *decrypted;
3478 } PartitionTarget;
3479
3480 static int partition_target_fd(PartitionTarget *t) {
3481 assert(t);
3482 assert(t->loop || t->fd >= 0 || t->whole_fd >= 0);
3483
3484 if (t->decrypted)
3485 return t->decrypted->fd;
3486
3487 if (t->loop)
3488 return t->loop->fd;
3489
3490 if (t->fd >= 0)
3491 return t->fd;
3492
3493 return t->whole_fd;
3494 }
3495
3496 static const char* partition_target_path(PartitionTarget *t) {
3497 assert(t);
3498 assert(t->loop || t->path);
3499
3500 if (t->decrypted)
3501 return t->decrypted->volume;
3502
3503 if (t->loop)
3504 return t->loop->node;
3505
3506 return t->path;
3507 }
3508
3509 static PartitionTarget *partition_target_free(PartitionTarget *t) {
3510 if (!t)
3511 return NULL;
3512
3513 decrypted_partition_target_free(t->decrypted);
3514 loop_device_unref(t->loop);
3515 safe_close(t->fd);
3516 unlink_and_free(t->path);
3517
3518 return mfree(t);
3519 }
3520
3521 DEFINE_TRIVIAL_CLEANUP_FUNC(PartitionTarget*, partition_target_free);
3522
3523 static int prepare_temporary_file(PartitionTarget *t, uint64_t size) {
3524 _cleanup_(unlink_and_freep) char *temp = NULL;
3525 _cleanup_close_ int fd = -EBADF;
3526 const char *vt;
3527 int r;
3528
3529 assert(t);
3530
3531 r = var_tmp_dir(&vt);
3532 if (r < 0)
3533 return log_error_errno(r, "Could not determine temporary directory: %m");
3534
3535 temp = path_join(vt, "repart-XXXXXX");
3536 if (!temp)
3537 return log_oom();
3538
3539 fd = mkostemp_safe(temp);
3540 if (fd < 0)
3541 return log_error_errno(fd, "Failed to create temporary file: %m");
3542
3543 if (ftruncate(fd, size) < 0)
3544 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m",
3545 FORMAT_BYTES(size));
3546
3547 t->fd = TAKE_FD(fd);
3548 t->path = TAKE_PTR(temp);
3549
3550 return 0;
3551 }
3552
3553 static int partition_target_prepare(
3554 Context *context,
3555 Partition *p,
3556 uint64_t size,
3557 bool need_path,
3558 PartitionTarget **ret) {
3559
3560 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
3561 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
3562 int whole_fd, r;
3563
3564 assert(context);
3565 assert(p);
3566 assert(ret);
3567
3568 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3569
3570 t = new(PartitionTarget, 1);
3571 if (!t)
3572 return log_oom();
3573 *t = (PartitionTarget) {
3574 .fd = -EBADF,
3575 .whole_fd = -EBADF,
3576 };
3577
3578 if (!need_path) {
3579 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
3580 return log_error_errno(errno, "Failed to seek to partition offset: %m");
3581
3582 t->whole_fd = whole_fd;
3583 *ret = TAKE_PTR(t);
3584 return 0;
3585 }
3586
3587 /* Loopback block devices are not only useful to turn regular files into block devices, but
3588 * also to cut out sections of block devices into new block devices. */
3589
3590 if (arg_offline <= 0) {
3591 r = loop_device_make(whole_fd, O_RDWR, p->offset, size, context->sector_size, 0, LOCK_EX, &d);
3592 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
3593 return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
3594 if (r >= 0) {
3595 t->loop = TAKE_PTR(d);
3596 *ret = TAKE_PTR(t);
3597 return 0;
3598 }
3599
3600 log_debug_errno(r, "No access to loop devices, falling back to a regular file");
3601 }
3602
3603 /* If we can't allocate a loop device, let's write to a regular file that we copy into the final
3604 * image so we can run in containers and without needing root privileges. On filesystems with
3605 * reflinking support, we can take advantage of this and just reflink the result into the image.
3606 */
3607
3608 r = prepare_temporary_file(t, size);
3609 if (r < 0)
3610 return r;
3611
3612 *ret = TAKE_PTR(t);
3613
3614 return 0;
3615 }
3616
3617 static int partition_target_grow(PartitionTarget *t, uint64_t size) {
3618 int r;
3619
3620 assert(t);
3621 assert(!t->decrypted);
3622
3623 if (t->loop) {
3624 r = loop_device_refresh_size(t->loop, UINT64_MAX, size);
3625 if (r < 0)
3626 return log_error_errno(r, "Failed to refresh loopback device size: %m");
3627 } else if (t->fd >= 0) {
3628 if (ftruncate(t->fd, size) < 0)
3629 return log_error_errno(errno, "Failed to grow '%s' to %s by truncation: %m",
3630 t->path, FORMAT_BYTES(size));
3631 }
3632
3633 return 0;
3634 }
3635
3636 static int partition_target_sync(Context *context, Partition *p, PartitionTarget *t) {
3637 int whole_fd, r;
3638
3639 assert(context);
3640 assert(p);
3641 assert(t);
3642
3643 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3644
3645 if (t->decrypted && fsync(t->decrypted->fd) < 0)
3646 return log_error_errno(errno, "Failed to sync changes to '%s': %m", t->decrypted->volume);
3647
3648 if (t->loop) {
3649 r = loop_device_sync(t->loop);
3650 if (r < 0)
3651 return log_error_errno(r, "Failed to sync loopback device: %m");
3652 } else if (t->fd >= 0) {
3653 struct stat st;
3654
3655 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
3656 return log_error_errno(errno, "Failed to seek to partition offset: %m");
3657
3658 if (lseek(t->fd, 0, SEEK_SET) < 0)
3659 return log_error_errno(errno, "Failed to seek to start of temporary file: %m");
3660
3661 if (fstat(t->fd, &st) < 0)
3662 return log_error_errno(errno, "Failed to stat temporary file: %m");
3663
3664 if (st.st_size > (off_t) p->new_size)
3665 return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
3666 "Partition %" PRIu64 "'s contents (%s) don't fit in the partition (%s)",
3667 p->partno, FORMAT_BYTES(st.st_size), FORMAT_BYTES(p->new_size));
3668
3669 r = copy_bytes(t->fd, whole_fd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_FSYNC);
3670 if (r < 0)
3671 return log_error_errno(r, "Failed to copy bytes to partition: %m");
3672 } else {
3673 if (fsync(t->whole_fd) < 0)
3674 return log_error_errno(errno, "Failed to sync changes: %m");
3675 }
3676
3677 return 0;
3678 }
3679
3680 static int partition_encrypt(Context *context, Partition *p, PartitionTarget *target, bool offline) {
3681 #if HAVE_LIBCRYPTSETUP && HAVE_CRYPT_SET_DATA_OFFSET && HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE && HAVE_CRYPT_REENCRYPT
3682 const char *node = partition_target_path(target);
3683 struct crypt_params_luks2 luks_params = {
3684 .label = strempty(ASSERT_PTR(p)->new_label),
3685 .sector_size = ASSERT_PTR(context)->fs_sector_size,
3686 .data_device = offline ? node : NULL,
3687 };
3688 struct crypt_params_reencrypt reencrypt_params = {
3689 .mode = CRYPT_REENCRYPT_ENCRYPT,
3690 .direction = CRYPT_REENCRYPT_BACKWARD,
3691 .resilience = "datashift",
3692 .data_shift = LUKS2_METADATA_SIZE / 512,
3693 .luks2 = &luks_params,
3694 .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY|CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT,
3695 };
3696 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
3697 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
3698 _cleanup_fclose_ FILE *h = NULL;
3699 _cleanup_free_ char *hp = NULL, *vol = NULL, *dm_name = NULL;
3700 const char *passphrase = NULL;
3701 size_t passphrase_size = 0;
3702 const char *vt;
3703 int r;
3704
3705 assert(context);
3706 assert(p);
3707 assert(p->encrypt != ENCRYPT_OFF);
3708
3709 r = dlopen_cryptsetup();
3710 if (r < 0)
3711 return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m");
3712
3713 log_info("Encrypting future partition %" PRIu64 "...", p->partno);
3714
3715 if (offline) {
3716 r = var_tmp_dir(&vt);
3717 if (r < 0)
3718 return log_error_errno(r, "Failed to determine temporary files directory: %m");
3719
3720 r = fopen_temporary_child(vt, &h, &hp);
3721 if (r < 0)
3722 return log_error_errno(r, "Failed to create temporary LUKS header file: %m");
3723
3724 /* Weird cryptsetup requirement which requires the header file to be the size of at least one
3725 * sector. */
3726 if (ftruncate(fileno(h), luks_params.sector_size) < 0)
3727 return log_error_errno(errno, "Failed to grow temporary LUKS header file: %m");
3728 } else {
3729 if (asprintf(&dm_name, "luks-repart-%08" PRIx64, random_u64()) < 0)
3730 return log_oom();
3731
3732 vol = path_join("/dev/mapper/", dm_name);
3733 if (!vol)
3734 return log_oom();
3735 }
3736
3737 r = sym_crypt_init(&cd, offline ? hp : node);
3738 if (r < 0)
3739 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", hp);
3740
3741 cryptsetup_enable_logging(cd);
3742
3743 if (offline) {
3744 /* Disable kernel keyring usage by libcryptsetup as a workaround for
3745 * https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/273. This makes sure that we can
3746 * do offline encryption even when repart is running in a container. */
3747 r = sym_crypt_volume_key_keyring(cd, false);
3748 if (r < 0)
3749 return log_error_errno(r, "Failed to disable kernel keyring: %m");
3750
3751 r = sym_crypt_metadata_locking(cd, false);
3752 if (r < 0)
3753 return log_error_errno(r, "Failed to disable metadata locking: %m");
3754
3755 r = sym_crypt_set_data_offset(cd, LUKS2_METADATA_SIZE / 512);
3756 if (r < 0)
3757 return log_error_errno(r, "Failed to set data offset: %m");
3758 }
3759
3760 r = sym_crypt_format(
3761 cd,
3762 CRYPT_LUKS2,
3763 "aes",
3764 "xts-plain64",
3765 SD_ID128_TO_UUID_STRING(p->luks_uuid),
3766 NULL,
3767 VOLUME_KEY_SIZE,
3768 &luks_params);
3769 if (r < 0)
3770 return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
3771
3772 if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
3773 r = sym_crypt_keyslot_add_by_volume_key(
3774 cd,
3775 CRYPT_ANY_SLOT,
3776 NULL,
3777 VOLUME_KEY_SIZE,
3778 strempty(arg_key),
3779 arg_key_size);
3780 if (r < 0)
3781 return log_error_errno(r, "Failed to add LUKS2 key: %m");
3782
3783 passphrase = strempty(arg_key);
3784 passphrase_size = arg_key_size;
3785 }
3786
3787 if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
3788 #if HAVE_TPM2
3789 _cleanup_(iovec_done) struct iovec pubkey = {}, blob = {}, srk = {};
3790 _cleanup_(iovec_done_erase) struct iovec secret = {};
3791 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
3792 ssize_t base64_encoded_size;
3793 int keyslot;
3794 TPM2Flags flags = 0;
3795
3796 if (arg_tpm2_public_key_pcr_mask != 0) {
3797 r = tpm2_load_pcr_public_key(arg_tpm2_public_key, &pubkey.iov_base, &pubkey.iov_len);
3798 if (r < 0) {
3799 if (arg_tpm2_public_key || r != -ENOENT)
3800 return log_error_errno(r, "Failed to read TPM PCR public key: %m");
3801
3802 log_debug_errno(r, "Failed to read TPM2 PCR public key, proceeding without: %m");
3803 arg_tpm2_public_key_pcr_mask = 0;
3804 }
3805 }
3806
3807 TPM2B_PUBLIC public;
3808 if (iovec_is_set(&pubkey)) {
3809 r = tpm2_tpm2b_public_from_pem(pubkey.iov_base, pubkey.iov_len, &public);
3810 if (r < 0)
3811 return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m");
3812 }
3813
3814 _cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
3815 if (arg_tpm2_pcrlock) {
3816 r = tpm2_pcrlock_policy_load(arg_tpm2_pcrlock, &pcrlock_policy);
3817 if (r < 0)
3818 return r;
3819
3820 flags |= TPM2_FLAGS_USE_PCRLOCK;
3821 }
3822
3823 _cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
3824 TPM2B_PUBLIC device_key_public = {};
3825 if (arg_tpm2_device_key) {
3826 r = tpm2_load_public_key_file(arg_tpm2_device_key, &device_key_public);
3827 if (r < 0)
3828 return r;
3829
3830 if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values))
3831 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
3832 "Must provide all PCR values when using TPM2 device key.");
3833 } else {
3834 r = tpm2_context_new(arg_tpm2_device, &tpm2_context);
3835 if (r < 0)
3836 return log_error_errno(r, "Failed to create TPM2 context: %m");
3837
3838 if (!tpm2_pcr_values_has_all_values(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values)) {
3839 r = tpm2_pcr_read_missing_values(tpm2_context, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values);
3840 if (r < 0)
3841 return log_error_errno(r, "Could not read pcr values: %m");
3842 }
3843 }
3844
3845 uint16_t hash_pcr_bank = 0;
3846 uint32_t hash_pcr_mask = 0;
3847 if (arg_tpm2_n_hash_pcr_values > 0) {
3848 size_t hash_count;
3849 r = tpm2_pcr_values_hash_count(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, &hash_count);
3850 if (r < 0)
3851 return log_error_errno(r, "Could not get hash count: %m");
3852
3853 if (hash_count > 1)
3854 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
3855
3856 hash_pcr_bank = arg_tpm2_hash_pcr_values[0].hash;
3857 r = tpm2_pcr_values_to_mask(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, hash_pcr_bank, &hash_pcr_mask);
3858 if (r < 0)
3859 return log_error_errno(r, "Could not get hash mask: %m");
3860 }
3861
3862 TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
3863 r = tpm2_calculate_sealing_policy(
3864 arg_tpm2_hash_pcr_values,
3865 arg_tpm2_n_hash_pcr_values,
3866 iovec_is_set(&pubkey) ? &public : NULL,
3867 /* use_pin= */ false,
3868 arg_tpm2_pcrlock ? &pcrlock_policy : NULL,
3869 &policy);
3870 if (r < 0)
3871 return log_error_errno(r, "Could not calculate sealing policy digest: %m");
3872
3873 if (arg_tpm2_device_key)
3874 r = tpm2_calculate_seal(
3875 arg_tpm2_seal_key_handle,
3876 &device_key_public,
3877 /* attributes= */ NULL,
3878 /* secret= */ NULL,
3879 &policy,
3880 /* pin= */ NULL,
3881 &secret,
3882 &blob,
3883 &srk);
3884 else
3885 r = tpm2_seal(tpm2_context,
3886 arg_tpm2_seal_key_handle,
3887 &policy,
3888 /* pin= */ NULL,
3889 &secret,
3890 &blob,
3891 /* ret_primary_alg= */ NULL,
3892 &srk);
3893 if (r < 0)
3894 return log_error_errno(r, "Failed to seal to TPM2: %m");
3895
3896 base64_encoded_size = base64mem(secret.iov_base, secret.iov_len, &base64_encoded);
3897 if (base64_encoded_size < 0)
3898 return log_error_errno(base64_encoded_size, "Failed to base64 encode secret key: %m");
3899
3900 r = cryptsetup_set_minimal_pbkdf(cd);
3901 if (r < 0)
3902 return log_error_errno(r, "Failed to set minimal PBKDF: %m");
3903
3904 keyslot = sym_crypt_keyslot_add_by_volume_key(
3905 cd,
3906 CRYPT_ANY_SLOT,
3907 /* volume_key= */ NULL,
3908 /* volume_key_size= */ VOLUME_KEY_SIZE,
3909 base64_encoded,
3910 base64_encoded_size);
3911 if (keyslot < 0)
3912 return log_error_errno(keyslot, "Failed to add new TPM2 key: %m");
3913
3914 r = tpm2_make_luks2_json(
3915 keyslot,
3916 hash_pcr_mask,
3917 hash_pcr_bank,
3918 &pubkey,
3919 arg_tpm2_public_key_pcr_mask,
3920 /* primary_alg= */ 0,
3921 &blob,
3922 &IOVEC_MAKE(policy.buffer, policy.size),
3923 /* salt= */ NULL, /* no salt because tpm2_seal has no pin */
3924 &srk,
3925 flags,
3926 &v);
3927 if (r < 0)
3928 return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
3929
3930 r = cryptsetup_add_token_json(cd, v);
3931 if (r < 0)
3932 return log_error_errno(r, "Failed to add TPM2 JSON token to LUKS2 header: %m");
3933
3934 passphrase = base64_encoded;
3935 passphrase_size = strlen(base64_encoded);
3936 #else
3937 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3938 "Support for TPM2 enrollment not enabled.");
3939 #endif
3940 }
3941
3942 if (offline) {
3943 r = sym_crypt_reencrypt_init_by_passphrase(
3944 cd,
3945 NULL,
3946 passphrase,
3947 passphrase_size,
3948 CRYPT_ANY_SLOT,
3949 0,
3950 sym_crypt_get_cipher(cd),
3951 sym_crypt_get_cipher_mode(cd),
3952 &reencrypt_params);
3953 if (r < 0)
3954 return log_error_errno(r, "Failed to prepare for reencryption: %m");
3955
3956 /* crypt_reencrypt_init_by_passphrase() doesn't actually put the LUKS header at the front, we
3957 * have to do that ourselves. */
3958
3959 sym_crypt_free(cd);
3960 cd = NULL;
3961
3962 r = sym_crypt_init(&cd, node);
3963 if (r < 0)
3964 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", node);
3965
3966 r = sym_crypt_header_restore(cd, CRYPT_LUKS2, hp);
3967 if (r < 0)
3968 return log_error_errno(r, "Failed to place new LUKS header at head of %s: %m", node);
3969
3970 reencrypt_params.flags &= ~CRYPT_REENCRYPT_INITIALIZE_ONLY;
3971
3972 r = sym_crypt_reencrypt_init_by_passphrase(
3973 cd,
3974 NULL,
3975 passphrase,
3976 passphrase_size,
3977 CRYPT_ANY_SLOT,
3978 0,
3979 NULL,
3980 NULL,
3981 &reencrypt_params);
3982 if (r < 0)
3983 return log_error_errno(r, "Failed to load reencryption context: %m");
3984
3985 r = sym_crypt_reencrypt(cd, NULL);
3986 if (r < 0)
3987 return log_error_errno(r, "Failed to encrypt %s: %m", node);
3988 } else {
3989 _cleanup_free_ DecryptedPartitionTarget *t = NULL;
3990 _cleanup_close_ int dev_fd = -1;
3991
3992 r = sym_crypt_activate_by_volume_key(
3993 cd,
3994 dm_name,
3995 NULL,
3996 VOLUME_KEY_SIZE,
3997 arg_discard ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0);
3998 if (r < 0)
3999 return log_error_errno(r, "Failed to activate LUKS superblock: %m");
4000
4001 dev_fd = open(vol, O_RDWR|O_CLOEXEC|O_NOCTTY);
4002 if (dev_fd < 0)
4003 return log_error_errno(errno, "Failed to open LUKS volume '%s': %m", vol);
4004
4005 if (flock(dev_fd, LOCK_EX) < 0)
4006 return log_error_errno(errno, "Failed to lock '%s': %m", vol);
4007
4008 t = new(DecryptedPartitionTarget, 1);
4009 if (!t)
4010 return log_oom();
4011
4012 *t = (DecryptedPartitionTarget) {
4013 .fd = TAKE_FD(dev_fd),
4014 .dm_name = TAKE_PTR(dm_name),
4015 .volume = TAKE_PTR(vol),
4016 .device = TAKE_PTR(cd),
4017 };
4018
4019 target->decrypted = TAKE_PTR(t);
4020 }
4021
4022 log_info("Successfully encrypted future partition %" PRIu64 ".", p->partno);
4023
4024 return 0;
4025 #else
4026 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
4027 "libcryptsetup is not supported or is missing required symbols, cannot encrypt: %m");
4028 #endif
4029 }
4030
4031 static int partition_format_verity_hash(
4032 Context *context,
4033 Partition *p,
4034 const char *node,
4035 const char *data_node) {
4036
4037 #if HAVE_LIBCRYPTSETUP
4038 Partition *dp;
4039 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4040 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
4041 _cleanup_free_ char *hint = NULL;
4042 int r;
4043
4044 assert(context);
4045 assert(p);
4046 assert(p->verity == VERITY_HASH);
4047 assert(data_node);
4048
4049 if (p->dropped)
4050 return 0;
4051
4052 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
4053 return 0;
4054
4055 /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
4056 if (p->copy_blocks_fd >= 0)
4057 return 0;
4058
4059 assert_se(dp = p->siblings[VERITY_DATA]);
4060 assert(!dp->dropped);
4061
4062 (void) partition_hint(p, node, &hint);
4063
4064 r = dlopen_cryptsetup();
4065 if (r < 0)
4066 return log_error_errno(r, "libcryptsetup not found, cannot setup verity: %m");
4067
4068 if (!node) {
4069 r = partition_target_prepare(context, p, p->new_size, /*need_path=*/ true, &t);
4070 if (r < 0)
4071 return r;
4072
4073 node = partition_target_path(t);
4074 }
4075
4076 if (p->verity_data_block_size == UINT64_MAX)
4077 p->verity_data_block_size = context->fs_sector_size;
4078 if (p->verity_hash_block_size == UINT64_MAX)
4079 p->verity_hash_block_size = context->fs_sector_size;
4080
4081 r = sym_crypt_init(&cd, node);
4082 if (r < 0)
4083 return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", node);
4084
4085 cryptsetup_enable_logging(cd);
4086
4087 r = sym_crypt_format(
4088 cd, CRYPT_VERITY, NULL, NULL, SD_ID128_TO_UUID_STRING(p->verity_uuid), NULL, 0,
4089 &(struct crypt_params_verity){
4090 .data_device = data_node,
4091 .flags = CRYPT_VERITY_CREATE_HASH,
4092 .hash_name = "sha256",
4093 .hash_type = 1,
4094 .data_block_size = p->verity_data_block_size,
4095 .hash_block_size = p->verity_hash_block_size,
4096 .salt_size = sizeof(p->verity_salt),
4097 .salt = (const char*)p->verity_salt,
4098 });
4099 if (r < 0) {
4100 /* libcryptsetup reports non-descriptive EIO errors for every I/O failure. Luckily, it
4101 * doesn't clobber errno so let's check for ENOSPC so we can report a better error if the
4102 * partition is too small. */
4103 if (r == -EIO && errno == ENOSPC)
4104 return log_error_errno(errno,
4105 "Verity hash data does not fit in partition %s with size %s",
4106 strna(hint), FORMAT_BYTES(p->new_size));
4107
4108 return log_error_errno(r, "Failed to setup verity hash data of partition %s: %m", strna(hint));
4109 }
4110
4111 if (t) {
4112 r = partition_target_sync(context, p, t);
4113 if (r < 0)
4114 return r;
4115 }
4116
4117 r = sym_crypt_get_volume_key_size(cd);
4118 if (r < 0)
4119 return log_error_errno(r, "Failed to determine verity root hash size of partition %s: %m", strna(hint));
4120
4121 _cleanup_(iovec_done) struct iovec rh = {
4122 .iov_base = malloc(r),
4123 .iov_len = r,
4124 };
4125 if (!rh.iov_base)
4126 return log_oom();
4127
4128 r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, (char *) rh.iov_base, &rh.iov_len, NULL, 0);
4129 if (r < 0)
4130 return log_error_errno(r, "Failed to get verity root hash of partition %s: %m", strna(hint));
4131
4132 assert(rh.iov_len >= sizeof(sd_id128_t) * 2);
4133
4134 if (!dp->new_uuid_is_set) {
4135 memcpy_safe(dp->new_uuid.bytes, rh.iov_base, sizeof(sd_id128_t));
4136 dp->new_uuid_is_set = true;
4137 }
4138
4139 if (!p->new_uuid_is_set) {
4140 memcpy_safe(p->new_uuid.bytes, (uint8_t*) rh.iov_base + (rh.iov_len - sizeof(sd_id128_t)), sizeof(sd_id128_t));
4141 p->new_uuid_is_set = true;
4142 }
4143
4144 p->roothash = TAKE_STRUCT(rh);
4145
4146 return 0;
4147 #else
4148 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libcryptsetup is not supported, cannot setup verity hashes: %m");
4149 #endif
4150 }
4151
4152 static int sign_verity_roothash(
4153 const struct iovec *roothash,
4154 struct iovec *ret_signature) {
4155
4156 #if HAVE_OPENSSL
4157 _cleanup_(BIO_freep) BIO *rb = NULL;
4158 _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL;
4159 _cleanup_free_ char *hex = NULL;
4160 _cleanup_free_ uint8_t *sig = NULL;
4161 int sigsz;
4162
4163 assert(roothash);
4164 assert(iovec_is_set(roothash));
4165 assert(ret_signature);
4166
4167 hex = hexmem(roothash->iov_base, roothash->iov_len);
4168 if (!hex)
4169 return log_oom();
4170
4171 rb = BIO_new_mem_buf(hex, -1);
4172 if (!rb)
4173 return log_oom();
4174
4175 p7 = PKCS7_sign(arg_certificate, arg_private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
4176 if (!p7)
4177 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s",
4178 ERR_error_string(ERR_get_error(), NULL));
4179
4180 sigsz = i2d_PKCS7(p7, &sig);
4181 if (sigsz < 0)
4182 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s",
4183 ERR_error_string(ERR_get_error(), NULL));
4184
4185 *ret_signature = IOVEC_MAKE(TAKE_PTR(sig), sigsz);
4186
4187 return 0;
4188 #else
4189 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot setup verity signature: %m");
4190 #endif
4191 }
4192
4193 static int partition_format_verity_sig(Context *context, Partition *p) {
4194 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
4195 _cleanup_(iovec_done) struct iovec sig = {};
4196 _cleanup_free_ char *text = NULL, *hint = NULL;
4197 Partition *hp;
4198 uint8_t fp[X509_FINGERPRINT_SIZE];
4199 int whole_fd, r;
4200
4201 assert(p->verity == VERITY_SIG);
4202
4203 if (p->dropped)
4204 return 0;
4205
4206 if (PARTITION_EXISTS(p))
4207 return 0;
4208
4209 (void) partition_hint(p, context->node, &hint);
4210
4211 assert_se(hp = p->siblings[VERITY_HASH]);
4212 assert(!hp->dropped);
4213
4214 assert(arg_certificate);
4215
4216 assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
4217
4218 r = sign_verity_roothash(&hp->roothash, &sig);
4219 if (r < 0)
4220 return r;
4221
4222 r = x509_fingerprint(arg_certificate, fp);
4223 if (r < 0)
4224 return log_error_errno(r, "Unable to calculate X509 certificate fingerprint: %m");
4225
4226 r = json_build(&v,
4227 JSON_BUILD_OBJECT(
4228 JSON_BUILD_PAIR("rootHash", JSON_BUILD_HEX(hp->roothash.iov_base, hp->roothash.iov_len)),
4229 JSON_BUILD_PAIR(
4230 "certificateFingerprint",
4231 JSON_BUILD_HEX(fp, sizeof(fp))
4232 ),
4233 JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(&sig))
4234 )
4235 );
4236 if (r < 0)
4237 return log_error_errno(r, "Failed to build verity signature JSON object: %m");
4238
4239 r = json_variant_format(v, 0, &text);
4240 if (r < 0)
4241 return log_error_errno(r, "Failed to format verity signature JSON object: %m");
4242
4243 if (strlen(text)+1 > p->new_size)
4244 return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Verity signature too long for partition: %m");
4245
4246 r = strgrowpad0(&text, p->new_size);
4247 if (r < 0)
4248 return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(p->new_size));
4249
4250 if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
4251 return log_error_errno(errno, "Failed to seek to partition %s offset: %m", strna(hint));
4252
4253 r = loop_write(whole_fd, text, p->new_size);
4254 if (r < 0)
4255 return log_error_errno(r, "Failed to write verity signature to partition %s: %m", strna(hint));
4256
4257 if (fsync(whole_fd) < 0)
4258 return log_error_errno(errno, "Failed to synchronize partition %s: %m", strna(hint));
4259
4260 return 0;
4261 }
4262
4263 static int context_copy_blocks(Context *context) {
4264 int r;
4265
4266 assert(context);
4267
4268 /* Copy in file systems on the block level */
4269
4270 LIST_FOREACH(partitions, p, context->partitions) {
4271 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4272
4273 if (p->copy_blocks_fd < 0)
4274 continue;
4275
4276 if (p->dropped)
4277 continue;
4278
4279 if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */
4280 continue;
4281
4282 if (partition_type_defer(&p->type))
4283 continue;
4284
4285 assert(p->new_size != UINT64_MAX);
4286 assert(p->copy_blocks_size != UINT64_MAX);
4287 assert(p->new_size >= p->copy_blocks_size + (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
4288
4289 usec_t start_timestamp = now(CLOCK_MONOTONIC);
4290
4291 r = partition_target_prepare(context, p, p->new_size,
4292 /*need_path=*/ p->encrypt != ENCRYPT_OFF || p->siblings[VERITY_HASH],
4293 &t);
4294 if (r < 0)
4295 return r;
4296
4297 if (p->encrypt != ENCRYPT_OFF && t->loop) {
4298 r = partition_encrypt(context, p, t, /* offline = */ false);
4299 if (r < 0)
4300 return r;
4301 }
4302
4303 if (p->copy_blocks_offset == UINT64_MAX)
4304 log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64 ".",
4305 p->copy_blocks_path, FORMAT_BYTES(p->copy_blocks_size), p->partno);
4306 else {
4307 log_info("Copying in '%s' @ %" PRIu64 " (%s) on block level into future partition %" PRIu64 ".",
4308 p->copy_blocks_path, p->copy_blocks_offset, FORMAT_BYTES(p->copy_blocks_size), p->partno);
4309
4310 if (lseek(p->copy_blocks_fd, p->copy_blocks_offset, SEEK_SET) < 0)
4311 return log_error_errno(errno, "Failed to seek to copy blocks offset in %s: %m", p->copy_blocks_path);
4312 }
4313
4314 r = copy_bytes(p->copy_blocks_fd, partition_target_fd(t), p->copy_blocks_size, COPY_REFLINK);
4315 if (r < 0)
4316 return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
4317
4318 log_info("Copying in of '%s' on block level completed.", p->copy_blocks_path);
4319
4320 if (p->encrypt != ENCRYPT_OFF && !t->loop) {
4321 r = partition_encrypt(context, p, t, /* offline = */ true);
4322 if (r < 0)
4323 return r;
4324 }
4325
4326 r = partition_target_sync(context, p, t);
4327 if (r < 0)
4328 return r;
4329
4330 usec_t time_spent = usec_sub_unsigned(now(CLOCK_MONOTONIC), start_timestamp);
4331 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 */
4332 log_info("Block level copying and synchronization of partition %" PRIu64 " complete in %s (%s/s).",
4333 p->partno, FORMAT_TIMESPAN(time_spent, 0), FORMAT_BYTES((uint64_t) ((double) p->copy_blocks_size / time_spent * USEC_PER_SEC)));
4334 else
4335 log_info("Block level copying and synchronization of partition %" PRIu64 " complete in %s.",
4336 p->partno, FORMAT_TIMESPAN(time_spent, 0));
4337
4338 if (p->siblings[VERITY_HASH] && !partition_type_defer(&p->siblings[VERITY_HASH]->type)) {
4339 r = partition_format_verity_hash(context, p->siblings[VERITY_HASH],
4340 /* node = */ NULL, partition_target_path(t));
4341 if (r < 0)
4342 return r;
4343 }
4344
4345 if (p->siblings[VERITY_SIG] && !partition_type_defer(&p->siblings[VERITY_SIG]->type)) {
4346 r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
4347 if (r < 0)
4348 return r;
4349 }
4350 }
4351
4352 return 0;
4353 }
4354
4355 static int add_exclude_path(const char *path, Hashmap **denylist, DenyType type) {
4356 _cleanup_free_ struct stat *st = NULL;
4357 int r;
4358
4359 assert(path);
4360 assert(denylist);
4361
4362 st = new(struct stat, 1);
4363 if (!st)
4364 return log_oom();
4365
4366 r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
4367 if (r == -ENOENT)
4368 return 0;
4369 if (r < 0)
4370 return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
4371
4372 r = hashmap_ensure_put(denylist, &inode_hash_ops, st, INT_TO_PTR(type));
4373 if (r == -EEXIST)
4374 return 0;
4375 if (r < 0)
4376 return log_oom();
4377 if (r > 0)
4378 TAKE_PTR(st);
4379
4380 return 0;
4381 }
4382
4383 static int make_copy_files_denylist(
4384 Context *context,
4385 const Partition *p,
4386 const char *source,
4387 const char *target,
4388 Hashmap **ret) {
4389
4390 _cleanup_hashmap_free_ Hashmap *denylist = NULL;
4391 int r;
4392
4393 assert(context);
4394 assert(p);
4395 assert(source);
4396 assert(target);
4397 assert(ret);
4398
4399 /* Always exclude the top level APIVFS and temporary directories since the contents of these
4400 * directories are almost certainly not intended to end up in an image. */
4401
4402 NULSTR_FOREACH(s, APIVFS_TMP_DIRS_NULSTR) {
4403 r = add_exclude_path(s, &denylist, DENY_CONTENTS);
4404 if (r < 0)
4405 return r;
4406 }
4407
4408 /* Add the user configured excludes. */
4409
4410 STRV_FOREACH(e, p->exclude_files_source) {
4411 r = add_exclude_path(*e, &denylist, endswith(*e, "/") ? DENY_CONTENTS : DENY_INODE);
4412 if (r < 0)
4413 return r;
4414 }
4415
4416 STRV_FOREACH(e, p->exclude_files_target) {
4417 _cleanup_free_ char *path = NULL;
4418
4419 const char *s = path_startswith(*e, target);
4420 if (!s)
4421 continue;
4422
4423 path = path_join(source, s);
4424 if (!path)
4425 return log_oom();
4426
4427 r = add_exclude_path(path, &denylist, endswith(*e, "/") ? DENY_CONTENTS : DENY_INODE);
4428 if (r < 0)
4429 return r;
4430 }
4431
4432 /* If we're populating a root partition, we don't want any files to end up under the APIVFS mount
4433 * points. While we already exclude <source>/proc, users could still do something such as
4434 * "CopyFiles=/abc:/". Now, if /abc has a proc subdirectory with files in it, those will end up in
4435 * the top level proc directory in the root partition, which we want to avoid. To deal with these
4436 * cases, whenever we're populating a root partition and the target of CopyFiles= is the root
4437 * directory of the root partition, we exclude all directories under the source that are named after
4438 * APIVFS directories or named after mount points of other partitions that are also going to be part
4439 * of the image. */
4440
4441 if (p->type.designator == PARTITION_ROOT && empty_or_root(target)) {
4442 LIST_FOREACH(partitions, q, context->partitions) {
4443 if (q->type.designator == PARTITION_ROOT)
4444 continue;
4445
4446 const char *sources = gpt_partition_type_mountpoint_nulstr(q->type);
4447 if (!sources)
4448 continue;
4449
4450 NULSTR_FOREACH(s, sources) {
4451 _cleanup_free_ char *path = NULL;
4452
4453 /* Exclude only the children of partition mount points so that the nested
4454 * partition mount point itself still ends up in the upper partition. */
4455
4456 path = path_join(source, s);
4457 if (!path)
4458 return -ENOMEM;
4459
4460 r = add_exclude_path(path, &denylist, DENY_CONTENTS);
4461 if (r < 0)
4462 return r;
4463 }
4464 }
4465
4466 NULSTR_FOREACH(s, APIVFS_TMP_DIRS_NULSTR) {
4467 _cleanup_free_ char *path = NULL;
4468
4469 path = path_join(source, s);
4470 if (!path)
4471 return -ENOMEM;
4472
4473 r = add_exclude_path(path, &denylist, DENY_CONTENTS);
4474 if (r < 0)
4475 return r;
4476 }
4477 }
4478
4479 *ret = TAKE_PTR(denylist);
4480 return 0;
4481 }
4482
4483 static int add_subvolume_path(const char *path, Set **subvolumes) {
4484 _cleanup_free_ struct stat *st = NULL;
4485 int r;
4486
4487 assert(path);
4488 assert(subvolumes);
4489
4490 st = new(struct stat, 1);
4491 if (!st)
4492 return log_oom();
4493
4494 r = chase_and_stat(path, arg_copy_source, CHASE_PREFIX_ROOT, NULL, st);
4495 if (r == -ENOENT)
4496 return 0;
4497 if (r < 0)
4498 return log_error_errno(r, "Failed to stat source file '%s/%s': %m", strempty(arg_copy_source), path);
4499
4500 r = set_ensure_consume(subvolumes, &inode_hash_ops, TAKE_PTR(st));
4501 if (r < 0)
4502 return log_oom();
4503
4504 return 0;
4505 }
4506
4507 static int make_subvolumes_set(
4508 Context *context,
4509 const Partition *p,
4510 const char *source,
4511 const char *target,
4512 Set **ret) {
4513 _cleanup_set_free_ Set *subvolumes = NULL;
4514 int r;
4515
4516 assert(context);
4517 assert(p);
4518 assert(target);
4519 assert(ret);
4520
4521 STRV_FOREACH(subvolume, p->subvolumes) {
4522 _cleanup_free_ char *path = NULL;
4523
4524 const char *s = path_startswith(*subvolume, target);
4525 if (!s)
4526 continue;
4527
4528 path = path_join(source, s);
4529 if (!path)
4530 return log_oom();
4531
4532 r = add_subvolume_path(path, &subvolumes);
4533 if (r < 0)
4534 return r;
4535 }
4536
4537 *ret = TAKE_PTR(subvolumes);
4538 return 0;
4539 }
4540
4541 static int do_copy_files(Context *context, Partition *p, const char *root) {
4542 int r;
4543
4544 assert(p);
4545 assert(root);
4546
4547 /* copy_tree_at() automatically copies the permissions of source directories to target directories if
4548 * it created them. However, the root directory is created by us, so we have to manually take care
4549 * that it is initialized. We use the first source directory targeting "/" as the metadata source for
4550 * the root directory. */
4551 STRV_FOREACH_PAIR(source, target, p->copy_files) {
4552 _cleanup_close_ int rfd = -EBADF, sfd = -EBADF;
4553
4554 if (!path_equal(*target, "/"))
4555 continue;
4556
4557 rfd = open(root, O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
4558 if (rfd < 0)
4559 return -errno;
4560
4561 sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_PATH|O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
4562 if (sfd < 0)
4563 return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
4564
4565 (void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS);
4566 (void) copy_access(sfd, rfd);
4567 (void) copy_times(sfd, rfd, 0);
4568
4569 break;
4570 }
4571
4572 STRV_FOREACH_PAIR(source, target, p->copy_files) {
4573 _cleanup_hashmap_free_ Hashmap *denylist = NULL;
4574 _cleanup_set_free_ Set *subvolumes_by_source_inode = NULL;
4575 _cleanup_close_ int sfd = -EBADF, pfd = -EBADF, tfd = -EBADF;
4576
4577 r = make_copy_files_denylist(context, p, *source, *target, &denylist);
4578 if (r < 0)
4579 return r;
4580
4581 r = make_subvolumes_set(context, p, *source, *target, &subvolumes_by_source_inode);
4582 if (r < 0)
4583 return r;
4584
4585 sfd = chase_and_open(*source, arg_copy_source, CHASE_PREFIX_ROOT, O_CLOEXEC|O_NOCTTY, NULL);
4586 if (sfd == -ENOENT) {
4587 log_notice_errno(sfd, "Failed to open source file '%s%s', skipping: %m", strempty(arg_copy_source), *source);
4588 continue;
4589 }
4590 if (sfd < 0)
4591 return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), *source);
4592
4593 r = fd_verify_regular(sfd);
4594 if (r < 0) {
4595 if (r != -EISDIR)
4596 return log_error_errno(r, "Failed to check type of source file '%s': %m", *source);
4597
4598 /* We are looking at a directory */
4599 tfd = chase_and_open(*target, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4600 if (tfd < 0) {
4601 _cleanup_free_ char *dn = NULL, *fn = NULL;
4602
4603 if (tfd != -ENOENT)
4604 return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
4605
4606 r = path_extract_filename(*target, &fn);
4607 if (r < 0)
4608 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
4609
4610 r = path_extract_directory(*target, &dn);
4611 if (r < 0)
4612 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
4613
4614 r = mkdir_p_root(root, dn, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4615 if (r < 0)
4616 return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
4617
4618 pfd = chase_and_open(dn, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4619 if (pfd < 0)
4620 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
4621
4622 r = copy_tree_at(
4623 sfd, ".",
4624 pfd, fn,
4625 UID_INVALID, GID_INVALID,
4626 COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
4627 denylist, subvolumes_by_source_inode);
4628 } else
4629 r = copy_tree_at(
4630 sfd, ".",
4631 tfd, ".",
4632 UID_INVALID, GID_INVALID,
4633 COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
4634 denylist, subvolumes_by_source_inode);
4635 if (r < 0)
4636 return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m",
4637 strempty(arg_copy_source), *source, strempty(root), *target);
4638 } else {
4639 _cleanup_free_ char *dn = NULL, *fn = NULL;
4640
4641 /* We are looking at a regular file */
4642
4643 r = path_extract_filename(*target, &fn);
4644 if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
4645 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
4646 "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
4647 if (r < 0)
4648 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
4649
4650 r = path_extract_directory(*target, &dn);
4651 if (r < 0)
4652 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
4653
4654 r = mkdir_p_root(root, dn, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4655 if (r < 0)
4656 return log_error_errno(r, "Failed to create parent directory: %m");
4657
4658 pfd = chase_and_open(dn, root, CHASE_PREFIX_ROOT, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
4659 if (pfd < 0)
4660 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
4661
4662 tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
4663 if (tfd < 0)
4664 return log_error_errno(errno, "Failed to create target file '%s': %m", *target);
4665
4666 r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_SIGINT|COPY_TRUNCATE);
4667 if (r < 0)
4668 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_copy_source), *target);
4669
4670 (void) copy_xattr(sfd, NULL, tfd, NULL, COPY_ALL_XATTRS);
4671 (void) copy_access(sfd, tfd);
4672 (void) copy_times(sfd, tfd, 0);
4673 }
4674 }
4675
4676 return 0;
4677 }
4678
4679 static int do_make_directories(Partition *p, const char *root) {
4680 int r;
4681
4682 assert(p);
4683 assert(root);
4684
4685 STRV_FOREACH(d, p->make_directories) {
4686 r = mkdir_p_root(root, *d, UID_INVALID, GID_INVALID, 0755, p->subvolumes);
4687 if (r < 0)
4688 return log_error_errno(r, "Failed to create directory '%s' in file system: %m", *d);
4689 }
4690
4691 return 0;
4692 }
4693
4694 static bool partition_needs_populate(Partition *p) {
4695 assert(p);
4696 return !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories);
4697 }
4698
4699 static int partition_populate_directory(Context *context, Partition *p, char **ret) {
4700 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
4701 const char *vt;
4702 int r;
4703
4704 assert(ret);
4705
4706 log_info("Populating %s filesystem.", p->format);
4707
4708 r = var_tmp_dir(&vt);
4709 if (r < 0)
4710 return log_error_errno(r, "Could not determine temporary directory: %m");
4711
4712 r = tempfn_random_child(vt, "repart", &root);
4713 if (r < 0)
4714 return log_error_errno(r, "Failed to generate temporary directory: %m");
4715
4716 r = mkdir(root, 0755);
4717 if (r < 0)
4718 return log_error_errno(errno, "Failed to create temporary directory: %m");
4719
4720 r = do_copy_files(context, p, root);
4721 if (r < 0)
4722 return r;
4723
4724 r = do_make_directories(p, root);
4725 if (r < 0)
4726 return r;
4727
4728 log_info("Successfully populated %s filesystem.", p->format);
4729
4730 *ret = TAKE_PTR(root);
4731 return 0;
4732 }
4733
4734 static int partition_populate_filesystem(Context *context, Partition *p, const char *node) {
4735 int r;
4736
4737 assert(p);
4738 assert(node);
4739
4740 log_info("Populating %s filesystem.", p->format);
4741
4742 /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to
4743 * appear in the host namespace. Hence we fork a child that has its own file system namespace and
4744 * detached mount propagation. */
4745
4746 r = safe_fork("(sd-copy)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
4747 if (r < 0)
4748 return r;
4749 if (r == 0) {
4750 static const char fs[] = "/run/systemd/mount-root";
4751 /* This is a child process with its own mount namespace and propagation to host turned off */
4752
4753 r = mkdir_p(fs, 0700);
4754 if (r < 0) {
4755 log_error_errno(r, "Failed to create mount point: %m");
4756 _exit(EXIT_FAILURE);
4757 }
4758
4759 if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0)
4760 _exit(EXIT_FAILURE);
4761
4762 if (do_copy_files(context, p, fs) < 0)
4763 _exit(EXIT_FAILURE);
4764
4765 if (do_make_directories(p, fs) < 0)
4766 _exit(EXIT_FAILURE);
4767
4768 r = syncfs_path(AT_FDCWD, fs);
4769 if (r < 0) {
4770 log_error_errno(r, "Failed to synchronize written files: %m");
4771 _exit(EXIT_FAILURE);
4772 }
4773
4774 _exit(EXIT_SUCCESS);
4775 }
4776
4777 log_info("Successfully populated %s filesystem.", p->format);
4778 return 0;
4779 }
4780
4781 static int context_mkfs(Context *context) {
4782 int r;
4783
4784 assert(context);
4785
4786 /* Make a file system */
4787
4788 LIST_FOREACH(partitions, p, context->partitions) {
4789 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
4790 _cleanup_(partition_target_freep) PartitionTarget *t = NULL;
4791 _cleanup_strv_free_ char **extra_mkfs_options = NULL;
4792
4793 if (p->dropped)
4794 continue;
4795
4796 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
4797 continue;
4798
4799 if (!p->format)
4800 continue;
4801
4802 /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
4803 if (p->copy_blocks_fd >= 0)
4804 continue;
4805
4806 if (partition_type_defer(&p->type))
4807 continue;
4808
4809 assert(p->offset != UINT64_MAX);
4810 assert(p->new_size != UINT64_MAX);
4811 assert(p->new_size >= (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
4812
4813 /* If we're doing encryption, we make sure we keep free space at the end which is required
4814 * for cryptsetup's offline encryption. */
4815 r = partition_target_prepare(context, p,
4816 p->new_size - (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0),
4817 /*need_path=*/ true,
4818 &t);
4819 if (r < 0)
4820 return r;
4821
4822 if (p->encrypt != ENCRYPT_OFF && t->loop) {
4823 r = partition_target_grow(t, p->new_size);
4824 if (r < 0)
4825 return r;
4826
4827 r = partition_encrypt(context, p, t, /* offline = */ false);
4828 if (r < 0)
4829 return log_error_errno(r, "Failed to encrypt device: %m");
4830 }
4831
4832 log_info("Formatting future partition %" PRIu64 ".", p->partno);
4833
4834 /* If we're not writing to a loop device or if we're populating a read-only filesystem, we
4835 * have to populate using the filesystem's mkfs's --root (or equivalent) option. To do that,
4836 * we need to set up the final directory tree beforehand. */
4837
4838 if (partition_needs_populate(p) && (!t->loop || fstype_is_ro(p->format))) {
4839 if (!mkfs_supports_root_option(p->format))
4840 return log_error_errno(SYNTHETIC_ERRNO(ENODEV),
4841 "Loop device access is required to populate %s filesystems.",
4842 p->format);
4843
4844 r = partition_populate_directory(context, p, &root);
4845 if (r < 0)
4846 return r;
4847 }
4848
4849 r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options);
4850 if (r < 0)
4851 return log_error_errno(r,
4852 "Failed to determine mkfs command line options for '%s': %m",
4853 p->format);
4854
4855 r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root,
4856 p->fs_uuid, arg_discard, /* quiet = */ false,
4857 context->fs_sector_size, extra_mkfs_options);
4858 if (r < 0)
4859 return r;
4860
4861 /* The mkfs binary we invoked might have removed our temporary file when we're not operating
4862 * on a loop device, so let's make sure we open the file again to make sure our file
4863 * descriptor points to any potential new file. */
4864
4865 if (t->fd >= 0 && t->path && !t->loop) {
4866 safe_close(t->fd);
4867 t->fd = open(t->path, O_RDWR|O_CLOEXEC);
4868 if (t->fd < 0)
4869 return log_error_errno(errno, "Failed to reopen temporary file: %m");
4870 }
4871
4872 log_info("Successfully formatted future partition %" PRIu64 ".", p->partno);
4873
4874 /* If we're writing to a loop device, we can now mount the empty filesystem and populate it. */
4875 if (partition_needs_populate(p) && !root) {
4876 assert(t->loop);
4877
4878 r = partition_populate_filesystem(context, p, partition_target_path(t));
4879 if (r < 0)
4880 return r;
4881 }
4882
4883 if (p->encrypt != ENCRYPT_OFF && !t->loop) {
4884 r = partition_target_grow(t, p->new_size);
4885 if (r < 0)
4886 return r;
4887
4888 r = partition_encrypt(context, p, t, /* offline = */ true);
4889 if (r < 0)
4890 return log_error_errno(r, "Failed to encrypt device: %m");
4891 }
4892
4893 /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and
4894 * if we don't sync before detaching a block device the in-flight sectors possibly won't hit
4895 * the disk. */
4896
4897 r = partition_target_sync(context, p, t);
4898 if (r < 0)
4899 return r;
4900
4901 if (p->siblings[VERITY_HASH] && !partition_type_defer(&p->siblings[VERITY_HASH]->type)) {
4902 r = partition_format_verity_hash(context, p->siblings[VERITY_HASH],
4903 /* node = */ NULL, partition_target_path(t));
4904 if (r < 0)
4905 return r;
4906 }
4907
4908 if (p->siblings[VERITY_SIG] && !partition_type_defer(&p->siblings[VERITY_SIG]->type)) {
4909 r = partition_format_verity_sig(context, p->siblings[VERITY_SIG]);
4910 if (r < 0)
4911 return r;
4912 }
4913 }
4914
4915 return 0;
4916 }
4917
4918 static int parse_x509_certificate(const char *certificate, size_t certificate_size, X509 **ret) {
4919 #if HAVE_OPENSSL
4920 _cleanup_(X509_freep) X509 *cert = NULL;
4921 _cleanup_(BIO_freep) BIO *cb = NULL;
4922
4923 assert(certificate);
4924 assert(certificate_size > 0);
4925 assert(ret);
4926
4927 cb = BIO_new_mem_buf(certificate, certificate_size);
4928 if (!cb)
4929 return log_oom();
4930
4931 cert = PEM_read_bio_X509(cb, NULL, NULL, NULL);
4932 if (!cert)
4933 return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s",
4934 ERR_error_string(ERR_get_error(), NULL));
4935
4936 if (ret)
4937 *ret = TAKE_PTR(cert);
4938
4939 return 0;
4940 #else
4941 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot parse X509 certificate.");
4942 #endif
4943 }
4944
4945 static int parse_private_key(const char *key, size_t key_size, EVP_PKEY **ret) {
4946 #if HAVE_OPENSSL
4947 _cleanup_(BIO_freep) BIO *kb = NULL;
4948 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pk = NULL;
4949
4950 assert(key);
4951 assert(key_size > 0);
4952 assert(ret);
4953
4954 kb = BIO_new_mem_buf(key, key_size);
4955 if (!kb)
4956 return log_oom();
4957
4958 pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL);
4959 if (!pk)
4960 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s",
4961 ERR_error_string(ERR_get_error(), NULL));
4962
4963 if (ret)
4964 *ret = TAKE_PTR(pk);
4965
4966 return 0;
4967 #else
4968 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL is not supported, cannot parse private key.");
4969 #endif
4970 }
4971
4972 static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
4973 struct {
4974 sd_id128_t type_uuid;
4975 uint64_t counter;
4976 } _packed_ plaintext = {};
4977 union {
4978 uint8_t md[SHA256_DIGEST_SIZE];
4979 sd_id128_t id;
4980 } result;
4981
4982 uint64_t k = 0;
4983 int r;
4984
4985 assert(context);
4986 assert(p);
4987 assert(ret);
4988
4989 /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
4990 * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
4991 * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
4992 * installation we are processing, but if random behaviour is desired can be random, too. We use the
4993 * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
4994 * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
4995 * second and later partition of the same type) if we have more than one partition of the same
4996 * time. Or in other words:
4997 *
4998 * With:
4999 * SEED := /etc/machine-id
5000 *
5001 * If first partition instance of type TYPE_UUID:
5002 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
5003 *
5004 * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
5005 * PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
5006 */
5007
5008 LIST_FOREACH(partitions, q, context->partitions) {
5009 if (p == q)
5010 break;
5011
5012 if (!sd_id128_equal(p->type.uuid, q->type.uuid))
5013 continue;
5014
5015 k++;
5016 }
5017
5018 plaintext.type_uuid = p->type.uuid;
5019 plaintext.counter = htole64(k);
5020
5021 hmac_sha256(context->seed.bytes, sizeof(context->seed.bytes),
5022 &plaintext,
5023 k == 0 ? sizeof(sd_id128_t) : sizeof(plaintext),
5024 result.md);
5025
5026 /* Take the first half, mark it as v4 UUID */
5027 assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
5028 result.id = id128_make_v4_uuid(result.id);
5029
5030 /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
5031 LIST_FOREACH(partitions, q, context->partitions) {
5032 if (p == q)
5033 continue;
5034
5035 if (sd_id128_in_set(result.id, q->current_uuid, q->new_uuid)) {
5036 log_warning("Partition UUID calculated from seed for partition %" PRIu64 " already used, reverting to randomized UUID.", p->partno);
5037
5038 r = sd_id128_randomize(&result.id);
5039 if (r < 0)
5040 return log_error_errno(r, "Failed to generate randomized UUID: %m");
5041
5042 break;
5043 }
5044 }
5045
5046 *ret = result.id;
5047 return 0;
5048 }
5049
5050 static int partition_acquire_label(Context *context, Partition *p, char **ret) {
5051 _cleanup_free_ char *label = NULL;
5052 const char *prefix;
5053 unsigned k = 1;
5054
5055 assert(context);
5056 assert(p);
5057 assert(ret);
5058
5059 prefix = gpt_partition_type_uuid_to_string(p->type.uuid);
5060 if (!prefix)
5061 prefix = "linux";
5062
5063 for (;;) {
5064 const char *ll = label ?: prefix;
5065 bool retry = false;
5066
5067 LIST_FOREACH(partitions, q, context->partitions) {
5068 if (p == q)
5069 break;
5070
5071 if (streq_ptr(ll, q->current_label) ||
5072 streq_ptr(ll, q->new_label)) {
5073 retry = true;
5074 break;
5075 }
5076 }
5077
5078 if (!retry)
5079 break;
5080
5081 label = mfree(label);
5082 if (asprintf(&label, "%s-%u", prefix, ++k) < 0)
5083 return log_oom();
5084 }
5085
5086 if (!label) {
5087 label = strdup(prefix);
5088 if (!label)
5089 return log_oom();
5090 }
5091
5092 *ret = TAKE_PTR(label);
5093 return 0;
5094 }
5095
5096 static int context_acquire_partition_uuids_and_labels(Context *context) {
5097 int r;
5098
5099 assert(context);
5100
5101 LIST_FOREACH(partitions, p, context->partitions) {
5102 sd_id128_t uuid;
5103
5104 /* Never touch foreign partitions */
5105 if (PARTITION_IS_FOREIGN(p)) {
5106 p->new_uuid = p->current_uuid;
5107
5108 if (p->current_label) {
5109 r = free_and_strdup_warn(&p->new_label, strempty(p->current_label));
5110 if (r < 0)
5111 return r;
5112 }
5113
5114 continue;
5115 }
5116
5117 if (!sd_id128_is_null(p->current_uuid))
5118 p->new_uuid = uuid = p->current_uuid; /* Never change initialized UUIDs */
5119 else if (p->new_uuid_is_set)
5120 uuid = p->new_uuid;
5121 else {
5122 /* Not explicitly set by user! */
5123 r = partition_acquire_uuid(context, p, &uuid);
5124 if (r < 0)
5125 return r;
5126
5127 /* The final verity hash/data UUIDs can only be determined after formatting the
5128 * verity hash partition. However, we still want to use the generated partition UUID
5129 * to derive other UUIDs to keep things unique and reproducible, so we always
5130 * generate a UUID if none is set, but we only use it as the actual partition UUID if
5131 * verity is not configured. */
5132 if (!IN_SET(p->verity, VERITY_DATA, VERITY_HASH)) {
5133 p->new_uuid = uuid;
5134 p->new_uuid_is_set = true;
5135 }
5136 }
5137
5138 /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid",
5139 * keyed off the partition UUID. */
5140 r = derive_uuid(uuid, "file-system-uuid", &p->fs_uuid);
5141 if (r < 0)
5142 return r;
5143
5144 if (p->encrypt != ENCRYPT_OFF) {
5145 r = derive_uuid(uuid, "luks-uuid", &p->luks_uuid);
5146 if (r < 0)
5147 return r;
5148 }
5149
5150 /* Derive the verity salt and verity superblock UUID from the seed to keep them reproducible */
5151 if (p->verity == VERITY_HASH) {
5152 derive_salt(context->seed, "verity-salt", p->verity_salt);
5153
5154 r = derive_uuid(context->seed, "verity-uuid", &p->verity_uuid);
5155 if (r < 0)
5156 return log_error_errno(r, "Failed to acquire verity uuid: %m");
5157 }
5158
5159 if (!isempty(p->current_label)) {
5160 /* never change initialized labels */
5161 r = free_and_strdup_warn(&p->new_label, p->current_label);
5162 if (r < 0)
5163 return r;
5164 } else if (!p->new_label) {
5165 /* Not explicitly set by user! */
5166
5167 r = partition_acquire_label(context, p, &p->new_label);
5168 if (r < 0)
5169 return r;
5170 }
5171 }
5172
5173 return 0;
5174 }
5175
5176 static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
5177 _cleanup_free_ char *a = NULL;
5178
5179 for (unsigned i = 0; i < sizeof(flags) * 8; i++) {
5180 uint64_t bit = UINT64_C(1) << i;
5181 char buf[DECIMAL_STR_MAX(unsigned)+1];
5182
5183 if (!FLAGS_SET(flags, bit))
5184 continue;
5185
5186 xsprintf(buf, "%u", i);
5187 if (!strextend_with_separator(&a, ",", buf))
5188 return -ENOMEM;
5189 }
5190
5191 return fdisk_partition_set_attrs(q, a);
5192 }
5193
5194 static uint64_t partition_merge_flags(Partition *p) {
5195 uint64_t f;
5196
5197 assert(p);
5198
5199 f = p->gpt_flags;
5200
5201 if (p->no_auto >= 0) {
5202 if (gpt_partition_type_knows_no_auto(p->type))
5203 SET_FLAG(f, SD_GPT_FLAG_NO_AUTO, p->no_auto);
5204 else {
5205 char buffer[SD_ID128_UUID_STRING_MAX];
5206 log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
5207 yes_no(p->no_auto),
5208 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5209 }
5210 }
5211
5212 if (p->read_only >= 0) {
5213 if (gpt_partition_type_knows_read_only(p->type))
5214 SET_FLAG(f, SD_GPT_FLAG_READ_ONLY, p->read_only);
5215 else {
5216 char buffer[SD_ID128_UUID_STRING_MAX];
5217 log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
5218 yes_no(p->read_only),
5219 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5220 }
5221 }
5222
5223 if (p->growfs >= 0) {
5224 if (gpt_partition_type_knows_growfs(p->type))
5225 SET_FLAG(f, SD_GPT_FLAG_GROWFS, p->growfs);
5226 else {
5227 char buffer[SD_ID128_UUID_STRING_MAX];
5228 log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
5229 yes_no(p->growfs),
5230 gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
5231 }
5232 }
5233
5234 return f;
5235 }
5236
5237 static int context_mangle_partitions(Context *context) {
5238 int r;
5239
5240 assert(context);
5241
5242 LIST_FOREACH(partitions, p, context->partitions) {
5243 if (p->dropped)
5244 continue;
5245
5246 if (partition_type_defer(&p->type))
5247 continue;
5248
5249 assert(p->new_size != UINT64_MAX);
5250 assert(p->offset != UINT64_MAX);
5251 assert(p->partno != UINT64_MAX);
5252
5253 if (PARTITION_EXISTS(p)) {
5254 bool changed = false;
5255
5256 assert(p->current_partition);
5257
5258 if (p->new_size != p->current_size) {
5259 assert(p->new_size >= p->current_size);
5260 assert(p->new_size % context->sector_size == 0);
5261
5262 r = fdisk_partition_size_explicit(p->current_partition, true);
5263 if (r < 0)
5264 return log_error_errno(r, "Failed to enable explicit sizing: %m");
5265
5266 r = fdisk_partition_set_size(p->current_partition, p->new_size / context->sector_size);
5267 if (r < 0)
5268 return log_error_errno(r, "Failed to grow partition: %m");
5269
5270 log_info("Growing existing partition %" PRIu64 ".", p->partno);
5271 changed = true;
5272 }
5273
5274 if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
5275 r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
5276 if (r < 0)
5277 return log_error_errno(r, "Failed to set partition UUID: %m");
5278
5279 log_info("Initializing UUID of existing partition %" PRIu64 ".", p->partno);
5280 changed = true;
5281 }
5282
5283 if (!streq_ptr(p->new_label, p->current_label)) {
5284 r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
5285 if (r < 0)
5286 return log_error_errno(r, "Failed to set partition label: %m");
5287
5288 log_info("Setting partition label of existing partition %" PRIu64 ".", p->partno);
5289 changed = true;
5290 }
5291
5292 if (changed) {
5293 assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
5294
5295 r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
5296 if (r < 0)
5297 return log_error_errno(r, "Failed to update partition: %m");
5298 }
5299 } else {
5300 _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
5301 _cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
5302
5303 assert(!p->new_partition);
5304 assert(p->offset % context->sector_size == 0);
5305 assert(p->new_size % context->sector_size == 0);
5306 assert(p->new_label);
5307
5308 t = fdisk_new_parttype();
5309 if (!t)
5310 return log_oom();
5311
5312 r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid));
5313 if (r < 0)
5314 return log_error_errno(r, "Failed to initialize partition type: %m");
5315
5316 q = fdisk_new_partition();
5317 if (!q)
5318 return log_oom();
5319
5320 r = fdisk_partition_set_type(q, t);
5321 if (r < 0)
5322 return log_error_errno(r, "Failed to set partition type: %m");
5323
5324 r = fdisk_partition_size_explicit(q, true);
5325 if (r < 0)
5326 return log_error_errno(r, "Failed to enable explicit sizing: %m");
5327
5328 r = fdisk_partition_set_start(q, p->offset / context->sector_size);
5329 if (r < 0)
5330 return log_error_errno(r, "Failed to position partition: %m");
5331
5332 r = fdisk_partition_set_size(q, p->new_size / context->sector_size);
5333 if (r < 0)
5334 return log_error_errno(r, "Failed to grow partition: %m");
5335
5336 r = fdisk_partition_set_partno(q, p->partno);
5337 if (r < 0)
5338 return log_error_errno(r, "Failed to set partition number: %m");
5339
5340 r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
5341 if (r < 0)
5342 return log_error_errno(r, "Failed to set partition UUID: %m");
5343
5344 r = fdisk_partition_set_name(q, strempty(p->new_label));
5345 if (r < 0)
5346 return log_error_errno(r, "Failed to set partition label: %m");
5347
5348 /* Merge the no auto + read only + growfs setting with the literal flags, and set them for the partition */
5349 r = set_gpt_flags(q, partition_merge_flags(p));
5350 if (r < 0)
5351 return log_error_errno(r, "Failed to set GPT partition flags: %m");
5352
5353 log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
5354
5355 r = fdisk_add_partition(context->fdisk_context, q, NULL);
5356 if (r < 0)
5357 return log_error_errno(r, "Failed to add partition: %m");
5358
5359 assert(!p->new_partition);
5360 p->new_partition = TAKE_PTR(q);
5361 }
5362 }
5363
5364 return 0;
5365 }
5366
5367 static int split_name_printf(Partition *p, char **ret) {
5368 assert(p);
5369
5370 const Specifier table[] = {
5371 { 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type.uuid) },
5372 { 'T', specifier_id128, &p->type.uuid },
5373 { 'U', specifier_id128, &p->new_uuid },
5374 { 'n', specifier_uint64, &p->partno },
5375
5376 COMMON_SYSTEM_SPECIFIERS,
5377 {}
5378 };
5379
5380 return specifier_printf(p->split_name_format, NAME_MAX, table, arg_root, p, ret);
5381 }
5382
5383 static int split_node(const char *node, char **ret_base, char **ret_ext) {
5384 _cleanup_free_ char *base = NULL, *ext = NULL;
5385 char *e;
5386 int r;
5387
5388 assert(node);
5389 assert(ret_base);
5390 assert(ret_ext);
5391
5392 r = path_extract_filename(node, &base);
5393 if (r == O_DIRECTORY || r == -EADDRNOTAVAIL)
5394 return log_error_errno(r, "Device node %s cannot be a directory", node);
5395 if (r < 0)
5396 return log_error_errno(r, "Failed to extract filename from %s: %m", node);
5397
5398 e = endswith(base, ".raw");
5399 if (e) {
5400 ext = strdup(e);
5401 if (!ext)
5402 return log_oom();
5403
5404 *e = 0;
5405 }
5406
5407 *ret_base = TAKE_PTR(base);
5408 *ret_ext = TAKE_PTR(ext);
5409
5410 return 0;
5411 }
5412
5413 static int split_name_resolve(Context *context) {
5414 _cleanup_free_ char *parent = NULL, *base = NULL, *ext = NULL;
5415 int r;
5416
5417 assert(context);
5418
5419 r = path_extract_directory(context->node, &parent);
5420 if (r < 0 && r != -EDESTADDRREQ)
5421 return log_error_errno(r, "Failed to extract directory from %s: %m", context->node);
5422
5423 r = split_node(context->node, &base, &ext);
5424 if (r < 0)
5425 return r;
5426
5427 LIST_FOREACH(partitions, p, context->partitions) {
5428 _cleanup_free_ char *resolved = NULL;
5429
5430 if (p->dropped)
5431 continue;
5432
5433 if (!p->split_name_format)
5434 continue;
5435
5436 r = split_name_printf(p, &resolved);
5437 if (r < 0)
5438 return log_error_errno(r, "Failed to resolve specifiers in %s: %m", p->split_name_format);
5439
5440 if (parent)
5441 p->split_path = strjoin(parent, "/", base, ".", resolved, ext);
5442 else
5443 p->split_path = strjoin(base, ".", resolved, ext);
5444 if (!p->split_path)
5445 return log_oom();
5446 }
5447
5448 LIST_FOREACH(partitions, p, context->partitions) {
5449 if (!p->split_path)
5450 continue;
5451
5452 LIST_FOREACH(partitions, q, context->partitions) {
5453 if (p == q)
5454 continue;
5455
5456 if (!q->split_path)
5457 continue;
5458
5459 if (!streq(p->split_path, q->split_path))
5460 continue;
5461
5462 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
5463 "%s and %s have the same resolved split name \"%s\", refusing",
5464 p->definition_path, q->definition_path, p->split_path);
5465 }
5466 }
5467
5468 return 0;
5469 }
5470
5471 static int context_split(Context *context) {
5472 int fd = -EBADF, r;
5473
5474 if (!arg_split)
5475 return 0;
5476
5477 assert(context);
5478
5479 /* We can't do resolution earlier because the partition UUIDs for verity partitions are only filled
5480 * in after they've been generated. */
5481
5482 r = split_name_resolve(context);
5483 if (r < 0)
5484 return r;
5485
5486 LIST_FOREACH(partitions, p, context->partitions) {
5487 _cleanup_close_ int fdt = -EBADF;
5488
5489 if (p->dropped)
5490 continue;
5491
5492 if (!p->split_path)
5493 continue;
5494
5495 if (partition_type_defer(&p->type))
5496 continue;
5497
5498 fdt = open(p->split_path, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL, 0666);
5499 if (fdt < 0)
5500 return log_error_errno(fdt, "Failed to open split partition file %s: %m", p->split_path);
5501
5502 if (fd < 0)
5503 assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
5504
5505 if (lseek(fd, p->offset, SEEK_SET) < 0)
5506 return log_error_errno(errno, "Failed to seek to partition offset: %m");
5507
5508 r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
5509 if (r < 0)
5510 return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
5511 }
5512
5513 return 0;
5514 }
5515
5516 static int context_write_partition_table(Context *context) {
5517 _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
5518 int capable, r;
5519
5520 assert(context);
5521
5522 if (!context->from_scratch && !context_changed(context)) {
5523 log_info("No changes.");
5524 return 0;
5525 }
5526
5527 if (arg_dry_run) {
5528 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
5529 return 0;
5530 }
5531
5532 log_info("Applying changes to %s.", context->node);
5533
5534 if (context->from_scratch && arg_empty != EMPTY_CREATE) {
5535 /* Erase everything if we operate from scratch, except if the image was just created anyway, and thus is definitely empty. */
5536 r = context_wipe_range(context, 0, context->total);
5537 if (r < 0)
5538 return r;
5539
5540 log_info("Wiped block device.");
5541
5542 if (arg_discard) {
5543 r = context_discard_range(context, 0, context->total);
5544 if (r == -EOPNOTSUPP)
5545 log_info("Storage does not support discard, not discarding entire block device data.");
5546 else if (r < 0)
5547 return log_error_errno(r, "Failed to discard entire block device: %m");
5548 else if (r > 0)
5549 log_info("Discarded entire block device.");
5550 }
5551 }
5552
5553 r = fdisk_get_partitions(context->fdisk_context, &original_table);
5554 if (r < 0)
5555 return log_error_errno(r, "Failed to acquire partition table: %m");
5556
5557 /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
5558 * gaps between partitions, just to be sure. */
5559 r = context_wipe_and_discard(context);
5560 if (r < 0)
5561 return r;
5562
5563 r = context_copy_blocks(context);
5564 if (r < 0)
5565 return r;
5566
5567 r = context_mkfs(context);
5568 if (r < 0)
5569 return r;
5570
5571 r = context_mangle_partitions(context);
5572 if (r < 0)
5573 return r;
5574
5575 log_info("Writing new partition table.");
5576
5577 r = fdisk_write_disklabel(context->fdisk_context);
5578 if (r < 0)
5579 return log_error_errno(r, "Failed to write partition table: %m");
5580
5581 capable = blockdev_partscan_enabled(fdisk_get_devfd(context->fdisk_context));
5582 if (capable == -ENOTBLK)
5583 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
5584 else if (capable < 0)
5585 return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
5586 else if (capable > 0) {
5587 log_info("Telling kernel to reread partition table.");
5588
5589 if (context->from_scratch)
5590 r = fdisk_reread_partition_table(context->fdisk_context);
5591 else
5592 r = fdisk_reread_changes(context->fdisk_context, original_table);
5593 if (r < 0)
5594 return log_error_errno(r, "Failed to reread partition table: %m");
5595 } else
5596 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
5597
5598 log_info("All done.");
5599
5600 return 0;
5601 }
5602
5603 static int context_read_seed(Context *context, const char *root) {
5604 int r;
5605
5606 assert(context);
5607
5608 if (!sd_id128_is_null(context->seed))
5609 return 0;
5610
5611 if (!arg_randomize) {
5612 r = id128_get_machine(root, &context->seed);
5613 if (r >= 0)
5614 return 0;
5615
5616 if (!ERRNO_IS_MACHINE_ID_UNSET(r))
5617 return log_error_errno(r, "Failed to parse machine ID of image: %m");
5618
5619 log_info("No machine ID set, using randomized partition UUIDs.");
5620 }
5621
5622 r = sd_id128_randomize(&context->seed);
5623 if (r < 0)
5624 return log_error_errno(r, "Failed to generate randomized seed: %m");
5625
5626 return 0;
5627 }
5628
5629 static int context_factory_reset(Context *context) {
5630 size_t n = 0;
5631 int r;
5632
5633 assert(context);
5634
5635 if (arg_factory_reset <= 0)
5636 return 0;
5637
5638 if (context->from_scratch) /* Nothing to reset if we start from scratch */
5639 return 0;
5640
5641 if (arg_dry_run) {
5642 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
5643 return 0;
5644 }
5645
5646 log_info("Applying factory reset.");
5647
5648 LIST_FOREACH(partitions, p, context->partitions) {
5649
5650 if (!p->factory_reset || !PARTITION_EXISTS(p))
5651 continue;
5652
5653 assert(p->partno != UINT64_MAX);
5654
5655 log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
5656
5657 r = fdisk_delete_partition(context->fdisk_context, p->partno);
5658 if (r < 0)
5659 return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
5660
5661 n++;
5662 }
5663
5664 if (n == 0) {
5665 log_info("Factory reset requested, but no partitions to delete found.");
5666 return 0;
5667 }
5668
5669 r = fdisk_write_disklabel(context->fdisk_context);
5670 if (r < 0)
5671 return log_error_errno(r, "Failed to write disk label: %m");
5672
5673 log_info("Successfully deleted %zu partitions.", n);
5674 return 1;
5675 }
5676
5677 static int context_can_factory_reset(Context *context) {
5678 assert(context);
5679
5680 LIST_FOREACH(partitions, p, context->partitions)
5681 if (p->factory_reset && PARTITION_EXISTS(p))
5682 return true;
5683
5684 return false;
5685 }
5686
5687 static int resolve_copy_blocks_auto_candidate(
5688 dev_t partition_devno,
5689 GptPartitionType partition_type,
5690 dev_t restrict_devno,
5691 sd_id128_t *ret_uuid) {
5692
5693 _cleanup_(blkid_free_probep) blkid_probe b = NULL;
5694 _cleanup_close_ int fd = -EBADF;
5695 _cleanup_free_ char *p = NULL;
5696 const char *pttype, *t;
5697 sd_id128_t pt_parsed, u;
5698 blkid_partition pp;
5699 dev_t whole_devno;
5700 blkid_partlist pl;
5701 int r;
5702
5703 /* Checks if the specified partition has the specified GPT type UUID, and is located on the specified
5704 * 'restrict_devno' device. The type check is particularly relevant if we have Verity volume which is
5705 * backed by two separate partitions: the data and the hash partitions, and we need to find the right
5706 * one of the two. */
5707
5708 r = block_get_whole_disk(partition_devno, &whole_devno);
5709 if (r < 0)
5710 return log_error_errno(
5711 r,
5712 "Unable to determine containing block device of partition %u:%u: %m",
5713 major(partition_devno), minor(partition_devno));
5714
5715 if (restrict_devno != (dev_t) -1 &&
5716 restrict_devno != whole_devno)
5717 return log_error_errno(
5718 SYNTHETIC_ERRNO(EPERM),
5719 "Partition %u:%u is located outside of block device %u:%u, refusing.",
5720 major(partition_devno), minor(partition_devno),
5721 major(restrict_devno), minor(restrict_devno));
5722
5723 fd = r = device_open_from_devnum(S_IFBLK, whole_devno, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &p);
5724 if (r < 0)
5725 return log_error_errno(r, "Failed to open block device " DEVNUM_FORMAT_STR ": %m",
5726 DEVNUM_FORMAT_VAL(whole_devno));
5727
5728 b = blkid_new_probe();
5729 if (!b)
5730 return log_oom();
5731
5732 errno = 0;
5733 r = blkid_probe_set_device(b, fd, 0, 0);
5734 if (r != 0)
5735 return log_error_errno(errno_or_else(ENOMEM), "Failed to open block device '%s': %m", p);
5736
5737 (void) blkid_probe_enable_partitions(b, 1);
5738 (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
5739
5740 errno = 0;
5741 r = blkid_do_safeprobe(b);
5742 if (r == _BLKID_SAFEPROBE_ERROR)
5743 return log_error_errno(errno_or_else(EIO), "Unable to probe for partition table of '%s': %m", p);
5744 if (IN_SET(r, _BLKID_SAFEPROBE_AMBIGUOUS, _BLKID_SAFEPROBE_NOT_FOUND)) {
5745 log_debug("Didn't find partition table on block device '%s'.", p);
5746 return false;
5747 }
5748
5749 assert(r == _BLKID_SAFEPROBE_FOUND);
5750
5751 (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
5752 if (!streq_ptr(pttype, "gpt")) {
5753 log_debug("Didn't find a GPT partition table on '%s'.", p);
5754 return false;
5755 }
5756
5757 errno = 0;
5758 pl = blkid_probe_get_partitions(b);
5759 if (!pl)
5760 return log_error_errno(errno_or_else(EIO), "Unable read partition table of '%s': %m", p);
5761
5762 pp = blkid_partlist_devno_to_partition(pl, partition_devno);
5763 if (!pp) {
5764 log_debug("Partition %u:%u has no matching partition table entry on '%s'.",
5765 major(partition_devno), minor(partition_devno), p);
5766 return false;
5767 }
5768
5769 t = blkid_partition_get_type_string(pp);
5770 if (isempty(t)) {
5771 log_debug("Partition %u:%u has no type on '%s'.",
5772 major(partition_devno), minor(partition_devno), p);
5773 return false;
5774 }
5775
5776 r = sd_id128_from_string(t, &pt_parsed);
5777 if (r < 0) {
5778 log_debug_errno(r, "Failed to parse partition type \"%s\": %m", t);
5779 return false;
5780 }
5781
5782 if (!sd_id128_equal(pt_parsed, partition_type.uuid)) {
5783 log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
5784 major(partition_devno), minor(partition_devno),
5785 SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type.uuid));
5786 return false;
5787 }
5788
5789 r = blkid_partition_get_uuid_id128(pp, &u);
5790 if (r == -ENXIO) {
5791 log_debug_errno(r, "Partition " DEVNUM_FORMAT_STR " has no UUID.", DEVNUM_FORMAT_VAL(partition_devno));
5792 return false;
5793 }
5794 if (r < 0) {
5795 log_debug_errno(r, "Failed to read partition UUID of " DEVNUM_FORMAT_STR ": %m", DEVNUM_FORMAT_VAL(partition_devno));
5796 return false;
5797 }
5798
5799 log_debug("Automatically found partition " DEVNUM_FORMAT_STR " of right type " SD_ID128_FORMAT_STR ".",
5800 DEVNUM_FORMAT_VAL(partition_devno),
5801 SD_ID128_FORMAT_VAL(pt_parsed));
5802
5803 if (ret_uuid)
5804 *ret_uuid = u;
5805
5806 return true;
5807 }
5808
5809 static int find_backing_devno(
5810 const char *path,
5811 const char *root,
5812 dev_t *ret) {
5813
5814 _cleanup_free_ char *resolved = NULL;
5815 int r;
5816
5817 assert(path);
5818
5819 r = chase(path, root, CHASE_PREFIX_ROOT, &resolved, NULL);
5820 if (r < 0)
5821 return r;
5822
5823 r = path_is_mount_point(resolved, NULL, 0);
5824 if (r < 0)
5825 return r;
5826 if (r == 0) /* Not a mount point, then it's not a partition of its own, let's not automatically use it. */
5827 return -ENOENT;
5828
5829 r = get_block_device(resolved, ret);
5830 if (r < 0)
5831 return r;
5832 if (r == 0) /* Not backed by physical file system, we can't use this */
5833 return -ENOENT;
5834
5835 return 0;
5836 }
5837
5838 static int resolve_copy_blocks_auto(
5839 GptPartitionType type,
5840 const char *root,
5841 dev_t restrict_devno,
5842 dev_t *ret_devno,
5843 sd_id128_t *ret_uuid) {
5844
5845 const char *try1 = NULL, *try2 = NULL;
5846 char p[SYS_BLOCK_PATH_MAX("/slaves")];
5847 _cleanup_closedir_ DIR *d = NULL;
5848 sd_id128_t found_uuid = SD_ID128_NULL;
5849 dev_t devno, found = 0;
5850 int r;
5851
5852 /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
5853 * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
5854 * and restrict block device references in the --image= case to loopback block device we set up.
5855 *
5856 * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
5857 * thus declares which device (and its partition subdevices) we shall limit access to. If
5858 * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
5859 * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
5860
5861 if (restrict_devno == 0)
5862 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
5863 "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
5864
5865 /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
5866 * partitions in the host, using the appropriate directory as key and ensuring that the partition
5867 * type matches. */
5868
5869 if (type.designator == PARTITION_ROOT)
5870 try1 = "/";
5871 else if (type.designator == PARTITION_USR)
5872 try1 = "/usr/";
5873 else if (type.designator == PARTITION_ROOT_VERITY)
5874 try1 = "/";
5875 else if (type.designator == PARTITION_USR_VERITY)
5876 try1 = "/usr/";
5877 else if (type.designator == PARTITION_ESP) {
5878 try1 = "/efi/";
5879 try2 = "/boot/";
5880 } else if (type.designator == PARTITION_XBOOTLDR)
5881 try1 = "/boot/";
5882 else
5883 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
5884 "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
5885 SD_ID128_FORMAT_VAL(type.uuid));
5886
5887 r = find_backing_devno(try1, root, &devno);
5888 if (r == -ENOENT && try2)
5889 r = find_backing_devno(try2, root, &devno);
5890 if (r < 0)
5891 return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
5892 SD_ID128_FORMAT_VAL(type.uuid));
5893
5894 xsprintf_sys_block_path(p, "/slaves", devno);
5895 d = opendir(p);
5896 if (d) {
5897 struct dirent *de;
5898
5899 for (;;) {
5900 _cleanup_free_ char *q = NULL, *t = NULL;
5901 sd_id128_t u;
5902 dev_t sl;
5903
5904 errno = 0;
5905 de = readdir_no_dot(d);
5906 if (!de) {
5907 if (errno != 0)
5908 return log_error_errno(errno, "Failed to read directory '%s': %m", p);
5909
5910 break;
5911 }
5912
5913 if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
5914 continue;
5915
5916 q = path_join(p, de->d_name, "/dev");
5917 if (!q)
5918 return log_oom();
5919
5920 r = read_one_line_file(q, &t);
5921 if (r < 0)
5922 return log_error_errno(r, "Failed to read %s: %m", q);
5923
5924 r = parse_devnum(t, &sl);
5925 if (r < 0) {
5926 log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
5927 continue;
5928 }
5929 if (major(sl) == 0) {
5930 log_debug("Device backing %s is special, ignoring.", q);
5931 continue;
5932 }
5933
5934 r = resolve_copy_blocks_auto_candidate(sl, type, restrict_devno, &u);
5935 if (r < 0)
5936 return r;
5937 if (r > 0) {
5938 /* We found a matching one! */
5939 if (found != 0)
5940 return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
5941 "Multiple matching partitions found, refusing.");
5942
5943 found = sl;
5944 found_uuid = u;
5945 }
5946 }
5947 } else if (errno != ENOENT)
5948 return log_error_errno(errno, "Failed open %s: %m", p);
5949 else {
5950 r = resolve_copy_blocks_auto_candidate(devno, type, restrict_devno, &found_uuid);
5951 if (r < 0)
5952 return r;
5953 if (r > 0)
5954 found = devno;
5955 }
5956
5957 if (found == 0)
5958 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
5959 "Unable to automatically discover suitable partition to copy blocks from.");
5960
5961 if (ret_devno)
5962 *ret_devno = found;
5963
5964 if (ret_uuid)
5965 *ret_uuid = found_uuid;
5966
5967 return 0;
5968 }
5969
5970 static int context_open_copy_block_paths(
5971 Context *context,
5972 dev_t restrict_devno) {
5973
5974 int r;
5975
5976 assert(context);
5977
5978 LIST_FOREACH(partitions, p, context->partitions) {
5979 _cleanup_close_ int source_fd = -EBADF;
5980 _cleanup_free_ char *opened = NULL;
5981 sd_id128_t uuid = SD_ID128_NULL;
5982 uint64_t size;
5983 struct stat st;
5984
5985 if (p->copy_blocks_fd >= 0)
5986 continue;
5987
5988 assert(p->copy_blocks_size == UINT64_MAX);
5989
5990 if (PARTITION_EXISTS(p)) /* Never copy over partitions that already exist! */
5991 continue;
5992
5993 if (p->copy_blocks_path) {
5994
5995 source_fd = chase_and_open(p->copy_blocks_path, p->copy_blocks_root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
5996 if (source_fd < 0)
5997 return log_error_errno(source_fd, "Failed to open '%s': %m", p->copy_blocks_path);
5998
5999 if (fstat(source_fd, &st) < 0)
6000 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
6001
6002 if (!S_ISREG(st.st_mode) && restrict_devno != (dev_t) -1)
6003 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
6004 "Copying from block device node is not permitted in --image=/--root= mode, refusing.");
6005
6006 } else if (p->copy_blocks_auto) {
6007 dev_t devno = 0; /* Fake initialization to appease gcc. */
6008
6009 r = resolve_copy_blocks_auto(p->type, p->copy_blocks_root, restrict_devno, &devno, &uuid);
6010 if (r < 0)
6011 return r;
6012 assert(devno != 0);
6013
6014 source_fd = r = device_open_from_devnum(S_IFBLK, devno, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
6015 if (r < 0)
6016 return log_error_errno(r, "Failed to open automatically determined source block copy device " DEVNUM_FORMAT_STR ": %m",
6017 DEVNUM_FORMAT_VAL(devno));
6018
6019 if (fstat(source_fd, &st) < 0)
6020 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
6021 } else
6022 continue;
6023
6024 if (S_ISDIR(st.st_mode)) {
6025 _cleanup_free_ char *bdev = NULL;
6026 dev_t devt;
6027
6028 /* If the file is a directory, automatically find the backing block device */
6029
6030 if (major(st.st_dev) != 0)
6031 devt = st.st_dev;
6032 else {
6033 /* Special support for btrfs */
6034 r = btrfs_get_block_device_fd(source_fd, &devt);
6035 if (r == -EUCLEAN)
6036 return btrfs_log_dev_root(LOG_ERR, r, opened);
6037 if (r < 0)
6038 return log_error_errno(r, "Unable to determine backing block device of '%s': %m", opened);
6039 }
6040
6041 safe_close(source_fd);
6042
6043 source_fd = r = device_open_from_devnum(S_IFBLK, devt, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &bdev);
6044 if (r < 0)
6045 return log_error_errno(r, "Failed to open block device backing '%s': %m", opened);
6046
6047 if (fstat(source_fd, &st) < 0)
6048 return log_error_errno(errno, "Failed to stat block device '%s': %m", bdev);
6049 }
6050
6051 if (S_ISREG(st.st_mode))
6052 size = st.st_size;
6053 else if (S_ISBLK(st.st_mode)) {
6054 r = blockdev_get_device_size(source_fd, &size);
6055 if (r < 0)
6056 return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
6057 } else
6058 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);
6059
6060 if (size <= 0)
6061 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
6062 if (size % 512 != 0)
6063 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
6064
6065 p->copy_blocks_fd = TAKE_FD(source_fd);
6066 p->copy_blocks_size = size;
6067
6068 free_and_replace(p->copy_blocks_path, opened);
6069
6070 /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
6071 if (!p->new_uuid_is_set && !sd_id128_is_null(uuid)) {
6072 p->new_uuid = uuid;
6073 p->new_uuid_is_set = true;
6074 }
6075 }
6076
6077 return 0;
6078 }
6079
6080 static int fd_apparent_size(int fd, uint64_t *ret) {
6081 off_t initial = 0;
6082 uint64_t size = 0;
6083
6084 assert(fd >= 0);
6085 assert(ret);
6086
6087 initial = lseek(fd, 0, SEEK_CUR);
6088 if (initial < 0)
6089 return log_error_errno(errno, "Failed to get file offset: %m");
6090
6091 for (off_t off = 0;;) {
6092 off_t r;
6093
6094 r = lseek(fd, off, SEEK_DATA);
6095 if (r < 0 && errno == ENXIO)
6096 /* If errno == ENXIO, that means we've reached the final hole of the file and
6097 * that hole isn't followed by more data. */
6098 break;
6099 if (r < 0)
6100 return log_error_errno(errno, "Failed to seek data in file from offset %"PRIi64": %m", off);
6101
6102 off = r; /* Set the offset to the start of the data segment. */
6103
6104 /* After copying a potential hole, find the end of the data segment by looking for
6105 * the next hole. If we get ENXIO, we're at EOF. */
6106 r = lseek(fd, off, SEEK_HOLE);
6107 if (r < 0) {
6108 if (errno == ENXIO)
6109 break;
6110 return log_error_errno(errno, "Failed to seek hole in file from offset %"PRIi64": %m", off);
6111 }
6112
6113 size += r - off;
6114 off = r;
6115 }
6116
6117 if (lseek(fd, initial, SEEK_SET) < 0)
6118 return log_error_errno(errno, "Failed to reset file offset: %m");
6119
6120 *ret = size;
6121
6122 return 0;
6123 }
6124
6125 static int context_minimize(Context *context) {
6126 const char *vt = NULL;
6127 int r;
6128
6129 assert(context);
6130
6131 LIST_FOREACH(partitions, p, context->partitions) {
6132 _cleanup_(rm_rf_physical_and_freep) char *root = NULL;
6133 _cleanup_(unlink_and_freep) char *temp = NULL;
6134 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
6135 _cleanup_strv_free_ char **extra_mkfs_options = NULL;
6136 _cleanup_close_ int fd = -EBADF;
6137 _cleanup_free_ char *hint = NULL;
6138 sd_id128_t fs_uuid;
6139 struct stat st;
6140 uint64_t fsz;
6141
6142 if (p->dropped)
6143 continue;
6144
6145 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
6146 continue;
6147
6148 if (!p->format)
6149 continue;
6150
6151 if (p->copy_blocks_fd >= 0)
6152 continue;
6153
6154 if (p->minimize == MINIMIZE_OFF)
6155 continue;
6156
6157 if (!partition_needs_populate(p))
6158 continue;
6159
6160 assert(!p->copy_blocks_path);
6161
6162 (void) partition_hint(p, context->node, &hint);
6163
6164 log_info("Pre-populating %s filesystem of partition %s twice to calculate minimal partition size",
6165 p->format, strna(hint));
6166
6167 if (!vt) {
6168 r = var_tmp_dir(&vt);
6169 if (r < 0)
6170 return log_error_errno(r, "Could not determine temporary directory: %m");
6171 }
6172
6173 r = tempfn_random_child(vt, "repart", &temp);
6174 if (r < 0)
6175 return log_error_errno(r, "Failed to generate temporary file path: %m");
6176
6177 if (fstype_is_ro(p->format))
6178 fs_uuid = p->fs_uuid;
6179 else {
6180 fd = open(temp, O_CREAT|O_EXCL|O_CLOEXEC|O_RDWR|O_NOCTTY, 0600);
6181 if (fd < 0)
6182 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6183
6184 /* This may seem huge but it will be created sparse so it doesn't take up any space
6185 * on disk until written to. */
6186 if (ftruncate(fd, 1024ULL * 1024ULL * 1024ULL * 1024ULL) < 0)
6187 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m",
6188 FORMAT_BYTES(1024ULL * 1024ULL * 1024ULL * 1024ULL));
6189
6190 if (arg_offline <= 0) {
6191 r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d);
6192 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
6193 return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
6194 }
6195
6196 /* We're going to populate this filesystem twice so use a random UUID the first time
6197 * to avoid UUID conflicts. */
6198 r = sd_id128_randomize(&fs_uuid);
6199 if (r < 0)
6200 return r;
6201 }
6202
6203 if (!d || fstype_is_ro(p->format)) {
6204 if (!mkfs_supports_root_option(p->format))
6205 return log_error_errno(SYNTHETIC_ERRNO(ENODEV),
6206 "Loop device access is required to populate %s filesystems",
6207 p->format);
6208
6209 r = partition_populate_directory(context, p, &root);
6210 if (r < 0)
6211 return r;
6212 }
6213
6214 r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options);
6215 if (r < 0)
6216 return log_error_errno(r,
6217 "Failed to determine mkfs command line options for '%s': %m",
6218 p->format);
6219
6220 r = make_filesystem(d ? d->node : temp,
6221 p->format,
6222 strempty(p->new_label),
6223 root,
6224 fs_uuid,
6225 arg_discard, /* quiet = */ false,
6226 context->fs_sector_size,
6227 extra_mkfs_options);
6228 if (r < 0)
6229 return r;
6230
6231 /* Read-only filesystems are minimal from the first try because they create and size the
6232 * loopback file for us. */
6233 if (fstype_is_ro(p->format)) {
6234 assert(fd < 0);
6235
6236 fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
6237 if (fd < 0)
6238 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6239
6240 if (fstat(fd, &st) < 0)
6241 return log_error_errno(errno, "Failed to stat temporary file: %m");
6242
6243 log_info("Minimal partition size of %s filesystem of partition %s is %s",
6244 p->format, strna(hint), FORMAT_BYTES(st.st_size));
6245
6246 p->copy_blocks_path = TAKE_PTR(temp);
6247 p->copy_blocks_path_is_our_file = true;
6248 p->copy_blocks_fd = TAKE_FD(fd);
6249 p->copy_blocks_size = st.st_size;
6250 continue;
6251 }
6252
6253 if (!root) {
6254 assert(d);
6255
6256 r = partition_populate_filesystem(context, p, d->node);
6257 if (r < 0)
6258 return r;
6259 }
6260
6261 /* Other filesystems need to be provided with a pre-sized loopback file and will adapt to
6262 * fully occupy it. Because we gave the filesystem a 1T sparse file, we need to shrink the
6263 * filesystem down to a reasonable size again to fit it in the disk image. While there are
6264 * some filesystems that support shrinking, it doesn't always work properly (e.g. shrinking
6265 * btrfs gives us a 2.0G filesystem regardless of what we put in it). Instead, let's populate
6266 * the filesystem again, but this time, instead of providing the filesystem with a 1T sparse
6267 * loopback file, let's size the loopback file based on the actual data used by the
6268 * filesystem in the sparse file after the first attempt. This should be a good guess of the
6269 * minimal amount of space needed in the filesystem to fit all the required data.
6270 */
6271 r = fd_apparent_size(fd, &fsz);
6272 if (r < 0)
6273 return r;
6274
6275 /* Massage the size a bit because just going by actual data used in the sparse file isn't
6276 * fool-proof. */
6277 uint64_t heuristic = streq(p->format, "xfs") ? fsz : fsz / 2;
6278 fsz = round_up_size(fsz + heuristic, context->grain_size);
6279 if (minimal_size_by_fs_name(p->format) != UINT64_MAX)
6280 fsz = MAX(minimal_size_by_fs_name(p->format), fsz);
6281
6282 log_info("Minimal partition size of %s filesystem of partition %s is %s",
6283 p->format, strna(hint), FORMAT_BYTES(fsz));
6284
6285 d = loop_device_unref(d);
6286
6287 /* Erase the previous filesystem first. */
6288 if (ftruncate(fd, 0) < 0)
6289 return log_error_errno(errno, "Failed to erase temporary file: %m");
6290
6291 if (ftruncate(fd, fsz) < 0)
6292 return log_error_errno(errno, "Failed to truncate temporary file to %s: %m", FORMAT_BYTES(fsz));
6293
6294 if (arg_offline <= 0) {
6295 r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d);
6296 if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes)))
6297 return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
6298 }
6299
6300 r = make_filesystem(d ? d->node : temp,
6301 p->format,
6302 strempty(p->new_label),
6303 root,
6304 p->fs_uuid,
6305 arg_discard,
6306 /* quiet = */ false,
6307 context->fs_sector_size,
6308 extra_mkfs_options);
6309 if (r < 0)
6310 return r;
6311
6312 if (!root) {
6313 assert(d);
6314
6315 r = partition_populate_filesystem(context, p, d->node);
6316 if (r < 0)
6317 return r;
6318 }
6319
6320 if (fstat(fd, &st) < 0)
6321 return log_error_errno(errno, "Failed to stat temporary file: %m");
6322
6323 p->copy_blocks_path = TAKE_PTR(temp);
6324 p->copy_blocks_path_is_our_file = true;
6325 p->copy_blocks_fd = TAKE_FD(fd);
6326 p->copy_blocks_size = st.st_size;
6327 }
6328
6329 /* Now that we've done the data partitions, do the verity hash partitions. We do these in a separate
6330 * step because they might depend on data generated in the previous step. */
6331
6332 LIST_FOREACH(partitions, p, context->partitions) {
6333 _cleanup_(unlink_and_freep) char *temp = NULL;
6334 _cleanup_free_ char *hint = NULL;
6335 _cleanup_close_ int fd = -EBADF;
6336 struct stat st;
6337 Partition *dp;
6338
6339 if (p->dropped)
6340 continue;
6341
6342 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
6343 continue;
6344
6345 if (p->minimize == MINIMIZE_OFF)
6346 continue;
6347
6348 if (p->verity != VERITY_HASH)
6349 continue;
6350
6351 assert_se(dp = p->siblings[VERITY_DATA]);
6352 assert(!dp->dropped);
6353 assert(dp->copy_blocks_path);
6354
6355 (void) partition_hint(p, context->node, &hint);
6356
6357 log_info("Pre-populating verity hash data of partition %s to calculate minimal partition size",
6358 strna(hint));
6359
6360 if (!vt) {
6361 r = var_tmp_dir(&vt);
6362 if (r < 0)
6363 return log_error_errno(r, "Could not determine temporary directory: %m");
6364 }
6365
6366 r = tempfn_random_child(vt, "repart", &temp);
6367 if (r < 0)
6368 return log_error_errno(r, "Failed to generate temporary file path: %m");
6369
6370 r = touch(temp);
6371 if (r < 0)
6372 return log_error_errno(r, "Failed to create temporary file: %m");
6373
6374 r = partition_format_verity_hash(context, p, temp, dp->copy_blocks_path);
6375 if (r < 0)
6376 return r;
6377
6378 fd = open(temp, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
6379 if (fd < 0)
6380 return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
6381
6382 if (fstat(fd, &st) < 0)
6383 return log_error_errno(errno, "Failed to stat temporary file: %m");
6384
6385 log_info("Minimal partition size of verity hash partition %s is %s",
6386 strna(hint), FORMAT_BYTES(st.st_size));
6387
6388 p->copy_blocks_path = TAKE_PTR(temp);
6389 p->copy_blocks_path_is_our_file = true;
6390 p->copy_blocks_fd = TAKE_FD(fd);
6391 p->copy_blocks_size = st.st_size;
6392 }
6393
6394 return 0;
6395 }
6396
6397 static int parse_partition_types(const char *p, GptPartitionType **partitions, size_t *n_partitions) {
6398 int r;
6399
6400 assert(partitions);
6401 assert(n_partitions);
6402
6403 for (;;) {
6404 _cleanup_free_ char *name = NULL;
6405 GptPartitionType type;
6406
6407 r = extract_first_word(&p, &name, ",", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
6408 if (r == 0)
6409 break;
6410 if (r < 0)
6411 return log_error_errno(r, "Failed to extract partition type identifier or GUID: %s", p);
6412
6413 r = gpt_partition_type_from_string(name, &type);
6414 if (r < 0)
6415 return log_error_errno(r, "'%s' is not a valid partition type identifier or GUID", name);
6416
6417 if (!GREEDY_REALLOC(*partitions, *n_partitions + 1))
6418 return log_oom();
6419
6420 (*partitions)[(*n_partitions)++] = type;
6421 }
6422
6423 return 0;
6424 }
6425
6426 static int help(void) {
6427 _cleanup_free_ char *link = NULL;
6428 int r;
6429
6430 r = terminal_urlify_man("systemd-repart", "8", &link);
6431 if (r < 0)
6432 return log_oom();
6433
6434 printf("%s [OPTIONS...] [DEVICE]\n"
6435 "\n%sGrow and add partitions to partition table.%s\n\n"
6436 " -h --help Show this help\n"
6437 " --version Show package version\n"
6438 " --no-pager Do not pipe output into a pager\n"
6439 " --no-legend Do not show the headers and footers\n"
6440 " --dry-run=BOOL Whether to run dry-run operation\n"
6441 " --empty=MODE One of refuse, allow, require, force, create; controls\n"
6442 " how to handle empty disks lacking partition tables\n"
6443 " --discard=BOOL Whether to discard backing blocks for new partitions\n"
6444 " --pretty=BOOL Whether to show pretty summary before doing changes\n"
6445 " --factory-reset=BOOL Whether to remove data partitions before recreating\n"
6446 " them\n"
6447 " --can-factory-reset Test whether factory reset is defined\n"
6448 " --root=PATH Operate relative to root path\n"
6449 " --image=PATH Operate relative to image file\n"
6450 " --image-policy=POLICY\n"
6451 " Specify disk image dissection policy\n"
6452 " --definitions=DIR Find partition definitions in specified directory\n"
6453 " --key-file=PATH Key to use when encrypting partitions\n"
6454 " --private-key=PATH Private key to use when generating verity roothash\n"
6455 " signatures\n"
6456 " --certificate=PATH PEM certificate to use when generating verity\n"
6457 " roothash signatures\n"
6458 " --tpm2-device=PATH Path to TPM2 device node to use\n"
6459 " --tpm2-device-key=PATH\n"
6460 " Enroll a TPM2 device using its public key\n"
6461 " --tpm2-seal-key-handle=HANDLE\n"
6462 " Specify handle of key to use for sealing\n"
6463 " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
6464 " TPM2 PCR indexes to use for TPM2 enrollment\n"
6465 " --tpm2-public-key=PATH\n"
6466 " Enroll signed TPM2 PCR policy against PEM public key\n"
6467 " --tpm2-public-key-pcrs=PCR1+PCR2+PCR3+…\n"
6468 " Enroll signed TPM2 PCR policy for specified TPM2 PCRs\n"
6469 " --tpm2-pcrlock=PATH\n"
6470 " Specify pcrlock policy to lock against\n"
6471 " --seed=UUID 128-bit seed UUID to derive all UUIDs from\n"
6472 " --size=BYTES Grow loopback file to specified size\n"
6473 " --json=pretty|short|off\n"
6474 " Generate JSON output\n"
6475 " --split=BOOL Whether to generate split artifacts\n"
6476 " --include-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6477 " Ignore partitions not of the specified types\n"
6478 " --exclude-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6479 " Ignore partitions of the specified types\n"
6480 " --defer-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
6481 " Take partitions of the specified types into account\n"
6482 " but don't populate them yet\n"
6483 " --sector-size=SIZE Set the logical sector size for the image\n"
6484 " --architecture=ARCH Set the generic architecture for the image\n"
6485 " --offline=BOOL Whether to build the image offline\n"
6486 " -s --copy-source=PATH Specify the primary source tree to copy files from\n"
6487 " --copy-from=IMAGE Copy partitions from the given image(s)\n"
6488 " -S --make-ddi=sysext Make a system extension DDI\n"
6489 " -C --make-ddi=confext Make a configuration extension DDI\n"
6490 " -P --make-ddi=portable Make a portable service DDI\n"
6491 "\nSee the %s for details.\n",
6492 program_invocation_short_name,
6493 ansi_highlight(),
6494 ansi_normal(),
6495 link);
6496
6497 return 0;
6498 }
6499
6500 static int parse_argv(int argc, char *argv[]) {
6501
6502 enum {
6503 ARG_VERSION = 0x100,
6504 ARG_NO_PAGER,
6505 ARG_NO_LEGEND,
6506 ARG_DRY_RUN,
6507 ARG_EMPTY,
6508 ARG_DISCARD,
6509 ARG_FACTORY_RESET,
6510 ARG_CAN_FACTORY_RESET,
6511 ARG_ROOT,
6512 ARG_IMAGE,
6513 ARG_IMAGE_POLICY,
6514 ARG_SEED,
6515 ARG_PRETTY,
6516 ARG_DEFINITIONS,
6517 ARG_SIZE,
6518 ARG_JSON,
6519 ARG_KEY_FILE,
6520 ARG_PRIVATE_KEY,
6521 ARG_CERTIFICATE,
6522 ARG_TPM2_DEVICE,
6523 ARG_TPM2_DEVICE_KEY,
6524 ARG_TPM2_SEAL_KEY_HANDLE,
6525 ARG_TPM2_PCRS,
6526 ARG_TPM2_PUBLIC_KEY,
6527 ARG_TPM2_PUBLIC_KEY_PCRS,
6528 ARG_TPM2_PCRLOCK,
6529 ARG_SPLIT,
6530 ARG_INCLUDE_PARTITIONS,
6531 ARG_EXCLUDE_PARTITIONS,
6532 ARG_DEFER_PARTITIONS,
6533 ARG_SECTOR_SIZE,
6534 ARG_SKIP_PARTITIONS,
6535 ARG_ARCHITECTURE,
6536 ARG_OFFLINE,
6537 ARG_COPY_FROM,
6538 ARG_MAKE_DDI,
6539 };
6540
6541 static const struct option options[] = {
6542 { "help", no_argument, NULL, 'h' },
6543 { "version", no_argument, NULL, ARG_VERSION },
6544 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6545 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6546 { "dry-run", required_argument, NULL, ARG_DRY_RUN },
6547 { "empty", required_argument, NULL, ARG_EMPTY },
6548 { "discard", required_argument, NULL, ARG_DISCARD },
6549 { "factory-reset", required_argument, NULL, ARG_FACTORY_RESET },
6550 { "can-factory-reset", no_argument, NULL, ARG_CAN_FACTORY_RESET },
6551 { "root", required_argument, NULL, ARG_ROOT },
6552 { "image", required_argument, NULL, ARG_IMAGE },
6553 { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
6554 { "seed", required_argument, NULL, ARG_SEED },
6555 { "pretty", required_argument, NULL, ARG_PRETTY },
6556 { "definitions", required_argument, NULL, ARG_DEFINITIONS },
6557 { "size", required_argument, NULL, ARG_SIZE },
6558 { "json", required_argument, NULL, ARG_JSON },
6559 { "key-file", required_argument, NULL, ARG_KEY_FILE },
6560 { "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
6561 { "certificate", required_argument, NULL, ARG_CERTIFICATE },
6562 { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
6563 { "tpm2-device-key", required_argument, NULL, ARG_TPM2_DEVICE_KEY },
6564 { "tpm2-seal-key-handle", required_argument, NULL, ARG_TPM2_SEAL_KEY_HANDLE },
6565 { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
6566 { "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
6567 { "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
6568 { "tpm2-pcrlock", required_argument, NULL, ARG_TPM2_PCRLOCK },
6569 { "split", required_argument, NULL, ARG_SPLIT },
6570 { "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS },
6571 { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS },
6572 { "defer-partitions", required_argument, NULL, ARG_DEFER_PARTITIONS },
6573 { "sector-size", required_argument, NULL, ARG_SECTOR_SIZE },
6574 { "architecture", required_argument, NULL, ARG_ARCHITECTURE },
6575 { "offline", required_argument, NULL, ARG_OFFLINE },
6576 { "copy-from", required_argument, NULL, ARG_COPY_FROM },
6577 { "copy-source", required_argument, NULL, 's' },
6578 { "make-ddi", required_argument, NULL, ARG_MAKE_DDI },
6579 {}
6580 };
6581
6582 bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true, auto_pcrlock = true;
6583 int c, r;
6584
6585 assert(argc >= 0);
6586 assert(argv);
6587
6588 while ((c = getopt_long(argc, argv, "hs:SCP", options, NULL)) >= 0)
6589
6590 switch (c) {
6591
6592 case 'h':
6593 return help();
6594
6595 case ARG_VERSION:
6596 return version();
6597
6598 case ARG_NO_PAGER:
6599 arg_pager_flags |= PAGER_DISABLE;
6600 break;
6601
6602 case ARG_NO_LEGEND:
6603 arg_legend = false;
6604 break;
6605
6606 case ARG_DRY_RUN:
6607 r = parse_boolean_argument("--dry-run=", optarg, &arg_dry_run);
6608 if (r < 0)
6609 return r;
6610 break;
6611
6612 case ARG_EMPTY:
6613 if (isempty(optarg)) {
6614 arg_empty = EMPTY_UNSET;
6615 break;
6616 }
6617
6618 arg_empty = empty_mode_from_string(optarg);
6619 if (arg_empty < 0)
6620 return log_error_errno(arg_empty, "Failed to parse --empty= parameter: %s", optarg);
6621
6622 break;
6623
6624 case ARG_DISCARD:
6625 r = parse_boolean_argument("--discard=", optarg, &arg_discard);
6626 if (r < 0)
6627 return r;
6628 break;
6629
6630 case ARG_FACTORY_RESET:
6631 r = parse_boolean_argument("--factory-reset=", optarg, NULL);
6632 if (r < 0)
6633 return r;
6634 arg_factory_reset = r;
6635 break;
6636
6637 case ARG_CAN_FACTORY_RESET:
6638 arg_can_factory_reset = true;
6639 break;
6640
6641 case ARG_ROOT:
6642 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
6643 if (r < 0)
6644 return r;
6645 break;
6646
6647 case ARG_IMAGE:
6648 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
6649 if (r < 0)
6650 return r;
6651 break;
6652
6653 case ARG_IMAGE_POLICY:
6654 r = parse_image_policy_argument(optarg, &arg_image_policy);
6655 if (r < 0)
6656 return r;
6657 break;
6658
6659 case ARG_SEED:
6660 if (isempty(optarg)) {
6661 arg_seed = SD_ID128_NULL;
6662 arg_randomize = false;
6663 } else if (streq(optarg, "random"))
6664 arg_randomize = true;
6665 else {
6666 r = sd_id128_from_string(optarg, &arg_seed);
6667 if (r < 0)
6668 return log_error_errno(r, "Failed to parse seed: %s", optarg);
6669
6670 arg_randomize = false;
6671 }
6672
6673 break;
6674
6675 case ARG_PRETTY:
6676 r = parse_boolean_argument("--pretty=", optarg, NULL);
6677 if (r < 0)
6678 return r;
6679 arg_pretty = r;
6680 break;
6681
6682 case ARG_DEFINITIONS: {
6683 _cleanup_free_ char *path = NULL;
6684 r = parse_path_argument(optarg, false, &path);
6685 if (r < 0)
6686 return r;
6687 if (strv_consume(&arg_definitions, TAKE_PTR(path)) < 0)
6688 return log_oom();
6689 break;
6690 }
6691
6692 case ARG_SIZE: {
6693 uint64_t parsed, rounded;
6694
6695 if (streq(optarg, "auto")) {
6696 arg_size = UINT64_MAX;
6697 arg_size_auto = true;
6698 break;
6699 }
6700
6701 r = parse_size(optarg, 1024, &parsed);
6702 if (r < 0)
6703 return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg);
6704
6705 rounded = round_up_size(parsed, 4096);
6706 if (rounded == 0)
6707 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too small, refusing.");
6708 if (rounded == UINT64_MAX)
6709 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too large, refusing.");
6710
6711 if (rounded != parsed)
6712 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64 " %s %" PRIu64 ")",
6713 parsed, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), rounded);
6714
6715 arg_size = rounded;
6716 arg_size_auto = false;
6717 break;
6718 }
6719
6720 case ARG_JSON:
6721 r = parse_json_argument(optarg, &arg_json_format_flags);
6722 if (r <= 0)
6723 return r;
6724
6725 break;
6726
6727 case ARG_KEY_FILE: {
6728 _cleanup_(erase_and_freep) char *k = NULL;
6729 size_t n = 0;
6730
6731 r = read_full_file_full(
6732 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6733 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
6734 NULL,
6735 &k, &n);
6736 if (r < 0)
6737 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
6738
6739 erase_and_free(arg_key);
6740 arg_key = TAKE_PTR(k);
6741 arg_key_size = n;
6742 break;
6743 }
6744
6745 case ARG_PRIVATE_KEY: {
6746 _cleanup_(erase_and_freep) char *k = NULL;
6747 size_t n = 0;
6748
6749 r = read_full_file_full(
6750 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6751 READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
6752 NULL,
6753 &k, &n);
6754 if (r < 0)
6755 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
6756
6757 EVP_PKEY_free(arg_private_key);
6758 arg_private_key = NULL;
6759 r = parse_private_key(k, n, &arg_private_key);
6760 if (r < 0)
6761 return r;
6762 break;
6763 }
6764
6765 case ARG_CERTIFICATE: {
6766 _cleanup_free_ char *cert = NULL;
6767 size_t n = 0;
6768
6769 r = read_full_file_full(
6770 AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
6771 READ_FULL_FILE_CONNECT_SOCKET,
6772 NULL,
6773 &cert, &n);
6774 if (r < 0)
6775 return log_error_errno(r, "Failed to read certificate file '%s': %m", optarg);
6776
6777 X509_free(arg_certificate);
6778 arg_certificate = NULL;
6779 r = parse_x509_certificate(cert, n, &arg_certificate);
6780 if (r < 0)
6781 return r;
6782 break;
6783 }
6784
6785 case ARG_TPM2_DEVICE: {
6786 _cleanup_free_ char *device = NULL;
6787
6788 if (streq(optarg, "list"))
6789 return tpm2_list_devices();
6790
6791 if (!streq(optarg, "auto")) {
6792 device = strdup(optarg);
6793 if (!device)
6794 return log_oom();
6795 }
6796
6797 free(arg_tpm2_device);
6798 arg_tpm2_device = TAKE_PTR(device);
6799 break;
6800 }
6801
6802 case ARG_TPM2_DEVICE_KEY:
6803 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_device_key);
6804 if (r < 0)
6805 return r;
6806
6807 break;
6808
6809 case ARG_TPM2_SEAL_KEY_HANDLE:
6810 r = safe_atou32_full(optarg, 16, &arg_tpm2_seal_key_handle);
6811 if (r < 0)
6812 return log_error_errno(r, "Could not parse TPM2 seal key handle index '%s': %m", optarg);
6813
6814 break;
6815
6816 case ARG_TPM2_PCRS:
6817 auto_hash_pcr_values = false;
6818 r = tpm2_parse_pcr_argument_append(optarg, &arg_tpm2_hash_pcr_values, &arg_tpm2_n_hash_pcr_values);
6819 if (r < 0)
6820 return r;
6821
6822 break;
6823
6824 case ARG_TPM2_PUBLIC_KEY:
6825 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key);
6826 if (r < 0)
6827 return r;
6828
6829 break;
6830
6831 case ARG_TPM2_PUBLIC_KEY_PCRS:
6832 auto_public_key_pcr_mask = false;
6833 r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
6834 if (r < 0)
6835 return r;
6836
6837 break;
6838
6839 case ARG_TPM2_PCRLOCK:
6840 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_pcrlock);
6841 if (r < 0)
6842 return r;
6843
6844 auto_pcrlock = false;
6845 break;
6846
6847 case ARG_SPLIT:
6848 r = parse_boolean_argument("--split=", optarg, NULL);
6849 if (r < 0)
6850 return r;
6851
6852 arg_split = r;
6853 break;
6854
6855 case ARG_INCLUDE_PARTITIONS:
6856 if (arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE)
6857 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6858 "Combination of --include-partitions= and --exclude-partitions= is invalid.");
6859
6860 r = parse_partition_types(optarg, &arg_filter_partitions, &arg_n_filter_partitions);
6861 if (r < 0)
6862 return r;
6863
6864 arg_filter_partitions_type = FILTER_PARTITIONS_INCLUDE;
6865
6866 break;
6867
6868 case ARG_EXCLUDE_PARTITIONS:
6869 if (arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE)
6870 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6871 "Combination of --include-partitions= and --exclude-partitions= is invalid.");
6872
6873 r = parse_partition_types(optarg, &arg_filter_partitions, &arg_n_filter_partitions);
6874 if (r < 0)
6875 return r;
6876
6877 arg_filter_partitions_type = FILTER_PARTITIONS_EXCLUDE;
6878
6879 break;
6880
6881 case ARG_DEFER_PARTITIONS:
6882 r = parse_partition_types(optarg, &arg_defer_partitions, &arg_n_defer_partitions);
6883 if (r < 0)
6884 return r;
6885
6886 break;
6887
6888 case ARG_SECTOR_SIZE:
6889 r = parse_sector_size(optarg, &arg_sector_size);
6890 if (r < 0)
6891 return r;
6892
6893 break;
6894
6895 case ARG_ARCHITECTURE:
6896 r = architecture_from_string(optarg);
6897 if (r < 0)
6898 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid architecture '%s'", optarg);
6899
6900 arg_architecture = r;
6901 break;
6902
6903 case ARG_OFFLINE:
6904 if (streq(optarg, "auto"))
6905 arg_offline = -1;
6906 else {
6907 r = parse_boolean_argument("--offline=", optarg, NULL);
6908 if (r < 0)
6909 return r;
6910
6911 arg_offline = r;
6912 }
6913
6914 break;
6915
6916 case ARG_COPY_FROM: {
6917 _cleanup_free_ char *p = NULL;
6918
6919 r = parse_path_argument(optarg, /* suppress_root= */ false, &p);
6920 if (r < 0)
6921 return r;
6922
6923 if (strv_consume(&arg_copy_from, TAKE_PTR(p)) < 0)
6924 return log_oom();
6925
6926 break;
6927 }
6928
6929 case 's':
6930 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_copy_source);
6931 if (r < 0)
6932 return r;
6933 break;
6934
6935 case ARG_MAKE_DDI:
6936 if (!filename_is_valid(optarg))
6937 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid DDI type: %s", optarg);
6938
6939 r = free_and_strdup_warn(&arg_make_ddi, optarg);
6940 if (r < 0)
6941 return r;
6942 break;
6943
6944 case 'S':
6945 r = free_and_strdup_warn(&arg_make_ddi, "sysext");
6946 if (r < 0)
6947 return r;
6948 break;
6949
6950 case 'C':
6951 r = free_and_strdup_warn(&arg_make_ddi, "confext");
6952 if (r < 0)
6953 return r;
6954 break;
6955
6956 case 'P':
6957 r = free_and_strdup_warn(&arg_make_ddi, "portable");
6958 if (r < 0)
6959 return r;
6960 break;
6961
6962 case '?':
6963 return -EINVAL;
6964
6965 default:
6966 assert_not_reached();
6967 }
6968
6969 if (argc - optind > 1)
6970 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
6971 "Expected at most one argument, the path to the block device or image file.");
6972
6973 if (arg_make_ddi) {
6974 if (arg_definitions)
6975 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --definitions= is not supported.");
6976 if (!IN_SET(arg_empty, EMPTY_UNSET, EMPTY_CREATE))
6977 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --empty=%s is not supported.", empty_mode_to_string(arg_empty));
6978
6979 /* Imply automatic sizing in DDI mode */
6980 if (arg_size == UINT64_MAX)
6981 arg_size_auto = true;
6982
6983 if (!arg_copy_source)
6984 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --copy-source= specified, refusing.");
6985
6986 r = dir_is_empty(arg_copy_source, /* ignore_hidden_or_backup= */ false);
6987 if (r < 0)
6988 return log_error_errno(r, "Failed to determine if '%s' is empty: %m", arg_copy_source);
6989 if (r > 0)
6990 return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Source directory '%s' is empty, refusing to create empty image.", arg_copy_source);
6991
6992 if (sd_id128_is_null(arg_seed) && !arg_randomize) {
6993 /* We don't want that /etc/machine-id leaks into any image built this way, hence
6994 * let's randomize the seed if not specified explicitly */
6995 log_notice("No seed value specified, randomizing generated UUIDs, resulting image will not be reproducible.");
6996 arg_randomize = true;
6997 }
6998
6999 arg_empty = EMPTY_CREATE;
7000 }
7001
7002 if (arg_empty == EMPTY_UNSET) /* default to refuse mode, if not otherwise specified */
7003 arg_empty = EMPTY_REFUSE;
7004
7005 if (arg_factory_reset > 0 && IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE))
7006 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7007 "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
7008
7009 if (arg_can_factory_reset)
7010 arg_dry_run = true; /* When --can-factory-reset is specified we don't make changes, hence
7011 * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
7012 * open things strictly read-only. */
7013 else if (arg_empty == EMPTY_CREATE)
7014 arg_dry_run = false; /* Imply --dry-run=no if we create the loopback file anew. After all we
7015 * cannot really break anyone's partition tables that way. */
7016
7017 /* Disable pager once we are not just reviewing, but doing things. */
7018 if (!arg_dry_run)
7019 arg_pager_flags |= PAGER_DISABLE;
7020
7021 if (arg_empty == EMPTY_CREATE && arg_size == UINT64_MAX && !arg_size_auto)
7022 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7023 "If --empty=create is specified, --size= must be specified, too.");
7024
7025 if (arg_image && arg_root)
7026 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
7027 else if (!arg_image && !arg_root && in_initrd()) {
7028
7029 /* By default operate on /sysusr/ or /sysroot/ when invoked in the initrd. We prefer the
7030 * former, if it is mounted, so that we have deterministic behaviour on systems where /usr/
7031 * is vendor-supplied but the root fs formatted on first boot. */
7032 r = path_is_mount_point("/sysusr/usr", NULL, 0);
7033 if (r <= 0) {
7034 if (r < 0 && r != -ENOENT)
7035 log_debug_errno(r, "Unable to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
7036
7037 arg_root = strdup("/sysroot");
7038 } else
7039 arg_root = strdup("/sysusr");
7040 if (!arg_root)
7041 return log_oom();
7042 }
7043
7044 if (argc > optind) {
7045 arg_node = strdup(argv[optind]);
7046 if (!arg_node)
7047 return log_oom();
7048 }
7049
7050 if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node && !arg_image)
7051 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7052 "A path to a device node or image file must be specified when --make-ddi=, --empty=force, --empty=require or --empty=create are used.");
7053
7054 if (arg_split && !arg_node)
7055 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7056 "A path to an image file must be specified when --split is used.");
7057
7058 if (auto_pcrlock) {
7059 assert(!arg_tpm2_pcrlock);
7060
7061 r = tpm2_pcrlock_search_file(NULL, NULL, &arg_tpm2_pcrlock);
7062 if (r < 0) {
7063 if (r != -ENOENT)
7064 log_warning_errno(r, "Search for pcrlock.json failed, assuming it does not exist: %m");
7065 } else
7066 log_debug("Automatically using pcrlock policy '%s'.", arg_tpm2_pcrlock);
7067 }
7068
7069 if (auto_public_key_pcr_mask) {
7070 assert(arg_tpm2_public_key_pcr_mask == 0);
7071 arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
7072 }
7073
7074 if (auto_hash_pcr_values && !arg_tpm2_pcrlock) { /* Only lock to PCR 7 if no pcr policy is specified. */
7075 assert(arg_tpm2_n_hash_pcr_values == 0);
7076
7077 if (!GREEDY_REALLOC_APPEND(
7078 arg_tpm2_hash_pcr_values,
7079 arg_tpm2_n_hash_pcr_values,
7080 &TPM2_PCR_VALUE_MAKE(TPM2_PCR_INDEX_DEFAULT, /* hash= */ 0, /* value= */ {}),
7081 1))
7082 return log_oom();
7083 }
7084
7085 if (arg_pretty < 0 && isatty(STDOUT_FILENO))
7086 arg_pretty = true;
7087
7088 if (arg_architecture >= 0) {
7089 FOREACH_ARRAY(p, arg_filter_partitions, arg_n_filter_partitions)
7090 *p = gpt_partition_type_override_architecture(*p, arg_architecture);
7091
7092 FOREACH_ARRAY(p, arg_defer_partitions, arg_n_defer_partitions)
7093 *p = gpt_partition_type_override_architecture(*p, arg_architecture);
7094 }
7095
7096 return 1;
7097 }
7098
7099 static int parse_proc_cmdline_factory_reset(void) {
7100 bool b;
7101 int r;
7102
7103 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
7104 return 0;
7105
7106 if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
7107 return 0;
7108
7109 r = proc_cmdline_get_bool("systemd.factory_reset", /* flags = */ 0, &b);
7110 if (r < 0)
7111 return log_error_errno(r, "Failed to parse systemd.factory_reset kernel command line argument: %m");
7112 if (r > 0) {
7113 arg_factory_reset = b;
7114
7115 if (b)
7116 log_notice("Honouring factory reset requested via kernel command line.");
7117 }
7118
7119 return 0;
7120 }
7121
7122 static int parse_efi_variable_factory_reset(void) {
7123 _cleanup_free_ char *value = NULL;
7124 int r;
7125
7126 if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
7127 return 0;
7128
7129 if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
7130 return 0;
7131
7132 r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(FactoryReset), &value);
7133 if (r < 0) {
7134 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
7135 return 0;
7136 return log_error_errno(r, "Failed to read EFI variable FactoryReset: %m");
7137 }
7138
7139 r = parse_boolean(value);
7140 if (r < 0)
7141 return log_error_errno(r, "Failed to parse EFI variable FactoryReset: %m");
7142
7143 arg_factory_reset = r;
7144 if (r)
7145 log_notice("Factory reset requested via EFI variable FactoryReset.");
7146
7147 return 0;
7148 }
7149
7150 static int remove_efi_variable_factory_reset(void) {
7151 int r;
7152
7153 r = efi_set_variable(EFI_SYSTEMD_VARIABLE(FactoryReset), NULL, 0);
7154 if (r < 0) {
7155 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
7156 return 0;
7157 return log_error_errno(r, "Failed to remove EFI variable FactoryReset: %m");
7158 }
7159
7160 log_info("Successfully unset EFI variable FactoryReset.");
7161 return 0;
7162 }
7163
7164 static int acquire_root_devno(
7165 const char *p,
7166 const char *root,
7167 int mode,
7168 char **ret,
7169 int *ret_fd) {
7170
7171 _cleanup_free_ char *found_path = NULL, *node = NULL;
7172 dev_t devno, fd_devno = MODE_INVALID;
7173 _cleanup_close_ int fd = -EBADF;
7174 struct stat st;
7175 int r;
7176
7177 assert(p);
7178 assert(ret);
7179 assert(ret_fd);
7180
7181 fd = chase_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
7182 if (fd < 0)
7183 return fd;
7184
7185 if (fstat(fd, &st) < 0)
7186 return -errno;
7187
7188 if (S_ISREG(st.st_mode)) {
7189 *ret = TAKE_PTR(found_path);
7190 *ret_fd = TAKE_FD(fd);
7191 return 0;
7192 }
7193
7194 if (S_ISBLK(st.st_mode)) {
7195 /* Refuse referencing explicit block devices if a root dir is specified, after all we should
7196 * not be able to leave the image the root path constrains us to. */
7197 if (root)
7198 return -EPERM;
7199
7200 fd_devno = devno = st.st_rdev;
7201 } else if (S_ISDIR(st.st_mode)) {
7202
7203 devno = st.st_dev;
7204 if (major(devno) == 0) {
7205 r = btrfs_get_block_device_fd(fd, &devno);
7206 if (r == -ENOTTY) /* not btrfs */
7207 return -ENODEV;
7208 if (r < 0)
7209 return r;
7210 }
7211 } else
7212 return -ENOTBLK;
7213
7214 /* From dm-crypt to backing partition */
7215 r = block_get_originating(devno, &devno);
7216 if (r == -ENOENT)
7217 log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
7218 else if (r < 0)
7219 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
7220
7221 /* From partition to whole disk containing it */
7222 r = block_get_whole_disk(devno, &devno);
7223 if (r < 0)
7224 log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
7225
7226 r = devname_from_devnum(S_IFBLK, devno, &node);
7227 if (r < 0)
7228 return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
7229
7230 /* Only if we still look at the same block device we can reuse the fd. Otherwise return an
7231 * invalidated fd. */
7232 if (fd_devno != MODE_INVALID && fd_devno == devno) {
7233 /* Tell udev not to interfere while we are processing the device */
7234 if (flock(fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
7235 return log_error_errno(errno, "Failed to lock device '%s': %m", node);
7236
7237 *ret_fd = TAKE_FD(fd);
7238 } else
7239 *ret_fd = -EBADF;
7240
7241 *ret = TAKE_PTR(node);
7242 return 0;
7243 }
7244
7245 static int find_root(Context *context) {
7246 _cleanup_free_ char *device = NULL;
7247 int r;
7248
7249 assert(context);
7250
7251 if (arg_node) {
7252 if (arg_empty == EMPTY_CREATE) {
7253 _cleanup_close_ int fd = -EBADF;
7254 _cleanup_free_ char *s = NULL;
7255
7256 s = strdup(arg_node);
7257 if (!s)
7258 return log_oom();
7259
7260 fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
7261 if (fd < 0)
7262 return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
7263
7264 context->node = TAKE_PTR(s);
7265 context->node_is_our_file = true;
7266 context->backing_fd = TAKE_FD(fd);
7267 return 0;
7268 }
7269
7270 /* Note that we don't specify a root argument here: if the user explicitly configured a node
7271 * we'll take it relative to the host, not the image */
7272 r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
7273 if (r == -EUCLEAN)
7274 return btrfs_log_dev_root(LOG_ERR, r, arg_node);
7275 if (r < 0)
7276 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node);
7277
7278 return 0;
7279 }
7280
7281 assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
7282
7283 /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
7284 * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
7285 * here. */
7286 r = readlink_malloc("/run/systemd/volatile-root", &device);
7287 if (r == -ENOENT) { /* volatile-root not found */
7288 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
7289 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
7290 * (think: volatile setups) */
7291
7292 FOREACH_STRING(p, "/", "/usr") {
7293
7294 r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, &context->node,
7295 &context->backing_fd);
7296 if (r < 0) {
7297 if (r == -EUCLEAN)
7298 return btrfs_log_dev_root(LOG_ERR, r, p);
7299 if (r != -ENODEV)
7300 return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
7301 } else
7302 return 0;
7303 }
7304 } else if (r < 0)
7305 return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
7306 else {
7307 r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd);
7308 if (r == -EUCLEAN)
7309 return btrfs_log_dev_root(LOG_ERR, r, device);
7310 if (r < 0)
7311 return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", device);
7312
7313 return 0;
7314 }
7315
7316 return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
7317 }
7318
7319 static int resize_pt(int fd, uint64_t sector_size) {
7320 _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
7321 int r;
7322
7323 /* After resizing the backing file we need to resize the partition table itself too, so that it takes
7324 * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
7325 * immediately write it again, with no changes. */
7326
7327 r = fdisk_new_context_at(fd, /* path= */ NULL, /* read_only= */ false, sector_size, &c);
7328 if (r < 0)
7329 return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
7330
7331 r = fdisk_has_label(c);
7332 if (r < 0)
7333 return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd));
7334 if (r == 0) {
7335 log_debug("Not resizing partition table, as there currently is none.");
7336 return 0;
7337 }
7338
7339 r = fdisk_write_disklabel(c);
7340 if (r < 0)
7341 return log_error_errno(r, "Failed to write resized partition table: %m");
7342
7343 log_info("Resized partition table.");
7344 return 1;
7345 }
7346
7347 static int resize_backing_fd(
7348 const char *node, /* The primary way we access the disk image to operate on */
7349 int *fd, /* An O_RDONLY fd referring to that inode */
7350 const char *backing_file, /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
7351 LoopDevice *loop_device,
7352 uint64_t sector_size) {
7353
7354 _cleanup_close_ int writable_fd = -EBADF;
7355 uint64_t current_size;
7356 struct stat st;
7357 int r;
7358
7359 assert(node);
7360 assert(fd);
7361
7362 if (arg_size == UINT64_MAX) /* Nothing to do */
7363 return 0;
7364
7365 if (*fd < 0) {
7366 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
7367 * keep a reference to the file we can pass around. */
7368 *fd = open(node, O_RDONLY|O_CLOEXEC);
7369 if (*fd < 0)
7370 return log_error_errno(errno, "Failed to open '%s' in order to adjust size: %m", node);
7371 }
7372
7373 if (fstat(*fd, &st) < 0)
7374 return log_error_errno(errno, "Failed to stat '%s': %m", node);
7375
7376 if (S_ISBLK(st.st_mode)) {
7377 if (!backing_file)
7378 return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot resize block device '%s'.", node);
7379
7380 assert(loop_device);
7381
7382 r = blockdev_get_device_size(*fd, &current_size);
7383 if (r < 0)
7384 return log_error_errno(r, "Failed to determine size of block device %s: %m", node);
7385 } else {
7386 r = stat_verify_regular(&st);
7387 if (r < 0)
7388 return log_error_errno(r, "Specified path '%s' is not a regular file or loopback block device, cannot resize: %m", node);
7389
7390 assert(!backing_file);
7391 assert(!loop_device);
7392 current_size = st.st_size;
7393 }
7394
7395 if (current_size >= arg_size) {
7396 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)",
7397 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7398 return 0;
7399 }
7400
7401 if (S_ISBLK(st.st_mode)) {
7402 assert(backing_file);
7403
7404 /* This is a loopback device. We can't really grow those directly, but we can grow the
7405 * backing file, hence let's do that. */
7406
7407 writable_fd = open(backing_file, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
7408 if (writable_fd < 0)
7409 return log_error_errno(errno, "Failed to open backing file '%s': %m", backing_file);
7410
7411 if (fstat(writable_fd, &st) < 0)
7412 return log_error_errno(errno, "Failed to stat() backing file '%s': %m", backing_file);
7413
7414 r = stat_verify_regular(&st);
7415 if (r < 0)
7416 return log_error_errno(r, "Backing file '%s' of block device is not a regular file: %m", backing_file);
7417
7418 if ((uint64_t) st.st_size != current_size)
7419 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
7420 "Size of backing file '%s' of loopback block device '%s' don't match, refusing.",
7421 node, backing_file);
7422 } else {
7423 assert(S_ISREG(st.st_mode));
7424 assert(!backing_file);
7425
7426 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
7427 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
7428 * as fdisk can't accept it anyway. */
7429
7430 writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
7431 if (writable_fd < 0)
7432 return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
7433 }
7434
7435 if (!arg_discard) {
7436 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
7437 if (!ERRNO_IS_NOT_SUPPORTED(errno))
7438 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by allocation: %m",
7439 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7440
7441 /* Fallback to truncation, if fallocate() is not supported. */
7442 log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
7443 } else {
7444 if (current_size == 0) /* Likely regular file just created by us */
7445 log_info("Allocated %s for '%s'.", FORMAT_BYTES(arg_size), node);
7446 else
7447 log_info("File '%s' grown from %s to %s by allocation.",
7448 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7449
7450 goto done;
7451 }
7452 }
7453
7454 if (ftruncate(writable_fd, arg_size) < 0)
7455 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
7456 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7457
7458 if (current_size == 0) /* Likely regular file just created by us */
7459 log_info("Sized '%s' to %s.", node, FORMAT_BYTES(arg_size));
7460 else
7461 log_info("File '%s' grown from %s to %s by truncation.",
7462 node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
7463
7464 done:
7465 r = resize_pt(writable_fd, sector_size);
7466 if (r < 0)
7467 return r;
7468
7469 if (loop_device) {
7470 r = loop_device_refresh_size(loop_device, UINT64_MAX, arg_size);
7471 if (r < 0)
7472 return log_error_errno(r, "Failed to update loop device size: %m");
7473 }
7474
7475 return 1;
7476 }
7477
7478 static int determine_auto_size(Context *c) {
7479 uint64_t sum;
7480
7481 assert(c);
7482
7483 sum = round_up_size(GPT_METADATA_SIZE, 4096);
7484
7485 LIST_FOREACH(partitions, p, c->partitions) {
7486 uint64_t m;
7487
7488 if (p->dropped)
7489 continue;
7490
7491 m = partition_min_size_with_padding(c, p);
7492 if (m > UINT64_MAX - sum)
7493 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Image would grow too large, refusing.");
7494
7495 sum += m;
7496 }
7497
7498 if (c->total != UINT64_MAX)
7499 /* Image already allocated? Then show its size. */
7500 log_info("Automatically determined minimal disk image size as %s, current image size is %s.",
7501 FORMAT_BYTES(sum), FORMAT_BYTES(c->total));
7502 else
7503 /* If the image is being created right now, then it has no previous size, suppress any comment about it hence. */
7504 log_info("Automatically determined minimal disk image size as %s.",
7505 FORMAT_BYTES(sum));
7506
7507 arg_size = sum;
7508 return 0;
7509 }
7510
7511 static int run(int argc, char *argv[]) {
7512 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
7513 _cleanup_(umount_and_freep) char *mounted_dir = NULL;
7514 _cleanup_(context_freep) Context* context = NULL;
7515 bool node_is_our_loop = false;
7516 int r;
7517
7518 log_show_color(true);
7519 log_parse_environment();
7520 log_open();
7521
7522 r = parse_argv(argc, argv);
7523 if (r <= 0)
7524 return r;
7525
7526 r = parse_proc_cmdline_factory_reset();
7527 if (r < 0)
7528 return r;
7529
7530 r = parse_efi_variable_factory_reset();
7531 if (r < 0)
7532 return r;
7533
7534 #if HAVE_LIBCRYPTSETUP
7535 cryptsetup_enable_logging(NULL);
7536 #endif
7537
7538 if (arg_image) {
7539 assert(!arg_root);
7540
7541 /* Mount this strictly read-only: we shall modify the partition table, not the file
7542 * systems */
7543 r = mount_image_privately_interactively(
7544 arg_image,
7545 arg_image_policy,
7546 DISSECT_IMAGE_MOUNT_READ_ONLY |
7547 (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) */
7548 DISSECT_IMAGE_GPT_ONLY |
7549 DISSECT_IMAGE_RELAX_VAR_CHECK |
7550 DISSECT_IMAGE_USR_NO_ROOT |
7551 DISSECT_IMAGE_REQUIRE_ROOT,
7552 &mounted_dir,
7553 /* ret_dir_fd= */ NULL,
7554 &loop_device);
7555 if (r < 0)
7556 return r;
7557
7558 arg_root = strdup(mounted_dir);
7559 if (!arg_root)
7560 return log_oom();
7561
7562 if (!arg_node) {
7563 arg_node = strdup(loop_device->node);
7564 if (!arg_node)
7565 return log_oom();
7566
7567 /* Remember that the device we are about to manipulate is actually the one we
7568 * allocated here, and thus to increase its backing file we know what to do */
7569 node_is_our_loop = true;
7570 }
7571 }
7572
7573 if (!arg_copy_source && arg_root) {
7574 /* If no explicit copy source is specified, then use --root=/--image= */
7575 arg_copy_source = strdup(arg_root);
7576 if (!arg_copy_source)
7577 return log_oom();
7578 }
7579
7580 context = context_new(arg_seed);
7581 if (!context)
7582 return log_oom();
7583
7584 r = context_copy_from(context);
7585 if (r < 0)
7586 return r;
7587
7588 if (arg_make_ddi) {
7589 _cleanup_free_ char *d = NULL, *dp = NULL;
7590 assert(!arg_definitions);
7591
7592 d = strjoin(arg_make_ddi, ".repart.d/");
7593 if (!d)
7594 return log_oom();
7595
7596 r = search_and_access(d, F_OK, NULL, CONF_PATHS_USR_STRV("systemd/repart/definitions"), &dp);
7597 if (r < 0)
7598 return log_error_errno(r, "DDI type '%s' is not defined: %m", arg_make_ddi);
7599
7600 if (strv_consume(&arg_definitions, TAKE_PTR(dp)) < 0)
7601 return log_oom();
7602 } else
7603 strv_uniq(arg_definitions);
7604
7605 r = context_read_definitions(context);
7606 if (r < 0)
7607 return r;
7608
7609 r = find_root(context);
7610 if (r == -ENODEV)
7611 return 76; /* Special return value which means "Root block device not found, so not doing
7612 * anything". This isn't really an error when called at boot. */
7613 if (r < 0)
7614 return r;
7615
7616 if (arg_size != UINT64_MAX) {
7617 r = resize_backing_fd(
7618 context->node,
7619 &context->backing_fd,
7620 node_is_our_loop ? arg_image : NULL,
7621 node_is_our_loop ? loop_device : NULL,
7622 context->sector_size);
7623 if (r < 0)
7624 return r;
7625 }
7626
7627 r = context_load_partition_table(context);
7628 if (r == -EHWPOISON)
7629 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
7630 * really an error when called at boot. */
7631 if (r < 0)
7632 return r;
7633 context->from_scratch = r > 0; /* Starting from scratch */
7634
7635 if (arg_can_factory_reset) {
7636 r = context_can_factory_reset(context);
7637 if (r < 0)
7638 return r;
7639 if (r == 0)
7640 return EXIT_FAILURE;
7641
7642 return 0;
7643 }
7644
7645 r = context_factory_reset(context);
7646 if (r < 0)
7647 return r;
7648 if (r > 0) {
7649 /* We actually did a factory reset! */
7650 r = remove_efi_variable_factory_reset();
7651 if (r < 0)
7652 return r;
7653
7654 /* Reload the reduced partition table */
7655 context_unload_partition_table(context);
7656 r = context_load_partition_table(context);
7657 if (r < 0)
7658 return r;
7659 }
7660
7661 r = context_read_seed(context, arg_root);
7662 if (r < 0)
7663 return r;
7664
7665 /* Make sure each partition has a unique UUID and unique label */
7666 r = context_acquire_partition_uuids_and_labels(context);
7667 if (r < 0)
7668 return r;
7669
7670 /* Open all files to copy blocks from now, since we want to take their size into consideration */
7671 r = context_open_copy_block_paths(
7672 context,
7673 loop_device ? loop_device->devno : /* if --image= is specified, only allow partitions on the loopback device */
7674 arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
7675 (dev_t) -1); /* if neither is specified, make no restrictions */
7676 if (r < 0)
7677 return r;
7678
7679 r = context_minimize(context);
7680 if (r < 0)
7681 return r;
7682
7683 if (arg_size_auto) {
7684 r = determine_auto_size(context);
7685 if (r < 0)
7686 return r;
7687
7688 /* Flush out everything again, and let's grow the file first, then start fresh */
7689 context_unload_partition_table(context);
7690
7691 assert(arg_size != UINT64_MAX);
7692 r = resize_backing_fd(
7693 context->node,
7694 &context->backing_fd,
7695 node_is_our_loop ? arg_image : NULL,
7696 node_is_our_loop ? loop_device : NULL,
7697 context->sector_size);
7698 if (r < 0)
7699 return r;
7700
7701 r = context_load_partition_table(context);
7702 if (r < 0)
7703 return r;
7704 }
7705
7706 /* First try to fit new partitions in, dropping by priority until it fits */
7707 for (;;) {
7708 uint64_t largest_free_area;
7709
7710 if (context_allocate_partitions(context, &largest_free_area))
7711 break; /* Success! */
7712
7713 if (!context_drop_or_foreignize_one_priority(context)) {
7714 r = log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
7715 "Can't fit requested partitions into available free space (%s), refusing.",
7716 FORMAT_BYTES(largest_free_area));
7717 determine_auto_size(context);
7718 return r;
7719 }
7720 }
7721
7722 /* Now assign free space according to the weight logic */
7723 r = context_grow_partitions(context);
7724 if (r < 0)
7725 return r;
7726
7727 /* Now calculate where each new partition gets placed */
7728 context_place_partitions(context);
7729
7730 (void) context_dump(context, /*late=*/ false);
7731
7732 r = context_write_partition_table(context);
7733 if (r < 0)
7734 return r;
7735
7736 r = context_split(context);
7737 if (r < 0)
7738 return r;
7739
7740 (void) context_dump(context, /*late=*/ true);
7741
7742 context->node = mfree(context->node);
7743
7744 LIST_FOREACH(partitions, p, context->partitions)
7745 p->split_path = mfree(p->split_path);
7746
7747 return 0;
7748 }
7749
7750 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);