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