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