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