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 "chase-symlinks.h"
23 #include "conf-files.h"
24 #include "conf-parser.h"
25 #include "cryptsetup-util.h"
26 #include "def.h"
27 #include "devnum-util.h"
28 #include "dirent-util.h"
29 #include "efivars.h"
30 #include "errno-util.h"
31 #include "fd-util.h"
32 #include "fdisk-util.h"
33 #include "fileio.h"
34 #include "format-table.h"
35 #include "format-util.h"
36 #include "fs-util.h"
37 #include "glyph-util.h"
38 #include "gpt.h"
39 #include "hexdecoct.h"
40 #include "hmac.h"
41 #include "id128-util.h"
42 #include "json.h"
43 #include "list.h"
44 #include "loop-util.h"
45 #include "main-func.h"
46 #include "mkdir.h"
47 #include "mkfs-util.h"
48 #include "mount-util.h"
49 #include "mountpoint-util.h"
50 #include "parse-argument.h"
51 #include "parse-helpers.h"
52 #include "pretty-print.h"
53 #include "proc-cmdline.h"
54 #include "process-util.h"
55 #include "random-util.h"
56 #include "resize-fs.h"
57 #include "sort-util.h"
58 #include "specifier.h"
59 #include "stdio-util.h"
60 #include "string-table.h"
61 #include "string-util.h"
62 #include "strv.h"
63 #include "sync-util.h"
64 #include "terminal-util.h"
65 #include "tpm2-util.h"
66 #include "user-util.h"
67 #include "utf8.h"
68 
69 /* If not configured otherwise use a minimal partition size of 10M */
70 #define DEFAULT_MIN_SIZE (10*1024*1024)
71 
72 /* Hard lower limit for new partition sizes */
73 #define HARD_MIN_SIZE 4096
74 
75 /* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */
76 #define GPT_METADATA_SIZE (1044*1024)
77 
78 /* LUKS2 takes off 16M of the partition size with its metadata by default */
79 #define LUKS2_METADATA_SIZE (16*1024*1024)
80 
81 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
82  * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
83  * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
84  * waste 3K per partition, which is probably fine. */
85 
86 static enum {
87         EMPTY_REFUSE,   /* refuse empty disks, never create a partition table */
88         EMPTY_ALLOW,    /* allow empty disks, create partition table if necessary */
89         EMPTY_REQUIRE,  /* require an empty disk, create a partition table */
90         EMPTY_FORCE,    /* make disk empty, erase everything, create a partition table always */
91         EMPTY_CREATE,   /* create disk as loopback file, create a partition table always */
92 } arg_empty = EMPTY_REFUSE;
93 
94 static bool arg_dry_run = true;
95 static const char *arg_node = NULL;
96 static char *arg_root = NULL;
97 static char *arg_image = NULL;
98 static char *arg_definitions = NULL;
99 static bool arg_discard = true;
100 static bool arg_can_factory_reset = false;
101 static int arg_factory_reset = -1;
102 static sd_id128_t arg_seed = SD_ID128_NULL;
103 static bool arg_randomize = false;
104 static int arg_pretty = -1;
105 static uint64_t arg_size = UINT64_MAX;
106 static bool arg_size_auto = false;
107 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
108 static PagerFlags arg_pager_flags = 0;
109 static bool arg_legend = true;
110 static void *arg_key = NULL;
111 static size_t arg_key_size = 0;
112 static char *arg_tpm2_device = NULL;
113 static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
114 
115 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
116 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
117 STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
118 STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
119 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
120 
121 typedef struct Partition Partition;
122 typedef struct FreeArea FreeArea;
123 typedef struct Context Context;
124 
125 typedef enum EncryptMode {
126         ENCRYPT_OFF,
127         ENCRYPT_KEY_FILE,
128         ENCRYPT_TPM2,
129         ENCRYPT_KEY_FILE_TPM2,
130         _ENCRYPT_MODE_MAX,
131         _ENCRYPT_MODE_INVALID = -EINVAL,
132 } EncryptMode;
133 
134 struct Partition {
135         char *definition_path;
136 
137         sd_id128_t type_uuid;
138         sd_id128_t current_uuid, new_uuid;
139         char *current_label, *new_label;
140 
141         bool dropped;
142         bool factory_reset;
143         int32_t priority;
144 
145         uint32_t weight, padding_weight;
146 
147         uint64_t current_size, new_size;
148         uint64_t size_min, size_max;
149 
150         uint64_t current_padding, new_padding;
151         uint64_t padding_min, padding_max;
152 
153         uint64_t partno;
154         uint64_t offset;
155 
156         struct fdisk_partition *current_partition;
157         struct fdisk_partition *new_partition;
158         FreeArea *padding_area;
159         FreeArea *allocated_to_area;
160 
161         char *copy_blocks_path;
162         bool copy_blocks_auto;
163         int copy_blocks_fd;
164         uint64_t copy_blocks_size;
165 
166         char *format;
167         char **copy_files;
168         char **make_directories;
169         EncryptMode encrypt;
170 
171         uint64_t gpt_flags;
172         int no_auto;
173         int read_only;
174         int growfs;
175 
176         LIST_FIELDS(Partition, partitions);
177 };
178 
179 #define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
180 #define PARTITION_EXISTS(p) (!!(p)->current_partition)
181 
182 struct FreeArea {
183         Partition *after;
184         uint64_t size;
185         uint64_t allocated;
186 };
187 
188 struct Context {
189         LIST_HEAD(Partition, partitions);
190         size_t n_partitions;
191 
192         FreeArea **free_areas;
193         size_t n_free_areas;
194 
195         uint64_t start, end, total;
196 
197         struct fdisk_context *fdisk_context;
198         uint64_t sector_size;
199         uint64_t grain_size;
200 
201         sd_id128_t seed;
202 };
203 
204 static const char *encrypt_mode_table[_ENCRYPT_MODE_MAX] = {
205         [ENCRYPT_OFF] = "off",
206         [ENCRYPT_KEY_FILE] = "key-file",
207         [ENCRYPT_TPM2] = "tpm2",
208         [ENCRYPT_KEY_FILE_TPM2] = "key-file+tpm2",
209 };
210 
211 #if HAVE_LIBCRYPTSETUP
212 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE);
213 #else
214 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE);
215 #endif
216 
217 
round_down_size(uint64_t v,uint64_t p)218 static uint64_t round_down_size(uint64_t v, uint64_t p) {
219         return (v / p) * p;
220 }
221 
round_up_size(uint64_t v,uint64_t p)222 static uint64_t round_up_size(uint64_t v, uint64_t p) {
223 
224         v = DIV_ROUND_UP(v, p);
225 
226         if (v > UINT64_MAX / p)
227                 return UINT64_MAX; /* overflow */
228 
229         return v * p;
230 }
231 
partition_new(void)232 static Partition *partition_new(void) {
233         Partition *p;
234 
235         p = new(Partition, 1);
236         if (!p)
237                 return NULL;
238 
239         *p = (Partition) {
240                 .weight = 1000,
241                 .padding_weight = 0,
242                 .current_size = UINT64_MAX,
243                 .new_size = UINT64_MAX,
244                 .size_min = UINT64_MAX,
245                 .size_max = UINT64_MAX,
246                 .current_padding = UINT64_MAX,
247                 .new_padding = UINT64_MAX,
248                 .padding_min = UINT64_MAX,
249                 .padding_max = UINT64_MAX,
250                 .partno = UINT64_MAX,
251                 .offset = UINT64_MAX,
252                 .copy_blocks_fd = -1,
253                 .copy_blocks_size = UINT64_MAX,
254                 .no_auto = -1,
255                 .read_only = -1,
256                 .growfs = -1,
257         };
258 
259         return p;
260 }
261 
partition_free(Partition * p)262 static Partition* partition_free(Partition *p) {
263         if (!p)
264                 return NULL;
265 
266         free(p->current_label);
267         free(p->new_label);
268         free(p->definition_path);
269 
270         if (p->current_partition)
271                 fdisk_unref_partition(p->current_partition);
272         if (p->new_partition)
273                 fdisk_unref_partition(p->new_partition);
274 
275         free(p->copy_blocks_path);
276         safe_close(p->copy_blocks_fd);
277 
278         free(p->format);
279         strv_free(p->copy_files);
280         strv_free(p->make_directories);
281 
282         return mfree(p);
283 }
284 
partition_unlink_and_free(Context * context,Partition * p)285 static Partition* partition_unlink_and_free(Context *context, Partition *p) {
286         if (!p)
287                 return NULL;
288 
289         LIST_REMOVE(partitions, context->partitions, p);
290 
291         assert(context->n_partitions > 0);
292         context->n_partitions--;
293 
294         return partition_free(p);
295 }
296 
297 DEFINE_TRIVIAL_CLEANUP_FUNC(Partition*, partition_free);
298 
context_new(sd_id128_t seed)299 static Context *context_new(sd_id128_t seed) {
300         Context *context;
301 
302         context = new(Context, 1);
303         if (!context)
304                 return NULL;
305 
306         *context = (Context) {
307                 .start = UINT64_MAX,
308                 .end = UINT64_MAX,
309                 .total = UINT64_MAX,
310                 .seed = seed,
311         };
312 
313         return context;
314 }
315 
context_free_free_areas(Context * context)316 static void context_free_free_areas(Context *context) {
317         assert(context);
318 
319         for (size_t i = 0; i < context->n_free_areas; i++)
320                 free(context->free_areas[i]);
321 
322         context->free_areas = mfree(context->free_areas);
323         context->n_free_areas = 0;
324 }
325 
context_free(Context * context)326 static Context *context_free(Context *context) {
327         if (!context)
328                 return NULL;
329 
330         while (context->partitions)
331                 partition_unlink_and_free(context, context->partitions);
332         assert(context->n_partitions == 0);
333 
334         context_free_free_areas(context);
335 
336         if (context->fdisk_context)
337                 fdisk_unref_context(context->fdisk_context);
338 
339         return mfree(context);
340 }
341 
342 DEFINE_TRIVIAL_CLEANUP_FUNC(Context*, context_free);
343 
context_add_free_area(Context * context,uint64_t size,Partition * after)344 static int context_add_free_area(
345                 Context *context,
346                 uint64_t size,
347                 Partition *after) {
348 
349         FreeArea *a;
350 
351         assert(context);
352         assert(!after || !after->padding_area);
353 
354         if (!GREEDY_REALLOC(context->free_areas, context->n_free_areas + 1))
355                 return -ENOMEM;
356 
357         a = new(FreeArea, 1);
358         if (!a)
359                 return -ENOMEM;
360 
361         *a = (FreeArea) {
362                 .size = size,
363                 .after = after,
364         };
365 
366         context->free_areas[context->n_free_areas++] = a;
367 
368         if (after)
369                 after->padding_area = a;
370 
371         return 0;
372 }
373 
context_drop_one_priority(Context * context)374 static bool context_drop_one_priority(Context *context) {
375         int32_t priority = 0;
376         bool exists = false;
377 
378         LIST_FOREACH(partitions, p, context->partitions) {
379                 if (p->dropped)
380                         continue;
381                 if (p->priority < priority)
382                         continue;
383                 if (p->priority == priority) {
384                         exists = exists || PARTITION_EXISTS(p);
385                         continue;
386                 }
387 
388                 priority = p->priority;
389                 exists = PARTITION_EXISTS(p);
390         }
391 
392         /* Refuse to drop partitions with 0 or negative priorities or partitions of priorities that have at
393          * least one existing priority */
394         if (priority <= 0 || exists)
395                 return false;
396 
397         LIST_FOREACH(partitions, p, context->partitions) {
398                 if (p->priority < priority)
399                         continue;
400 
401                 if (p->dropped)
402                         continue;
403 
404                 p->dropped = true;
405                 log_info("Can't fit partition %s of priority %" PRIi32 ", dropping.", p->definition_path, p->priority);
406         }
407 
408         return true;
409 }
410 
partition_min_size(Context * context,const Partition * p)411 static uint64_t partition_min_size(Context *context, const Partition *p) {
412         uint64_t sz;
413 
414         assert(context);
415         assert(p);
416 
417         /* Calculate the disk space we really need at minimum for this partition. If the partition already
418          * exists the current size is what we really need. If it doesn't exist yet refuse to allocate less
419          * than 4K.
420          *
421          * DEFAULT_MIN_SIZE is the default SizeMin= we configure if nothing else is specified. */
422 
423         if (PARTITION_IS_FOREIGN(p)) {
424                 /* Don't allow changing size of partitions not managed by us */
425                 assert(p->current_size != UINT64_MAX);
426                 return p->current_size;
427         }
428 
429         sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE;
430 
431         if (!PARTITION_EXISTS(p)) {
432                 uint64_t d = 0;
433 
434                 if (p->encrypt != ENCRYPT_OFF)
435                         d += round_up_size(LUKS2_METADATA_SIZE, context->grain_size);
436 
437                 if (p->copy_blocks_size != UINT64_MAX)
438                         d += round_up_size(p->copy_blocks_size, context->grain_size);
439                 else if (p->format || p->encrypt != ENCRYPT_OFF) {
440                         uint64_t f;
441 
442                         /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */
443                         f = p->format ? round_up_size(minimal_size_by_fs_name(p->format), context->grain_size) : UINT64_MAX;
444                         d += f == UINT64_MAX ? context->grain_size : f;
445                 }
446 
447                 if (d > sz)
448                         sz = d;
449         }
450 
451         return MAX(round_up_size(p->size_min != UINT64_MAX ? p->size_min : DEFAULT_MIN_SIZE, context->grain_size), sz);
452 }
453 
partition_max_size(const Context * context,const Partition * p)454 static uint64_t partition_max_size(const Context *context, const Partition *p) {
455         uint64_t sm;
456 
457         /* Calculate how large the partition may become at max. This is generally the configured maximum
458          * size, except when it already exists and is larger than that. In that case it's the existing size,
459          * since we never want to shrink partitions. */
460 
461         assert(context);
462         assert(p);
463 
464         if (PARTITION_IS_FOREIGN(p)) {
465                 /* Don't allow changing size of partitions not managed by us */
466                 assert(p->current_size != UINT64_MAX);
467                 return p->current_size;
468         }
469 
470         sm = round_down_size(p->size_max, context->grain_size);
471 
472         if (p->current_size != UINT64_MAX)
473                 return MAX(p->current_size, sm);
474 
475         return sm;
476 }
477 
partition_min_size_with_padding(Context * context,const Partition * p)478 static uint64_t partition_min_size_with_padding(Context *context, const Partition *p) {
479         uint64_t sz;
480 
481         /* Calculate the disk space we need for this partition plus any free space coming after it. This
482          * takes user configured padding into account as well as any additional whitespace needed to align
483          * the next partition to 4K again. */
484 
485         assert(context);
486         assert(p);
487 
488         sz = partition_min_size(context, p);
489 
490         if (p->padding_min != UINT64_MAX)
491                 sz += p->padding_min;
492 
493         if (PARTITION_EXISTS(p)) {
494                 /* If the partition wasn't aligned, add extra space so that any we might add will be aligned */
495                 assert(p->offset != UINT64_MAX);
496                 return round_up_size(p->offset + sz, context->grain_size) - p->offset;
497         }
498 
499         /* If this is a new partition we'll place it aligned, hence we just need to round up the required size here */
500         return round_up_size(sz, context->grain_size);
501 }
502 
free_area_available(const FreeArea * a)503 static uint64_t free_area_available(const FreeArea *a) {
504         assert(a);
505 
506         /* Determines how much of this free area is not allocated yet */
507 
508         assert(a->size >= a->allocated);
509         return a->size - a->allocated;
510 }
511 
free_area_available_for_new_partitions(Context * context,const FreeArea * a)512 static uint64_t free_area_available_for_new_partitions(Context *context, const FreeArea *a) {
513         uint64_t avail;
514 
515         assert(context);
516         assert(a);
517 
518         /* Similar to free_area_available(), but takes into account that the required size and padding of the
519          * preceding partition is honoured. */
520 
521         avail = free_area_available(a);
522         if (a->after) {
523                 uint64_t need, space_end, new_end;
524 
525                 need = partition_min_size_with_padding(context, a->after);
526 
527                 assert(a->after->offset != UINT64_MAX);
528                 assert(a->after->current_size != UINT64_MAX);
529 
530                 /* Calculate where the free area ends, based on the offset of the partition preceding it */
531                 space_end = round_up_size(a->after->offset + a->after->current_size, context->grain_size) + avail;
532 
533                 /* Calculate where the partition would end when we give it as much as it needs */
534                 new_end = round_up_size(a->after->offset + need, context->grain_size);
535 
536                 /* Calculate saturated difference of the two: that's how much we have free for other partitions */
537                 return LESS_BY(space_end, new_end);
538         }
539 
540         return avail;
541 }
542 
free_area_compare(FreeArea * const * a,FreeArea * const * b,Context * context)543 static int free_area_compare(FreeArea *const *a, FreeArea *const*b, Context *context) {
544         assert(context);
545 
546         return CMP(free_area_available_for_new_partitions(context, *a),
547                    free_area_available_for_new_partitions(context, *b));
548 }
549 
charge_size(Context * context,uint64_t total,uint64_t amount)550 static uint64_t charge_size(Context *context, uint64_t total, uint64_t amount) {
551         assert(context);
552         /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */
553         assert(amount <= total);
554         return LESS_BY(total, round_up_size(amount, context->grain_size));
555 }
556 
charge_weight(uint64_t total,uint64_t amount)557 static uint64_t charge_weight(uint64_t total, uint64_t amount) {
558         assert(amount <= total);
559         return total - amount;
560 }
561 
context_allocate_partitions(Context * context,uint64_t * ret_largest_free_area)562 static bool context_allocate_partitions(Context *context, uint64_t *ret_largest_free_area) {
563         assert(context);
564 
565         /* Sort free areas by size, putting smallest first */
566         typesafe_qsort_r(context->free_areas, context->n_free_areas, free_area_compare, context);
567 
568         /* In any case return size of the largest free area (i.e. not the size of all free areas
569          * combined!) */
570         if (ret_largest_free_area)
571                 *ret_largest_free_area =
572                         context->n_free_areas == 0 ? 0 :
573                         free_area_available_for_new_partitions(context, context->free_areas[context->n_free_areas-1]);
574 
575         /* A simple first-fit algorithm. We return true if we can fit the partitions in, otherwise false. */
576         LIST_FOREACH(partitions, p, context->partitions) {
577                 bool fits = false;
578                 uint64_t required;
579                 FreeArea *a = NULL;
580 
581                 /* Skip partitions we already dropped or that already exist */
582                 if (p->dropped || PARTITION_EXISTS(p))
583                         continue;
584 
585                 /* How much do we need to fit? */
586                 required = partition_min_size_with_padding(context, p);
587                 assert(required % context->grain_size == 0);
588 
589                 for (size_t i = 0; i < context->n_free_areas; i++) {
590                         a = context->free_areas[i];
591 
592                         if (free_area_available_for_new_partitions(context, a) >= required) {
593                                 fits = true;
594                                 break;
595                         }
596                 }
597 
598                 if (!fits)
599                         return false; /* �� Oh no! We can't fit this partition into any free area! */
600 
601                 /* Assign the partition to this free area */
602                 p->allocated_to_area = a;
603 
604                 /* Budget the minimal partition size */
605                 a->allocated += required;
606         }
607 
608         return true;
609 }
610 
context_sum_weights(Context * context,FreeArea * a,uint64_t * ret)611 static int context_sum_weights(Context *context, FreeArea *a, uint64_t *ret) {
612         uint64_t weight_sum = 0;
613 
614         assert(context);
615         assert(a);
616         assert(ret);
617 
618         /* Determine the sum of the weights of all partitions placed in or before the specified free area */
619 
620         LIST_FOREACH(partitions, p, context->partitions) {
621                 if (p->padding_area != a && p->allocated_to_area != a)
622                         continue;
623 
624                 if (p->weight > UINT64_MAX - weight_sum)
625                         goto overflow_sum;
626                 weight_sum += p->weight;
627 
628                 if (p->padding_weight > UINT64_MAX - weight_sum)
629                         goto overflow_sum;
630                 weight_sum += p->padding_weight;
631         }
632 
633         *ret = weight_sum;
634         return 0;
635 
636 overflow_sum:
637         return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Combined weight of partition exceeds unsigned 64bit range, refusing.");
638 }
639 
scale_by_weight(uint64_t value,uint64_t weight,uint64_t weight_sum,uint64_t * ret)640 static int scale_by_weight(uint64_t value, uint64_t weight, uint64_t weight_sum, uint64_t *ret) {
641         assert(weight_sum >= weight);
642         assert(ret);
643 
644         if (weight == 0) {
645                 *ret = 0;
646                 return 0;
647         }
648 
649         if (value > UINT64_MAX / weight)
650                 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Scaling by weight of partition exceeds unsigned 64bit range, refusing.");
651 
652         *ret = value * weight / weight_sum;
653         return 0;
654 }
655 
656 typedef enum GrowPartitionPhase {
657         /* The first phase: we charge partitions which need more (according to constraints) than their weight-based share. */
658         PHASE_OVERCHARGE,
659 
660         /* The second phase: we charge partitions which need less (according to constraints) than their weight-based share. */
661         PHASE_UNDERCHARGE,
662 
663         /* The third phase: we distribute what remains among the remaining partitions, according to the weights */
664         PHASE_DISTRIBUTE,
665 
666         _GROW_PARTITION_PHASE_MAX,
667 } GrowPartitionPhase;
668 
context_grow_partitions_phase(Context * context,FreeArea * a,GrowPartitionPhase phase,uint64_t * span,uint64_t * weight_sum)669 static int context_grow_partitions_phase(
670                 Context *context,
671                 FreeArea *a,
672                 GrowPartitionPhase phase,
673                 uint64_t *span,
674                 uint64_t *weight_sum) {
675 
676         int r;
677 
678         assert(context);
679         assert(a);
680 
681         /* Now let's look at the intended weights and adjust them taking the minimum space assignments into
682          * account. i.e. if a partition has a small weight but a high minimum space value set it should not
683          * get any additional room from the left-overs. Similar, if two partitions have the same weight they
684          * should get the same space if possible, even if one has a smaller minimum size than the other. */
685         LIST_FOREACH(partitions, p, context->partitions) {
686 
687                 /* Look only at partitions associated with this free area, i.e. immediately
688                  * preceding it, or allocated into it */
689                 if (p->allocated_to_area != a && p->padding_area != a)
690                         continue;
691 
692                 if (p->new_size == UINT64_MAX) {
693                         bool charge = false, try_again = false;
694                         uint64_t share, rsz, xsz;
695 
696                         /* Calculate how much this space this partition needs if everyone would get
697                          * the weight based share */
698                         r = scale_by_weight(*span, p->weight, *weight_sum, &share);
699                         if (r < 0)
700                                 return r;
701 
702                         rsz = partition_min_size(context, p);
703                         xsz = partition_max_size(context, p);
704 
705                         if (phase == PHASE_OVERCHARGE && rsz > share) {
706                                 /* This partition needs more than its calculated share. Let's assign
707                                  * it that, and take this partition out of all calculations and start
708                                  * again. */
709 
710                                 p->new_size = rsz;
711                                 charge = try_again = true;
712 
713                         } else if (phase == PHASE_UNDERCHARGE && xsz != UINT64_MAX && xsz < share) {
714                                 /* This partition accepts less than its calculated
715                                  * share. Let's assign it that, and take this partition out
716                                  * of all calculations and start again. */
717 
718                                 p->new_size = xsz;
719                                 charge = try_again = true;
720 
721                         } else if (phase == PHASE_DISTRIBUTE) {
722                                 /* This partition can accept its calculated share. Let's
723                                  * assign it. There's no need to restart things here since
724                                  * assigning this shouldn't impact the shares of the other
725                                  * partitions. */
726 
727                                 if (PARTITION_IS_FOREIGN(p))
728                                         /* Never change of foreign partitions (i.e. those we don't manage) */
729                                         p->new_size = p->current_size;
730                                 else
731                                         p->new_size = MAX(round_down_size(share, context->grain_size), rsz);
732 
733                                 charge = true;
734                         }
735 
736                         if (charge) {
737                                 *span = charge_size(context, *span, p->new_size);
738                                 *weight_sum = charge_weight(*weight_sum, p->weight);
739                         }
740 
741                         if (try_again)
742                                 return 0; /* try again */
743                 }
744 
745                 if (p->new_padding == UINT64_MAX) {
746                         bool charge = false, try_again = false;
747                         uint64_t share;
748 
749                         r = scale_by_weight(*span, p->padding_weight, *weight_sum, &share);
750                         if (r < 0)
751                                 return r;
752 
753                         if (phase == PHASE_OVERCHARGE && p->padding_min != UINT64_MAX && p->padding_min > share) {
754                                 p->new_padding = p->padding_min;
755                                 charge = try_again = true;
756                         } else if (phase == PHASE_UNDERCHARGE && p->padding_max != UINT64_MAX && p->padding_max < share) {
757                                 p->new_padding = p->padding_max;
758                                 charge = try_again = true;
759                         } else if (phase == PHASE_DISTRIBUTE) {
760 
761                                 p->new_padding = round_down_size(share, context->grain_size);
762                                 if (p->padding_min != UINT64_MAX && p->new_padding < p->padding_min)
763                                         p->new_padding = p->padding_min;
764 
765                                 charge = true;
766                         }
767 
768                         if (charge) {
769                                 *span = charge_size(context, *span, p->new_padding);
770                                 *weight_sum = charge_weight(*weight_sum, p->padding_weight);
771                         }
772 
773                         if (try_again)
774                                 return 0; /* try again */
775                 }
776         }
777 
778         return 1; /* done */
779 }
780 
context_grow_partitions_on_free_area(Context * context,FreeArea * a)781 static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) {
782         uint64_t weight_sum = 0, span;
783         int r;
784 
785         assert(context);
786         assert(a);
787 
788         r = context_sum_weights(context, a, &weight_sum);
789         if (r < 0)
790                 return r;
791 
792         /* Let's calculate the total area covered by this free area and the partition before it */
793         span = a->size;
794         if (a->after) {
795                 assert(a->after->offset != UINT64_MAX);
796                 assert(a->after->current_size != UINT64_MAX);
797 
798                 span += round_up_size(a->after->offset + a->after->current_size, context->grain_size) - a->after->offset;
799         }
800 
801         for (GrowPartitionPhase phase = 0; phase < _GROW_PARTITION_PHASE_MAX;) {
802                 r = context_grow_partitions_phase(context, a, phase, &span, &weight_sum);
803                 if (r < 0)
804                         return r;
805                 if (r == 0) /* not done yet, re-run this phase */
806                         continue;
807 
808                 phase++; /* got to next phase */
809         }
810 
811         /* We still have space left over? Donate to preceding partition if we have one */
812         if (span > 0 && a->after && !PARTITION_IS_FOREIGN(a->after)) {
813                 uint64_t m, xsz;
814 
815                 assert(a->after->new_size != UINT64_MAX);
816 
817                 /* Calculate new size and align (but ensure this doesn't shrink the size) */
818                 m = MAX(a->after->new_size, round_down_size(a->after->new_size + span, context->grain_size));
819 
820                 xsz = partition_max_size(context, a->after);
821                 if (xsz != UINT64_MAX && m > xsz)
822                         m = xsz;
823 
824                 span = charge_size(context, span, m - a->after->new_size);
825                 a->after->new_size = m;
826         }
827 
828         /* What? Even still some space left (maybe because there was no preceding partition, or it had a
829          * size limit), then let's donate it to whoever wants it. */
830         if (span > 0)
831                 LIST_FOREACH(partitions, p, context->partitions) {
832                         uint64_t m, xsz;
833 
834                         if (p->allocated_to_area != a)
835                                 continue;
836 
837                         if (PARTITION_IS_FOREIGN(p))
838                                 continue;
839 
840                         assert(p->new_size != UINT64_MAX);
841                         m = MAX(p->new_size, round_down_size(p->new_size + span, context->grain_size));
842 
843                         xsz = partition_max_size(context, p);
844                         if (xsz != UINT64_MAX && m > xsz)
845                                 m = xsz;
846 
847                         span = charge_size(context, span, m - p->new_size);
848                         p->new_size = m;
849 
850                         if (span == 0)
851                                 break;
852                 }
853 
854         /* Yuck, still no one? Then make it padding */
855         if (span > 0 && a->after) {
856                 assert(a->after->new_padding != UINT64_MAX);
857                 a->after->new_padding += span;
858         }
859 
860         return 0;
861 }
862 
context_grow_partitions(Context * context)863 static int context_grow_partitions(Context *context) {
864         int r;
865 
866         assert(context);
867 
868         for (size_t i = 0; i < context->n_free_areas; i++) {
869                 r = context_grow_partitions_on_free_area(context, context->free_areas[i]);
870                 if (r < 0)
871                         return r;
872         }
873 
874         /* All existing partitions that have no free space after them can't change size */
875         LIST_FOREACH(partitions, p, context->partitions) {
876                 if (p->dropped)
877                         continue;
878 
879                 if (!PARTITION_EXISTS(p) || p->padding_area) {
880                         /* The algorithm above must have initialized this already */
881                         assert(p->new_size != UINT64_MAX);
882                         continue;
883                 }
884 
885                 assert(p->new_size == UINT64_MAX);
886                 p->new_size = p->current_size;
887 
888                 assert(p->new_padding == UINT64_MAX);
889                 p->new_padding = p->current_padding;
890         }
891 
892         return 0;
893 }
894 
context_place_partitions(Context * context)895 static void context_place_partitions(Context *context) {
896         uint64_t partno = 0;
897 
898         assert(context);
899 
900         /* Determine next partition number to assign */
901         LIST_FOREACH(partitions, p, context->partitions) {
902                 if (!PARTITION_EXISTS(p))
903                         continue;
904 
905                 assert(p->partno != UINT64_MAX);
906                 if (p->partno >= partno)
907                         partno = p->partno + 1;
908         }
909 
910         for (size_t i = 0; i < context->n_free_areas; i++) {
911                 FreeArea *a = context->free_areas[i];
912                 _unused_ uint64_t left;
913                 uint64_t start;
914 
915                 if (a->after) {
916                         assert(a->after->offset != UINT64_MAX);
917                         assert(a->after->new_size != UINT64_MAX);
918                         assert(a->after->new_padding != UINT64_MAX);
919 
920                         start = a->after->offset + a->after->new_size + a->after->new_padding;
921                 } else
922                         start = context->start;
923 
924                 start = round_up_size(start, context->grain_size);
925                 left = a->size;
926 
927                 LIST_FOREACH(partitions, p, context->partitions) {
928                         if (p->allocated_to_area != a)
929                                 continue;
930 
931                         p->offset = start;
932                         p->partno = partno++;
933 
934                         assert(left >= p->new_size);
935                         start += p->new_size;
936                         left -= p->new_size;
937 
938                         assert(left >= p->new_padding);
939                         start += p->new_padding;
940                         left -= p->new_padding;
941                 }
942         }
943 }
944 
config_parse_type(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)945 static int config_parse_type(
946                 const char *unit,
947                 const char *filename,
948                 unsigned line,
949                 const char *section,
950                 unsigned section_line,
951                 const char *lvalue,
952                 int ltype,
953                 const char *rvalue,
954                 void *data,
955                 void *userdata) {
956 
957         sd_id128_t *type_uuid = data;
958         int r;
959 
960         assert(rvalue);
961         assert(type_uuid);
962 
963         r = gpt_partition_type_uuid_from_string(rvalue, type_uuid);
964         if (r < 0)
965                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue);
966 
967         return 0;
968 }
969 
config_parse_label(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)970 static int config_parse_label(
971                 const char *unit,
972                 const char *filename,
973                 unsigned line,
974                 const char *section,
975                 unsigned section_line,
976                 const char *lvalue,
977                 int ltype,
978                 const char *rvalue,
979                 void *data,
980                 void *userdata) {
981 
982         _cleanup_free_ char *resolved = NULL;
983         char **label = data;
984         int r;
985 
986         assert(rvalue);
987         assert(label);
988 
989         /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
990          * assigning the empty string to reset to default here, but really accept it as label to set. */
991 
992         r = specifier_printf(rvalue, GPT_LABEL_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
993         if (r < 0) {
994                 log_syntax(unit, LOG_WARNING, filename, line, r,
995                            "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
996                 return 0;
997         }
998 
999         if (!utf8_is_valid(resolved)) {
1000                 log_syntax(unit, LOG_WARNING, filename, line, 0,
1001                            "Partition label not valid UTF-8, ignoring: %s", rvalue);
1002                 return 0;
1003         }
1004 
1005         r = gpt_partition_label_valid(resolved);
1006         if (r < 0) {
1007                 log_syntax(unit, LOG_WARNING, filename, line, r,
1008                            "Failed to check if string is valid as GPT partition label, ignoring: \"%s\" (from \"%s\")",
1009                            resolved, rvalue);
1010                 return 0;
1011         }
1012         if (!r) {
1013                 log_syntax(unit, LOG_WARNING, filename, line, 0,
1014                            "Partition label too long for GPT table, ignoring: \"%s\" (from \"%s\")",
1015                            resolved, rvalue);
1016                 return 0;
1017         }
1018 
1019         free_and_replace(*label, resolved);
1020         return 0;
1021 }
1022 
config_parse_weight(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1023 static int config_parse_weight(
1024                 const char *unit,
1025                 const char *filename,
1026                 unsigned line,
1027                 const char *section,
1028                 unsigned section_line,
1029                 const char *lvalue,
1030                 int ltype,
1031                 const char *rvalue,
1032                 void *data,
1033                 void *userdata) {
1034 
1035         uint32_t *priority = data, v;
1036         int r;
1037 
1038         assert(rvalue);
1039         assert(priority);
1040 
1041         r = safe_atou32(rvalue, &v);
1042         if (r < 0) {
1043                 log_syntax(unit, LOG_WARNING, filename, line, r,
1044                            "Failed to parse weight value, ignoring: %s", rvalue);
1045                 return 0;
1046         }
1047 
1048         if (v > 1000U*1000U) {
1049                 log_syntax(unit, LOG_WARNING, filename, line, 0,
1050                            "Weight needs to be in range 0…10000000, ignoring: %" PRIu32, v);
1051                 return 0;
1052         }
1053 
1054         *priority = v;
1055         return 0;
1056 }
1057 
config_parse_size4096(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1058 static int config_parse_size4096(
1059                 const char *unit,
1060                 const char *filename,
1061                 unsigned line,
1062                 const char *section,
1063                 unsigned section_line,
1064                 const char *lvalue,
1065                 int ltype,
1066                 const char *rvalue,
1067                 void *data,
1068                 void *userdata) {
1069 
1070         uint64_t *sz = data, parsed;
1071         int r;
1072 
1073         assert(rvalue);
1074         assert(data);
1075 
1076         r = parse_size(rvalue, 1024, &parsed);
1077         if (r < 0)
1078                 return log_syntax(unit, LOG_ERR, filename, line, r,
1079                                   "Failed to parse size value: %s", rvalue);
1080 
1081         if (ltype > 0)
1082                 *sz = round_up_size(parsed, 4096);
1083         else if (ltype < 0)
1084                 *sz = round_down_size(parsed, 4096);
1085         else
1086                 *sz = parsed;
1087 
1088         if (*sz != parsed)
1089                 log_syntax(unit, LOG_NOTICE, filename, line, r, "Rounded %s= size %" PRIu64 " → %" PRIu64 ", a multiple of 4096.", lvalue, parsed, *sz);
1090 
1091         return 0;
1092 }
1093 
config_parse_fstype(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1094 static int config_parse_fstype(
1095                 const char *unit,
1096                 const char *filename,
1097                 unsigned line,
1098                 const char *section,
1099                 unsigned section_line,
1100                 const char *lvalue,
1101                 int ltype,
1102                 const char *rvalue,
1103                 void *data,
1104                 void *userdata) {
1105 
1106         char **fstype = data;
1107 
1108         assert(rvalue);
1109         assert(data);
1110 
1111         if (!filename_is_valid(rvalue))
1112                 return log_syntax(unit, LOG_ERR, filename, line, 0,
1113                                   "File system type is not valid, refusing: %s", rvalue);
1114 
1115         return free_and_strdup_warn(fstype, rvalue);
1116 }
1117 
config_parse_copy_files(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1118 static int config_parse_copy_files(
1119                 const char *unit,
1120                 const char *filename,
1121                 unsigned line,
1122                 const char *section,
1123                 unsigned section_line,
1124                 const char *lvalue,
1125                 int ltype,
1126                 const char *rvalue,
1127                 void *data,
1128                 void *userdata) {
1129 
1130         _cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL;
1131         const char *p = rvalue, *target;
1132         Partition *partition = data;
1133         int r;
1134 
1135         assert(rvalue);
1136         assert(partition);
1137 
1138         r = extract_first_word(&p, &source, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1139         if (r < 0)
1140                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract source path: %s", rvalue);
1141         if (r == 0) {
1142                 log_syntax(unit, LOG_WARNING, filename, line, 0, "No argument specified: %s", rvalue);
1143                 return 0;
1144         }
1145 
1146         r = extract_first_word(&p, &buffer, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
1147         if (r < 0)
1148                 return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract target path: %s", rvalue);
1149         if (r == 0)
1150                 target = source; /* No target, then it's the same as the source */
1151         else
1152                 target = buffer;
1153 
1154         if (!isempty(p))
1155                 return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
1156 
1157         r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_source);
1158         if (r < 0) {
1159                 log_syntax(unit, LOG_WARNING, filename, line, r,
1160                            "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue);
1161                 return 0;
1162         }
1163 
1164         r = path_simplify_and_warn(resolved_source, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1165         if (r < 0)
1166                 return 0;
1167 
1168         r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_target);
1169         if (r < 0) {
1170                 log_syntax(unit, LOG_WARNING, filename, line, r,
1171                            "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target);
1172                 return 0;
1173         }
1174 
1175         r = path_simplify_and_warn(resolved_target, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1176         if (r < 0)
1177                 return 0;
1178 
1179         r = strv_consume_pair(&partition->copy_files, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target));
1180         if (r < 0)
1181                 return log_oom();
1182 
1183         return 0;
1184 }
1185 
config_parse_copy_blocks(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1186 static int config_parse_copy_blocks(
1187                 const char *unit,
1188                 const char *filename,
1189                 unsigned line,
1190                 const char *section,
1191                 unsigned section_line,
1192                 const char *lvalue,
1193                 int ltype,
1194                 const char *rvalue,
1195                 void *data,
1196                 void *userdata) {
1197 
1198         _cleanup_free_ char *d = NULL;
1199         Partition *partition = data;
1200         int r;
1201 
1202         assert(rvalue);
1203         assert(partition);
1204 
1205         if (isempty(rvalue)) {
1206                 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1207                 partition->copy_blocks_auto = false;
1208                 return 0;
1209         }
1210 
1211         if (streq(rvalue, "auto")) {
1212                 partition->copy_blocks_path = mfree(partition->copy_blocks_path);
1213                 partition->copy_blocks_auto = true;
1214                 return 0;
1215         }
1216 
1217         r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
1218         if (r < 0) {
1219                 log_syntax(unit, LOG_WARNING, filename, line, r,
1220                            "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
1221                 return 0;
1222         }
1223 
1224         r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1225         if (r < 0)
1226                 return 0;
1227 
1228         free_and_replace(partition->copy_blocks_path, d);
1229         partition->copy_blocks_auto = false;
1230         return 0;
1231 }
1232 
config_parse_make_dirs(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1233 static int config_parse_make_dirs(
1234                 const char *unit,
1235                 const char *filename,
1236                 unsigned line,
1237                 const char *section,
1238                 unsigned section_line,
1239                 const char *lvalue,
1240                 int ltype,
1241                 const char *rvalue,
1242                 void *data,
1243                 void *userdata) {
1244 
1245         Partition *partition = data;
1246         const char *p = rvalue;
1247         int r;
1248 
1249         assert(rvalue);
1250         assert(partition);
1251 
1252         for (;;) {
1253                 _cleanup_free_ char *word = NULL, *d = NULL;
1254 
1255                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
1256                 if (r == -ENOMEM)
1257                         return log_oom();
1258                 if (r < 0) {
1259                         log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
1260                         return 0;
1261                 }
1262                 if (r == 0)
1263                         return 0;
1264 
1265                 r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
1266                 if (r < 0) {
1267                         log_syntax(unit, LOG_WARNING, filename, line, r,
1268                                    "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);
1269                         continue;
1270                 }
1271 
1272                 r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
1273                 if (r < 0)
1274                         continue;
1275 
1276                 r = strv_consume(&partition->make_directories, TAKE_PTR(d));
1277                 if (r < 0)
1278                         return log_oom();
1279         }
1280 }
1281 
1282 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt, encrypt_mode, EncryptMode, ENCRYPT_OFF, "Invalid encryption mode");
1283 
config_parse_gpt_flags(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)1284 static int config_parse_gpt_flags(
1285                 const char *unit,
1286                 const char *filename,
1287                 unsigned line,
1288                 const char *section,
1289                 unsigned section_line,
1290                 const char *lvalue,
1291                 int ltype,
1292                 const char *rvalue,
1293                 void *data,
1294                 void *userdata) {
1295 
1296         uint64_t *gpt_flags = data;
1297         int r;
1298 
1299         assert(rvalue);
1300         assert(gpt_flags);
1301 
1302         r = safe_atou64(rvalue, gpt_flags);
1303         if (r < 0) {
1304                 log_syntax(unit, LOG_WARNING, filename, line, r,
1305                            "Failed to parse Flags= value, ignoring: %s", rvalue);
1306                 return 0;
1307         }
1308 
1309         return 0;
1310 }
1311 
partition_read_definition(Partition * p,const char * path)1312 static int partition_read_definition(Partition *p, const char *path) {
1313 
1314         ConfigTableItem table[] = {
1315                 { "Partition", "Type",            config_parse_type,        0, &p->type_uuid        },
1316                 { "Partition", "Label",           config_parse_label,       0, &p->new_label        },
1317                 { "Partition", "UUID",            config_parse_id128,       0, &p->new_uuid         },
1318                 { "Partition", "Priority",        config_parse_int32,       0, &p->priority         },
1319                 { "Partition", "Weight",          config_parse_weight,      0, &p->weight           },
1320                 { "Partition", "PaddingWeight",   config_parse_weight,      0, &p->padding_weight   },
1321                 { "Partition", "SizeMinBytes",    config_parse_size4096,    1, &p->size_min         },
1322                 { "Partition", "SizeMaxBytes",    config_parse_size4096,   -1, &p->size_max         },
1323                 { "Partition", "PaddingMinBytes", config_parse_size4096,    1, &p->padding_min      },
1324                 { "Partition", "PaddingMaxBytes", config_parse_size4096,   -1, &p->padding_max      },
1325                 { "Partition", "FactoryReset",    config_parse_bool,        0, &p->factory_reset    },
1326                 { "Partition", "CopyBlocks",      config_parse_copy_blocks, 0, p                    },
1327                 { "Partition", "Format",          config_parse_fstype,      0, &p->format           },
1328                 { "Partition", "CopyFiles",       config_parse_copy_files,  0, p                    },
1329                 { "Partition", "MakeDirectories", config_parse_make_dirs,   0, p                    },
1330                 { "Partition", "Encrypt",         config_parse_encrypt,     0, &p->encrypt          },
1331                 { "Partition", "Flags",           config_parse_gpt_flags,   0, &p->gpt_flags        },
1332                 { "Partition", "ReadOnly",        config_parse_tristate,    0, &p->read_only        },
1333                 { "Partition", "NoAuto",          config_parse_tristate,    0, &p->no_auto          },
1334                 { "Partition", "GrowFileSystem",  config_parse_tristate,    0, &p->growfs           },
1335                 {}
1336         };
1337         int r;
1338 
1339         r = config_parse(NULL, path, NULL,
1340                          "Partition\0",
1341                          config_item_table_lookup, table,
1342                          CONFIG_PARSE_WARN,
1343                          p,
1344                          NULL);
1345         if (r < 0)
1346                 return r;
1347 
1348         if (p->size_min != UINT64_MAX && p->size_max != UINT64_MAX && p->size_min > p->size_max)
1349                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1350                                   "SizeMinBytes= larger than SizeMaxBytes=, refusing.");
1351 
1352         if (p->padding_min != UINT64_MAX && p->padding_max != UINT64_MAX && p->padding_min > p->padding_max)
1353                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1354                                   "PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
1355 
1356         if (sd_id128_is_null(p->type_uuid))
1357                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1358                                   "Type= not defined, refusing.");
1359 
1360         if ((p->copy_blocks_path || p->copy_blocks_auto) &&
1361             (p->format || !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)))
1362                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1363                                   "Format=/CopyFiles=/MakeDirectories= and CopyBlocks= cannot be combined, refusing.");
1364 
1365         if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && streq_ptr(p->format, "swap"))
1366                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
1367                                   "Format=swap and CopyFiles= cannot be combined, refusing.");
1368 
1369         if (!p->format && (!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories) || (p->encrypt != ENCRYPT_OFF && !(p->copy_blocks_path || p->copy_blocks_auto)))) {
1370                 /* Pick "ext4" as file system if we are configured to copy files or encrypt the device */
1371                 p->format = strdup("ext4");
1372                 if (!p->format)
1373                         return log_oom();
1374         }
1375 
1376         /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
1377         if ((gpt_partition_type_is_root_verity(p->type_uuid) ||
1378              gpt_partition_type_is_usr_verity(p->type_uuid)) &&
1379             p->read_only < 0)
1380                 p->read_only = true;
1381 
1382         /* Default to "growfs" on, unless read-only */
1383         if (gpt_partition_type_knows_growfs(p->type_uuid) &&
1384             p->read_only <= 0)
1385                 p->growfs = true;
1386 
1387         return 0;
1388 }
1389 
context_read_definitions(Context * context,const char * directory,const char * root)1390 static int context_read_definitions(
1391                 Context *context,
1392                 const char *directory,
1393                 const char *root) {
1394 
1395         _cleanup_strv_free_ char **files = NULL;
1396         Partition *last = NULL;
1397         int r;
1398 
1399         assert(context);
1400 
1401         if (directory)
1402                 r = conf_files_list_strv(&files, ".conf", NULL, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) STRV_MAKE(directory));
1403         else
1404                 r = conf_files_list_strv(&files, ".conf", root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) CONF_PATHS_STRV("repart.d"));
1405         if (r < 0)
1406                 return log_error_errno(r, "Failed to enumerate *.conf files: %m");
1407 
1408         STRV_FOREACH(f, files) {
1409                 _cleanup_(partition_freep) Partition *p = NULL;
1410 
1411                 p = partition_new();
1412                 if (!p)
1413                         return log_oom();
1414 
1415                 p->definition_path = strdup(*f);
1416                 if (!p->definition_path)
1417                         return log_oom();
1418 
1419                 r = partition_read_definition(p, *f);
1420                 if (r < 0)
1421                         return r;
1422 
1423                 LIST_INSERT_AFTER(partitions, context->partitions, last, p);
1424                 last = TAKE_PTR(p);
1425                 context->n_partitions++;
1426         }
1427 
1428         return 0;
1429 }
1430 
determine_current_padding(struct fdisk_context * c,struct fdisk_table * t,struct fdisk_partition * p,uint64_t secsz,uint64_t grainsz,uint64_t * ret)1431 static int determine_current_padding(
1432                 struct fdisk_context *c,
1433                 struct fdisk_table *t,
1434                 struct fdisk_partition *p,
1435                 uint64_t secsz,
1436                 uint64_t grainsz,
1437                 uint64_t *ret) {
1438 
1439         size_t n_partitions;
1440         uint64_t offset, next = UINT64_MAX;
1441 
1442         assert(c);
1443         assert(t);
1444         assert(p);
1445 
1446         if (!fdisk_partition_has_end(p))
1447                 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition has no end!");
1448 
1449         offset = fdisk_partition_get_end(p);
1450         assert(offset < UINT64_MAX / secsz);
1451         offset *= secsz;
1452 
1453         n_partitions = fdisk_table_get_nents(t);
1454         for (size_t i = 0; i < n_partitions; i++)  {
1455                 struct fdisk_partition *q;
1456                 uint64_t start;
1457 
1458                 q = fdisk_table_get_partition(t, i);
1459                 if (!q)
1460                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1461 
1462                 if (fdisk_partition_is_used(q) <= 0)
1463                         continue;
1464 
1465                 if (!fdisk_partition_has_start(q))
1466                         continue;
1467 
1468                 start = fdisk_partition_get_start(q);
1469                 assert(start < UINT64_MAX / secsz);
1470                 start *= secsz;
1471 
1472                 if (start >= offset && (next == UINT64_MAX || next > start))
1473                         next = start;
1474         }
1475 
1476         if (next == UINT64_MAX) {
1477                 /* No later partition? In that case check the end of the usable area */
1478                 next = fdisk_get_last_lba(c);
1479                 assert(next < UINT64_MAX);
1480                 next++; /* The last LBA is one sector before the end */
1481 
1482                 assert(next < UINT64_MAX / secsz);
1483                 next *= secsz;
1484 
1485                 if (offset > next)
1486                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
1487         }
1488 
1489         assert(next >= offset);
1490         offset = round_up_size(offset, grainsz);
1491         next = round_down_size(next, grainsz);
1492 
1493         *ret = LESS_BY(next, offset); /* Saturated subtraction, rounding might have fucked things up */
1494         return 0;
1495 }
1496 
fdisk_ask_cb(struct fdisk_context * c,struct fdisk_ask * ask,void * data)1497 static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *data) {
1498         _cleanup_free_ char *ids = NULL;
1499         int r;
1500 
1501         if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
1502                 return -EINVAL;
1503 
1504         ids = new(char, SD_ID128_UUID_STRING_MAX);
1505         if (!ids)
1506                 return -ENOMEM;
1507 
1508         r = fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids));
1509         if (r < 0)
1510                 return r;
1511 
1512         TAKE_PTR(ids);
1513         return 0;
1514 }
1515 
fdisk_set_disklabel_id_by_uuid(struct fdisk_context * c,sd_id128_t id)1516 static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id) {
1517         int r;
1518 
1519         r = fdisk_set_ask(c, fdisk_ask_cb, &id);
1520         if (r < 0)
1521                 return r;
1522 
1523         r = fdisk_set_disklabel_id(c);
1524         if (r < 0)
1525                 return r;
1526 
1527         return fdisk_set_ask(c, NULL, NULL);
1528 }
1529 
derive_uuid(sd_id128_t base,const char * token,sd_id128_t * ret)1530 static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) {
1531         union {
1532                 uint8_t md[SHA256_DIGEST_SIZE];
1533                 sd_id128_t id;
1534         } result;
1535 
1536         assert(token);
1537         assert(ret);
1538 
1539         /* Derive a new UUID from the specified UUID in a stable and reasonably safe way. Specifically, we
1540          * calculate the HMAC-SHA256 of the specified token string, keyed by the supplied base (typically the
1541          * machine ID). We use the machine ID as key (and not as cleartext!) of the HMAC operation since it's
1542          * the machine ID we don't want to leak. */
1543 
1544         hmac_sha256(base.bytes, sizeof(base.bytes), token, strlen(token), result.md);
1545 
1546         /* Take the first half, mark it as v4 UUID */
1547         assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
1548         *ret = id128_make_v4_uuid(result.id);
1549         return 0;
1550 }
1551 
context_load_partition_table(Context * context,const char * node,int * backing_fd)1552 static int context_load_partition_table(
1553                 Context *context,
1554                 const char *node,
1555                 int *backing_fd) {
1556 
1557         _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
1558         _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
1559         uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors;
1560         _cleanup_free_ char *disk_uuid_string = NULL;
1561         bool from_scratch = false;
1562         sd_id128_t disk_uuid;
1563         size_t n_partitions;
1564         unsigned long secsz;
1565         uint64_t grainsz;
1566         int r;
1567 
1568         assert(context);
1569         assert(node);
1570         assert(backing_fd);
1571         assert(!context->fdisk_context);
1572         assert(!context->free_areas);
1573         assert(context->start == UINT64_MAX);
1574         assert(context->end == UINT64_MAX);
1575         assert(context->total == UINT64_MAX);
1576 
1577         c = fdisk_new_context();
1578         if (!c)
1579                 return log_oom();
1580 
1581         /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
1582          * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
1583         if (*backing_fd < 0)
1584                 r = fdisk_assign_device(c, node, arg_dry_run);
1585         else
1586                 r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(*backing_fd), arg_dry_run);
1587         if (r == -EINVAL && arg_size_auto) {
1588                 struct stat st;
1589 
1590                 /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept
1591                  * it if automatic sizing is requested. */
1592 
1593                 if (*backing_fd < 0)
1594                         r = stat(node, &st);
1595                 else
1596                         r = fstat(*backing_fd, &st);
1597                 if (r < 0)
1598                         return log_error_errno(errno, "Failed to stat block device '%s': %m", node);
1599 
1600                 if (S_ISREG(st.st_mode) && st.st_size == 0) {
1601                         /* User the fallback values if we have no better idea */
1602                         context->sector_size = 512;
1603                         context->grain_size = 4096;
1604                         return /* from_scratch = */ true;
1605                 }
1606 
1607                 r = -EINVAL;
1608         }
1609         if (r < 0)
1610                 return log_error_errno(r, "Failed to open device '%s': %m", node);
1611 
1612         if (*backing_fd < 0) {
1613                 /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
1614                 *backing_fd = fcntl(fdisk_get_devfd(c), F_DUPFD_CLOEXEC, 3);
1615                 if (*backing_fd < 0)
1616                         return log_error_errno(errno, "Failed to duplicate fdisk fd: %m");
1617         }
1618 
1619         /* Tell udev not to interfere while we are processing the device */
1620         if (flock(fdisk_get_devfd(c), arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
1621                 return log_error_errno(errno, "Failed to lock block device: %m");
1622 
1623         /* The offsets/sizes libfdisk returns to us will be in multiple of the sector size of the
1624          * device. This is typically 512, and sometimes 4096. Let's query libfdisk once for it, and then use
1625          * it for all our needs. Note that the values we use ourselves always are in bytes though, thus mean
1626          * the same thing universally. Also note that regardless what kind of sector size is in use we'll
1627          * place partitions at multiples of 4K. */
1628         secsz = fdisk_get_sector_size(c);
1629 
1630         /* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
1631         if (secsz < 512 || secsz != 1UL << log2u64(secsz))
1632                 return log_error_errno(errno, "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
1633 
1634         /* Use at least 4K, and ensure it's a multiple of the sector size, regardless if that is smaller or
1635          * larger */
1636         grainsz = secsz < 4096 ? 4096 : secsz;
1637 
1638         log_debug("Sector size of device is %lu bytes. Using grain size of %" PRIu64 ".", secsz, grainsz);
1639 
1640         switch (arg_empty) {
1641 
1642         case EMPTY_REFUSE:
1643                 /* Refuse empty disks, insist on an existing GPT partition table */
1644                 if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1645                         return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", node);
1646 
1647                 break;
1648 
1649         case EMPTY_REQUIRE:
1650                 /* Require an empty disk, refuse any existing partition table */
1651                 r = fdisk_has_label(c);
1652                 if (r < 0)
1653                         return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1654                 if (r > 0)
1655                         return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", node);
1656 
1657                 from_scratch = true;
1658                 break;
1659 
1660         case EMPTY_ALLOW:
1661                 /* Allow both an empty disk and an existing partition table, but only GPT */
1662                 r = fdisk_has_label(c);
1663                 if (r < 0)
1664                         return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node);
1665                 if (r > 0) {
1666                         if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
1667                                 return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", node);
1668                 } else
1669                         from_scratch = true;
1670 
1671                 break;
1672 
1673         case EMPTY_FORCE:
1674         case EMPTY_CREATE:
1675                 /* Always reinitiaize the disk, don't consider what there was on the disk before */
1676                 from_scratch = true;
1677                 break;
1678         }
1679 
1680         if (from_scratch) {
1681                 r = fdisk_create_disklabel(c, "gpt");
1682                 if (r < 0)
1683                         return log_error_errno(r, "Failed to create GPT disk label: %m");
1684 
1685                 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
1686                 if (r < 0)
1687                         return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1688 
1689                 r = fdisk_set_disklabel_id_by_uuid(c, disk_uuid);
1690                 if (r < 0)
1691                         return log_error_errno(r, "Failed to set GPT disk label: %m");
1692 
1693                 goto add_initial_free_area;
1694         }
1695 
1696         r = fdisk_get_disklabel_id(c, &disk_uuid_string);
1697         if (r < 0)
1698                 return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
1699 
1700         r = sd_id128_from_string(disk_uuid_string, &disk_uuid);
1701         if (r < 0)
1702                 return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
1703 
1704         if (sd_id128_is_null(disk_uuid)) {
1705                 r = derive_uuid(context->seed, "disk-uuid", &disk_uuid);
1706                 if (r < 0)
1707                         return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
1708 
1709                 r = fdisk_set_disklabel_id(c);
1710                 if (r < 0)
1711                         return log_error_errno(r, "Failed to set GPT disk label: %m");
1712         }
1713 
1714         r = fdisk_get_partitions(c, &t);
1715         if (r < 0)
1716                 return log_error_errno(r, "Failed to acquire partition table: %m");
1717 
1718         n_partitions = fdisk_table_get_nents(t);
1719         for (size_t i = 0; i < n_partitions; i++)  {
1720                 _cleanup_free_ char *label_copy = NULL;
1721                 Partition *last = NULL;
1722                 struct fdisk_partition *p;
1723                 struct fdisk_parttype *pt;
1724                 const char *pts, *ids, *label;
1725                 uint64_t sz, start;
1726                 bool found = false;
1727                 sd_id128_t ptid, id;
1728                 size_t partno;
1729 
1730                 p = fdisk_table_get_partition(t, i);
1731                 if (!p)
1732                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata: %m");
1733 
1734                 if (fdisk_partition_is_used(p) <= 0)
1735                         continue;
1736 
1737                 if (fdisk_partition_has_start(p) <= 0 ||
1738                     fdisk_partition_has_size(p) <= 0 ||
1739                     fdisk_partition_has_partno(p) <= 0)
1740                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
1741 
1742                 pt = fdisk_partition_get_type(p);
1743                 if (!pt)
1744                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition: %m");
1745 
1746                 pts = fdisk_parttype_get_string(pt);
1747                 if (!pts)
1748                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire type of partition as string: %m");
1749 
1750                 r = sd_id128_from_string(pts, &ptid);
1751                 if (r < 0)
1752                         return log_error_errno(r, "Failed to parse partition type UUID %s: %m", pts);
1753 
1754                 ids = fdisk_partition_get_uuid(p);
1755                 if (!ids)
1756                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a UUID.");
1757 
1758                 r = sd_id128_from_string(ids, &id);
1759                 if (r < 0)
1760                         return log_error_errno(r, "Failed to parse partition UUID %s: %m", ids);
1761 
1762                 label = fdisk_partition_get_name(p);
1763                 if (!isempty(label)) {
1764                         label_copy = strdup(label);
1765                         if (!label_copy)
1766                                 return log_oom();
1767                 }
1768 
1769                 sz = fdisk_partition_get_size(p);
1770                 assert(sz <= UINT64_MAX/secsz);
1771                 sz *= secsz;
1772 
1773                 start = fdisk_partition_get_start(p);
1774                 assert(start <= UINT64_MAX/secsz);
1775                 start *= secsz;
1776 
1777                 partno = fdisk_partition_get_partno(p);
1778 
1779                 if (left_boundary == UINT64_MAX || left_boundary > start)
1780                         left_boundary = start;
1781 
1782                 /* Assign this existing partition to the first partition of the right type that doesn't have
1783                  * an existing one assigned yet. */
1784                 LIST_FOREACH(partitions, pp, context->partitions) {
1785                         last = pp;
1786 
1787                         if (!sd_id128_equal(pp->type_uuid, ptid))
1788                                 continue;
1789 
1790                         if (!pp->current_partition) {
1791                                 pp->current_uuid = id;
1792                                 pp->current_size = sz;
1793                                 pp->offset = start;
1794                                 pp->partno = partno;
1795                                 pp->current_label = TAKE_PTR(label_copy);
1796 
1797                                 pp->current_partition = p;
1798                                 fdisk_ref_partition(p);
1799 
1800                                 r = determine_current_padding(c, t, p, secsz, grainsz, &pp->current_padding);
1801                                 if (r < 0)
1802                                         return r;
1803 
1804                                 if (pp->current_padding > 0) {
1805                                         r = context_add_free_area(context, pp->current_padding, pp);
1806                                         if (r < 0)
1807                                                 return r;
1808                                 }
1809 
1810                                 found = true;
1811                                 break;
1812                         }
1813                 }
1814 
1815                 /* If we have no matching definition, create a new one. */
1816                 if (!found) {
1817                         _cleanup_(partition_freep) Partition *np = NULL;
1818 
1819                         np = partition_new();
1820                         if (!np)
1821                                 return log_oom();
1822 
1823                         np->current_uuid = id;
1824                         np->type_uuid = ptid;
1825                         np->current_size = sz;
1826                         np->offset = start;
1827                         np->partno = partno;
1828                         np->current_label = TAKE_PTR(label_copy);
1829 
1830                         np->current_partition = p;
1831                         fdisk_ref_partition(p);
1832 
1833                         r = determine_current_padding(c, t, p, secsz, grainsz, &np->current_padding);
1834                         if (r < 0)
1835                                 return r;
1836 
1837                         if (np->current_padding > 0) {
1838                                 r = context_add_free_area(context, np->current_padding, np);
1839                                 if (r < 0)
1840                                         return r;
1841                         }
1842 
1843                         LIST_INSERT_AFTER(partitions, context->partitions, last, TAKE_PTR(np));
1844                         context->n_partitions++;
1845                 }
1846         }
1847 
1848 add_initial_free_area:
1849         nsectors = fdisk_get_nsectors(c);
1850         assert(nsectors <= UINT64_MAX/secsz);
1851         nsectors *= secsz;
1852 
1853         first_lba = fdisk_get_first_lba(c);
1854         assert(first_lba <= UINT64_MAX/secsz);
1855         first_lba *= secsz;
1856 
1857         last_lba = fdisk_get_last_lba(c);
1858         assert(last_lba < UINT64_MAX);
1859         last_lba++;
1860         assert(last_lba <= UINT64_MAX/secsz);
1861         last_lba *= secsz;
1862 
1863         assert(last_lba >= first_lba);
1864 
1865         if (left_boundary == UINT64_MAX) {
1866                 /* No partitions at all? Then the whole disk is up for grabs. */
1867 
1868                 first_lba = round_up_size(first_lba, grainsz);
1869                 last_lba = round_down_size(last_lba, grainsz);
1870 
1871                 if (last_lba > first_lba) {
1872                         r = context_add_free_area(context, last_lba - first_lba, NULL);
1873                         if (r < 0)
1874                                 return r;
1875                 }
1876         } else {
1877                 /* Add space left of first partition */
1878                 assert(left_boundary >= first_lba);
1879 
1880                 first_lba = round_up_size(first_lba, grainsz);
1881                 left_boundary = round_down_size(left_boundary, grainsz);
1882                 last_lba = round_down_size(last_lba, grainsz);
1883 
1884                 if (left_boundary > first_lba) {
1885                         r = context_add_free_area(context, left_boundary - first_lba, NULL);
1886                         if (r < 0)
1887                                 return r;
1888                 }
1889         }
1890 
1891         context->start = first_lba;
1892         context->end = last_lba;
1893         context->total = nsectors;
1894         context->sector_size = secsz;
1895         context->grain_size = grainsz;
1896         context->fdisk_context = TAKE_PTR(c);
1897 
1898         return from_scratch;
1899 }
1900 
context_unload_partition_table(Context * context)1901 static void context_unload_partition_table(Context *context) {
1902         assert(context);
1903 
1904         LIST_FOREACH(partitions, p, context->partitions) {
1905 
1906                 /* Entirely remove partitions that have no configuration */
1907                 if (PARTITION_IS_FOREIGN(p)) {
1908                         partition_unlink_and_free(context, p);
1909                         continue;
1910                 }
1911 
1912                 /* Otherwise drop all data we read off the block device and everything we might have
1913                  * calculated based on it */
1914 
1915                 p->dropped = false;
1916                 p->current_size = UINT64_MAX;
1917                 p->new_size = UINT64_MAX;
1918                 p->current_padding = UINT64_MAX;
1919                 p->new_padding = UINT64_MAX;
1920                 p->partno = UINT64_MAX;
1921                 p->offset = UINT64_MAX;
1922 
1923                 if (p->current_partition) {
1924                         fdisk_unref_partition(p->current_partition);
1925                         p->current_partition = NULL;
1926                 }
1927 
1928                 if (p->new_partition) {
1929                         fdisk_unref_partition(p->new_partition);
1930                         p->new_partition = NULL;
1931                 }
1932 
1933                 p->padding_area = NULL;
1934                 p->allocated_to_area = NULL;
1935 
1936                 p->current_uuid = SD_ID128_NULL;
1937                 p->current_label = mfree(p->current_label);
1938         }
1939 
1940         context->start = UINT64_MAX;
1941         context->end = UINT64_MAX;
1942         context->total = UINT64_MAX;
1943 
1944         if (context->fdisk_context) {
1945                 fdisk_unref_context(context->fdisk_context);
1946                 context->fdisk_context = NULL;
1947         }
1948 
1949         context_free_free_areas(context);
1950 }
1951 
format_size_change(uint64_t from,uint64_t to,char ** ret)1952 static int format_size_change(uint64_t from, uint64_t to, char **ret) {
1953         char *t;
1954 
1955         if (from != UINT64_MAX) {
1956                 if (from == to || to == UINT64_MAX)
1957                         t = strdup(FORMAT_BYTES(from));
1958                 else
1959                         t = strjoin(FORMAT_BYTES(from), " ", special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
1960         } else if (to != UINT64_MAX)
1961                 t = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), " ", FORMAT_BYTES(to));
1962         else {
1963                 *ret = NULL;
1964                 return 0;
1965         }
1966 
1967         if (!t)
1968                 return log_oom();
1969 
1970         *ret = t;
1971         return 1;
1972 }
1973 
partition_label(const Partition * p)1974 static const char *partition_label(const Partition *p) {
1975         assert(p);
1976 
1977         if (p->new_label)
1978                 return p->new_label;
1979 
1980         if (p->current_label)
1981                 return p->current_label;
1982 
1983         return gpt_partition_type_uuid_to_string(p->type_uuid);
1984 }
1985 
context_dump_partitions(Context * context,const char * node)1986 static int context_dump_partitions(Context *context, const char *node) {
1987         _cleanup_(table_unrefp) Table *t = NULL;
1988         uint64_t sum_padding = 0, sum_size = 0;
1989         int r;
1990 
1991         if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) {
1992                 log_info("Empty partition table.");
1993                 return 0;
1994         }
1995 
1996         t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity");
1997         if (!t)
1998                 return log_oom();
1999 
2000         if (!DEBUG_LOGGING) {
2001                 if (arg_json_format_flags & JSON_FORMAT_OFF)
2002                         (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2003                                                     (size_t) 8, (size_t) 11);
2004                 else
2005                         (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
2006                                                     (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12);
2007         }
2008 
2009         (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
2010         (void) table_set_align_percent(t, table_get_cell(t, 0, 6), 100);
2011         (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100);
2012         (void) table_set_align_percent(t, table_get_cell(t, 0, 8), 100);
2013         (void) table_set_align_percent(t, table_get_cell(t, 0, 9), 100);
2014         (void) table_set_align_percent(t, table_get_cell(t, 0, 10), 100);
2015         (void) table_set_align_percent(t, table_get_cell(t, 0, 11), 100);
2016 
2017         LIST_FOREACH(partitions, p, context->partitions) {
2018                 _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
2019                 char uuid_buffer[SD_ID128_UUID_STRING_MAX];
2020                 const char *label, *activity = NULL;
2021 
2022                 if (p->dropped)
2023                         continue;
2024 
2025                 if (p->current_size == UINT64_MAX)
2026                         activity = "create";
2027                 else if (p->current_size != p->new_size)
2028                         activity = "resize";
2029 
2030                 label = partition_label(p);
2031                 partname = p->partno != UINT64_MAX ? fdisk_partname(node, p->partno+1) : NULL;
2032 
2033                 r = format_size_change(p->current_size, p->new_size, &size_change);
2034                 if (r < 0)
2035                         return r;
2036 
2037                 r = format_size_change(p->current_padding, p->new_padding, &padding_change);
2038                 if (r < 0)
2039                         return r;
2040 
2041                 if (p->new_size != UINT64_MAX)
2042                         sum_size += p->new_size;
2043                 if (p->new_padding != UINT64_MAX)
2044                         sum_padding += p->new_padding;
2045 
2046                 r = table_add_many(
2047                                 t,
2048                                 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
2049                                 TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
2050                                 TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid,
2051                                 TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
2052                                 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
2053                                 TABLE_UINT64, p->offset,
2054                                 TABLE_UINT64, p->current_size == UINT64_MAX ? 0 : p->current_size,
2055                                 TABLE_UINT64, p->new_size,
2056                                 TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL,
2057                                 TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding,
2058                                 TABLE_UINT64, p->new_padding,
2059                                 TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL,
2060                                 TABLE_STRING, activity ?: "unchanged");
2061                 if (r < 0)
2062                         return table_log_add_error(r);
2063         }
2064 
2065         if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) {
2066                 const char *a, *b;
2067 
2068                 a = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_size));
2069                 b = strjoina(special_glyph(SPECIAL_GLYPH_SIGMA), " = ", FORMAT_BYTES(sum_padding));
2070 
2071                 r = table_add_many(
2072                                 t,
2073                                 TABLE_EMPTY,
2074                                 TABLE_EMPTY,
2075                                 TABLE_EMPTY,
2076                                 TABLE_EMPTY,
2077                                 TABLE_EMPTY,
2078                                 TABLE_EMPTY,
2079                                 TABLE_EMPTY,
2080                                 TABLE_EMPTY,
2081                                 TABLE_STRING, a,
2082                                 TABLE_EMPTY,
2083                                 TABLE_EMPTY,
2084                                 TABLE_STRING, b,
2085                                 TABLE_EMPTY);
2086                 if (r < 0)
2087                         return table_log_add_error(r);
2088         }
2089 
2090         return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
2091 }
2092 
context_bar_char_process_partition(Context * context,Partition * bar[],size_t n,Partition * p,size_t * ret_start)2093 static void context_bar_char_process_partition(
2094                 Context *context,
2095                 Partition *bar[],
2096                 size_t n,
2097                 Partition *p,
2098                 size_t *ret_start) {
2099 
2100         uint64_t from, to, total;
2101         size_t x, y;
2102 
2103         assert(context);
2104         assert(bar);
2105         assert(n > 0);
2106         assert(p);
2107 
2108         if (p->dropped)
2109                 return;
2110 
2111         assert(p->offset != UINT64_MAX);
2112         assert(p->new_size != UINT64_MAX);
2113 
2114         from = p->offset;
2115         to = from + p->new_size;
2116 
2117         assert(context->total > 0);
2118         total = context->total;
2119 
2120         assert(from <= total);
2121         x = from * n / total;
2122 
2123         assert(to <= total);
2124         y = to * n / total;
2125 
2126         assert(x <= y);
2127         assert(y <= n);
2128 
2129         for (size_t i = x; i < y; i++)
2130                 bar[i] = p;
2131 
2132         *ret_start = x;
2133 }
2134 
partition_hint(const Partition * p,const char * node,char ** ret)2135 static int partition_hint(const Partition *p, const char *node, char **ret) {
2136         _cleanup_free_ char *buf = NULL;
2137         const char *label;
2138         sd_id128_t id;
2139 
2140         /* Tries really hard to find a suitable description for this partition */
2141 
2142         if (p->definition_path) {
2143                 buf = strdup(basename(p->definition_path));
2144                 goto done;
2145         }
2146 
2147         label = partition_label(p);
2148         if (!isempty(label)) {
2149                 buf = strdup(label);
2150                 goto done;
2151         }
2152 
2153         if (p->partno != UINT64_MAX) {
2154                 buf = fdisk_partname(node, p->partno+1);
2155                 goto done;
2156         }
2157 
2158         if (!sd_id128_is_null(p->new_uuid))
2159                 id = p->new_uuid;
2160         else if (!sd_id128_is_null(p->current_uuid))
2161                 id = p->current_uuid;
2162         else
2163                 id = p->type_uuid;
2164 
2165         buf = strdup(SD_ID128_TO_UUID_STRING(id));
2166 
2167 done:
2168         if (!buf)
2169                 return -ENOMEM;
2170 
2171         *ret = TAKE_PTR(buf);
2172         return 0;
2173 }
2174 
context_dump_partition_bar(Context * context,const char * node)2175 static int context_dump_partition_bar(Context *context, const char *node) {
2176         _cleanup_free_ Partition **bar = NULL;
2177         _cleanup_free_ size_t *start_array = NULL;
2178         Partition *last = NULL;
2179         bool z = false;
2180         size_t c, j = 0;
2181 
2182         assert_se((c = columns()) >= 2);
2183         c -= 2; /* We do not use the leftmost and rightmost character cell */
2184 
2185         bar = new0(Partition*, c);
2186         if (!bar)
2187                 return log_oom();
2188 
2189         start_array = new(size_t, context->n_partitions);
2190         if (!start_array)
2191                 return log_oom();
2192 
2193         LIST_FOREACH(partitions, p, context->partitions)
2194                 context_bar_char_process_partition(context, bar, c, p, start_array + j++);
2195 
2196         putc(' ', stdout);
2197 
2198         for (size_t i = 0; i < c; i++) {
2199                 if (bar[i]) {
2200                         if (last != bar[i])
2201                                 z = !z;
2202 
2203                         fputs(z ? ansi_green() : ansi_yellow(), stdout);
2204                         fputs(special_glyph(SPECIAL_GLYPH_DARK_SHADE), stdout);
2205                 } else {
2206                         fputs(ansi_normal(), stdout);
2207                         fputs(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), stdout);
2208                 }
2209 
2210                 last = bar[i];
2211         }
2212 
2213         fputs(ansi_normal(), stdout);
2214         putc('\n', stdout);
2215 
2216         for (size_t i = 0; i < context->n_partitions; i++) {
2217                 _cleanup_free_ char **line = NULL;
2218 
2219                 line = new0(char*, c);
2220                 if (!line)
2221                         return log_oom();
2222 
2223                 j = 0;
2224                 LIST_FOREACH(partitions, p, context->partitions) {
2225                         _cleanup_free_ char *d = NULL;
2226                         j++;
2227 
2228                         if (i < context->n_partitions - j) {
2229 
2230                                 if (line[start_array[j-1]]) {
2231                                         const char *e;
2232 
2233                                         /* Upgrade final corner to the right with a branch to the right */
2234                                         e = startswith(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
2235                                         if (e) {
2236                                                 d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), e);
2237                                                 if (!d)
2238                                                         return log_oom();
2239                                         }
2240                                 }
2241 
2242                                 if (!d) {
2243                                         d = strdup(special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
2244                                         if (!d)
2245                                                 return log_oom();
2246                                 }
2247 
2248                         } else if (i == context->n_partitions - j) {
2249                                 _cleanup_free_ char *hint = NULL;
2250 
2251                                 (void) partition_hint(p, node, &hint);
2252 
2253                                 if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)))
2254                                         d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint));
2255                                 else
2256                                         d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_RIGHT), " ", strna(hint));
2257 
2258                                 if (!d)
2259                                         return log_oom();
2260                         }
2261 
2262                         if (d)
2263                                 free_and_replace(line[start_array[j-1]], d);
2264                 }
2265 
2266                 putc(' ', stdout);
2267 
2268                 j = 0;
2269                 while (j < c) {
2270                         if (line[j]) {
2271                                 fputs(line[j], stdout);
2272                                 j += utf8_console_width(line[j]);
2273                         } else {
2274                                 putc(' ', stdout);
2275                                 j++;
2276                         }
2277                 }
2278 
2279                 putc('\n', stdout);
2280 
2281                 for (j = 0; j < c; j++)
2282                         free(line[j]);
2283         }
2284 
2285         return 0;
2286 }
2287 
context_changed(const Context * context)2288 static bool context_changed(const Context *context) {
2289         assert(context);
2290 
2291         LIST_FOREACH(partitions, p, context->partitions) {
2292                 if (p->dropped)
2293                         continue;
2294 
2295                 if (p->allocated_to_area)
2296                         return true;
2297 
2298                 if (p->new_size != p->current_size)
2299                         return true;
2300         }
2301 
2302         return false;
2303 }
2304 
context_wipe_range(Context * context,uint64_t offset,uint64_t size)2305 static int context_wipe_range(Context *context, uint64_t offset, uint64_t size) {
2306         _cleanup_(blkid_free_probep) blkid_probe probe = NULL;
2307         int r;
2308 
2309         assert(context);
2310         assert(offset != UINT64_MAX);
2311         assert(size != UINT64_MAX);
2312 
2313         probe = blkid_new_probe();
2314         if (!probe)
2315                 return log_oom();
2316 
2317         errno = 0;
2318         r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size);
2319         if (r < 0)
2320                 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping.");
2321 
2322         errno = 0;
2323         if (blkid_probe_enable_superblocks(probe, true) < 0 ||
2324             blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 ||
2325             blkid_probe_enable_partitions(probe, true) < 0 ||
2326             blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0)
2327                 return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing.");
2328 
2329         for (;;) {
2330                 errno = 0;
2331                 r = blkid_do_probe(probe);
2332                 if (r < 0)
2333                         return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe for file systems.");
2334                 if (r > 0)
2335                         break;
2336 
2337                 errno = 0;
2338                 if (blkid_do_wipe(probe, false) < 0)
2339                         return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to wipe file system signature.");
2340         }
2341 
2342         return 0;
2343 }
2344 
context_wipe_partition(Context * context,Partition * p)2345 static int context_wipe_partition(Context *context, Partition *p) {
2346         int r;
2347 
2348         assert(context);
2349         assert(p);
2350         assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */
2351 
2352         assert(p->offset != UINT64_MAX);
2353         assert(p->new_size != UINT64_MAX);
2354 
2355         r = context_wipe_range(context, p->offset, p->new_size);
2356         if (r < 0)
2357                 return r;
2358 
2359         log_info("Successfully wiped file system signatures from future partition %" PRIu64 ".", p->partno);
2360         return 0;
2361 }
2362 
context_discard_range(Context * context,uint64_t offset,uint64_t size)2363 static int context_discard_range(
2364                 Context *context,
2365                 uint64_t offset,
2366                 uint64_t size) {
2367 
2368         struct stat st;
2369         int fd;
2370 
2371         assert(context);
2372         assert(offset != UINT64_MAX);
2373         assert(size != UINT64_MAX);
2374 
2375         if (size <= 0)
2376                 return 0;
2377 
2378         assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
2379 
2380         if (fstat(fd, &st) < 0)
2381                 return -errno;
2382 
2383         if (S_ISREG(st.st_mode)) {
2384                 if (fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, size) < 0) {
2385                         if (ERRNO_IS_NOT_SUPPORTED(errno))
2386                                 return -EOPNOTSUPP;
2387 
2388                         return -errno;
2389                 }
2390 
2391                 return 1;
2392         }
2393 
2394         if (S_ISBLK(st.st_mode)) {
2395                 uint64_t range[2], end;
2396 
2397                 range[0] = round_up_size(offset, context->sector_size);
2398 
2399                 if (offset > UINT64_MAX - size)
2400                         return -ERANGE;
2401 
2402                 end = offset + size;
2403                 if (end <= range[0])
2404                         return 0;
2405 
2406                 range[1] = round_down_size(end - range[0], context->sector_size);
2407                 if (range[1] <= 0)
2408                         return 0;
2409 
2410                 if (ioctl(fd, BLKDISCARD, range) < 0) {
2411                         if (ERRNO_IS_NOT_SUPPORTED(errno))
2412                                 return -EOPNOTSUPP;
2413 
2414                         return -errno;
2415                 }
2416 
2417                 return 1;
2418         }
2419 
2420         return -EOPNOTSUPP;
2421 }
2422 
context_discard_partition(Context * context,Partition * p)2423 static int context_discard_partition(Context *context, Partition *p) {
2424         int r;
2425 
2426         assert(context);
2427         assert(p);
2428 
2429         assert(p->offset != UINT64_MAX);
2430         assert(p->new_size != UINT64_MAX);
2431         assert(!PARTITION_EXISTS(p)); /* Safety check: never discard existing partitions */
2432 
2433         if (!arg_discard)
2434                 return 0;
2435 
2436         r = context_discard_range(context, p->offset, p->new_size);
2437         if (r == -EOPNOTSUPP) {
2438                 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno);
2439                 return 0;
2440         }
2441         if (r == -EBUSY) {
2442                 /* Let's handle this gracefully: https://bugzilla.kernel.org/show_bug.cgi?id=211167 */
2443                 log_info("Block device is busy, not discarding partition %" PRIu64 " because it probably is mounted.", p->partno);
2444                 return 0;
2445         }
2446         if (r == 0) {
2447                 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
2448                 return 0;
2449         }
2450         if (r < 0)
2451                 return log_error_errno(r, "Failed to discard data for future partition %" PRIu64 ".", p->partno);
2452 
2453         log_info("Successfully discarded data from future partition %" PRIu64 ".", p->partno);
2454         return 1;
2455 }
2456 
context_discard_gap_after(Context * context,Partition * p)2457 static int context_discard_gap_after(Context *context, Partition *p) {
2458         uint64_t gap, next = UINT64_MAX;
2459         int r;
2460 
2461         assert(context);
2462         assert(!p || (p->offset != UINT64_MAX && p->new_size != UINT64_MAX));
2463 
2464         if (p)
2465                 gap = p->offset + p->new_size;
2466         else
2467                 gap = context->start;
2468 
2469         LIST_FOREACH(partitions, q, context->partitions) {
2470                 if (q->dropped)
2471                         continue;
2472 
2473                 assert(q->offset != UINT64_MAX);
2474                 assert(q->new_size != UINT64_MAX);
2475 
2476                 if (q->offset < gap)
2477                         continue;
2478 
2479                 if (next == UINT64_MAX || q->offset < next)
2480                         next = q->offset;
2481         }
2482 
2483         if (next == UINT64_MAX) {
2484                 next = context->end;
2485                 if (gap > next)
2486                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
2487         }
2488 
2489         assert(next >= gap);
2490         r = context_discard_range(context, gap, next - gap);
2491         if (r == -EOPNOTSUPP) {
2492                 if (p)
2493                         log_info("Storage does not support discard, not discarding gap after partition %" PRIu64 ".", p->partno);
2494                 else
2495                         log_info("Storage does not support discard, not discarding gap at beginning of disk.");
2496                 return 0;
2497         }
2498         if (r == 0)  /* Too short */
2499                 return 0;
2500         if (r < 0) {
2501                 if (p)
2502                         return log_error_errno(r, "Failed to discard gap after partition %" PRIu64 ".", p->partno);
2503                 else
2504                         return log_error_errno(r, "Failed to discard gap at beginning of disk.");
2505         }
2506 
2507         if (p)
2508                 log_info("Successfully discarded gap after partition %" PRIu64 ".", p->partno);
2509         else
2510                 log_info("Successfully discarded gap at beginning of disk.");
2511 
2512         return 0;
2513 }
2514 
context_wipe_and_discard(Context * context,bool from_scratch)2515 static int context_wipe_and_discard(Context *context, bool from_scratch) {
2516         int r;
2517 
2518         assert(context);
2519 
2520         /* Wipe and discard the contents of all partitions we are about to create. We skip the discarding if
2521          * we were supposed to start from scratch anyway, as in that case we just discard the whole block
2522          * device in one go early on. */
2523 
2524         LIST_FOREACH(partitions, p, context->partitions) {
2525 
2526                 if (!p->allocated_to_area)
2527                         continue;
2528 
2529                 r = context_wipe_partition(context, p);
2530                 if (r < 0)
2531                         return r;
2532 
2533                 if (!from_scratch) {
2534                         r = context_discard_partition(context, p);
2535                         if (r < 0)
2536                                 return r;
2537 
2538                         r = context_discard_gap_after(context, p);
2539                         if (r < 0)
2540                                 return r;
2541                 }
2542         }
2543 
2544         if (!from_scratch) {
2545                 r = context_discard_gap_after(context, NULL);
2546                 if (r < 0)
2547                         return r;
2548         }
2549 
2550         return 0;
2551 }
2552 
partition_encrypt(Context * context,Partition * p,const char * node,struct crypt_device ** ret_cd,char ** ret_volume,int * ret_fd)2553 static int partition_encrypt(
2554                 Context *context,
2555                 Partition *p,
2556                 const char *node,
2557                 struct crypt_device **ret_cd,
2558                 char **ret_volume,
2559                 int *ret_fd) {
2560 #if HAVE_LIBCRYPTSETUP
2561         _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
2562         _cleanup_(erase_and_freep) void *volume_key = NULL;
2563         _cleanup_free_ char *dm_name = NULL, *vol = NULL;
2564         size_t volume_key_size = 256 / 8;
2565         sd_id128_t uuid;
2566         int r;
2567 
2568         assert(context);
2569         assert(p);
2570         assert(p->encrypt != ENCRYPT_OFF);
2571 
2572         log_debug("Encryption mode for partition %" PRIu64 ": %s", p->partno, encrypt_mode_to_string(p->encrypt));
2573 
2574         r = dlopen_cryptsetup();
2575         if (r < 0)
2576                 return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m");
2577 
2578         if (asprintf(&dm_name, "luks-repart-%08" PRIx64, random_u64()) < 0)
2579                 return log_oom();
2580 
2581         if (ret_volume) {
2582                 vol = path_join("/dev/mapper/", dm_name);
2583                 if (!vol)
2584                         return log_oom();
2585         }
2586 
2587         r = derive_uuid(p->new_uuid, "luks-uuid", &uuid);
2588         if (r < 0)
2589                 return r;
2590 
2591         log_info("Encrypting future partition %" PRIu64 "...", p->partno);
2592 
2593         volume_key = malloc(volume_key_size);
2594         if (!volume_key)
2595                 return log_oom();
2596 
2597         r = genuine_random_bytes(volume_key, volume_key_size, RANDOM_BLOCK);
2598         if (r < 0)
2599                 return log_error_errno(r, "Failed to generate volume key: %m");
2600 
2601         r = sym_crypt_init(&cd, node);
2602         if (r < 0)
2603                 return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
2604 
2605         cryptsetup_enable_logging(cd);
2606 
2607         r = sym_crypt_format(cd,
2608                          CRYPT_LUKS2,
2609                          "aes",
2610                          "xts-plain64",
2611                          SD_ID128_TO_UUID_STRING(uuid),
2612                          volume_key,
2613                          volume_key_size,
2614                          &(struct crypt_params_luks2) {
2615                                  .label = strempty(p->new_label),
2616                                  .sector_size = context->sector_size,
2617                          });
2618         if (r < 0)
2619                 return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
2620 
2621         if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
2622                 r = sym_crypt_keyslot_add_by_volume_key(
2623                                 cd,
2624                                 CRYPT_ANY_SLOT,
2625                                 volume_key,
2626                                 volume_key_size,
2627                                 strempty(arg_key),
2628                                 arg_key_size);
2629                 if (r < 0)
2630                         return log_error_errno(r, "Failed to add LUKS2 key: %m");
2631         }
2632 
2633         if (IN_SET(p->encrypt, ENCRYPT_TPM2, ENCRYPT_KEY_FILE_TPM2)) {
2634 #if HAVE_TPM2
2635                 _cleanup_(erase_and_freep) char *base64_encoded = NULL;
2636                 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
2637                 _cleanup_(erase_and_freep) void *secret = NULL;
2638                 _cleanup_free_ void *blob = NULL, *hash = NULL;
2639                 size_t secret_size, blob_size, hash_size;
2640                 uint16_t pcr_bank, primary_alg;
2641                 int keyslot;
2642 
2643                 r = tpm2_seal(arg_tpm2_device, arg_tpm2_pcr_mask, NULL, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg);
2644                 if (r < 0)
2645                         return log_error_errno(r, "Failed to seal to TPM2: %m");
2646 
2647                 r = base64mem(secret, secret_size, &base64_encoded);
2648                 if (r < 0)
2649                         return log_error_errno(r, "Failed to base64 encode secret key: %m");
2650 
2651                 r = cryptsetup_set_minimal_pbkdf(cd);
2652                 if (r < 0)
2653                         return log_error_errno(r, "Failed to set minimal PBKDF: %m");
2654 
2655                 keyslot = sym_crypt_keyslot_add_by_volume_key(
2656                                 cd,
2657                                 CRYPT_ANY_SLOT,
2658                                 volume_key,
2659                                 volume_key_size,
2660                                 base64_encoded,
2661                                 strlen(base64_encoded));
2662                 if (keyslot < 0)
2663                         return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node);
2664 
2665                 r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, 0, &v);
2666                 if (r < 0)
2667                         return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m");
2668 
2669                 r = cryptsetup_add_token_json(cd, v);
2670                 if (r < 0)
2671                         return log_error_errno(r, "Failed to add TPM2 JSON token to LUKS2 header: %m");
2672 #else
2673                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
2674                                        "Support for TPM2 enrollment not enabled.");
2675 #endif
2676         }
2677 
2678         r = sym_crypt_activate_by_volume_key(
2679                         cd,
2680                         dm_name,
2681                         volume_key,
2682                         volume_key_size,
2683                         arg_discard ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0);
2684         if (r < 0)
2685                 return log_error_errno(r, "Failed to activate LUKS superblock: %m");
2686 
2687         log_info("Successfully encrypted future partition %" PRIu64 ".", p->partno);
2688 
2689         if (ret_fd) {
2690                 _cleanup_close_ int dev_fd = -1;
2691 
2692                 dev_fd = open(vol, O_RDWR|O_CLOEXEC|O_NOCTTY);
2693                 if (dev_fd < 0)
2694                         return log_error_errno(errno, "Failed to open LUKS volume '%s': %m", vol);
2695 
2696                 *ret_fd = TAKE_FD(dev_fd);
2697         }
2698 
2699         if (ret_cd)
2700                 *ret_cd = TAKE_PTR(cd);
2701         if (ret_volume)
2702                 *ret_volume = TAKE_PTR(vol);
2703 
2704         return 0;
2705 #else
2706         return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libcryptsetup is not supported, cannot encrypt: %m");
2707 #endif
2708 }
2709 
deactivate_luks(struct crypt_device * cd,const char * node)2710 static int deactivate_luks(struct crypt_device *cd, const char *node) {
2711 #if HAVE_LIBCRYPTSETUP
2712         int r;
2713 
2714         if (!cd)
2715                 return 0;
2716 
2717         assert(node);
2718 
2719         /* udev or so might access out block device in the background while we are done. Let's hence force
2720          * detach the volume. We sync'ed before, hence this should be safe. */
2721 
2722         r = sym_crypt_deactivate_by_name(cd, basename(node), CRYPT_DEACTIVATE_FORCE);
2723         if (r < 0)
2724                 return log_error_errno(r, "Failed to deactivate LUKS device: %m");
2725 
2726         return 1;
2727 #else
2728         return 0;
2729 #endif
2730 }
2731 
context_copy_blocks(Context * context)2732 static int context_copy_blocks(Context *context) {
2733         int whole_fd = -1, r;
2734 
2735         assert(context);
2736 
2737         /* Copy in file systems on the block level */
2738 
2739         LIST_FOREACH(partitions, p, context->partitions) {
2740                 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
2741                 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
2742                 _cleanup_free_ char *encrypted = NULL;
2743                 _cleanup_close_ int encrypted_dev_fd = -1;
2744                 int target_fd;
2745 
2746                 if (p->copy_blocks_fd < 0)
2747                         continue;
2748 
2749                 if (p->dropped)
2750                         continue;
2751 
2752                 if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */
2753                         continue;
2754 
2755                 assert(p->new_size != UINT64_MAX);
2756                 assert(p->copy_blocks_size != UINT64_MAX);
2757                 assert(p->new_size >= p->copy_blocks_size);
2758 
2759                 if (whole_fd < 0)
2760                         assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
2761 
2762                 if (p->encrypt != ENCRYPT_OFF) {
2763                         r = loop_device_make(whole_fd, O_RDWR, p->offset, p->new_size, 0, &d);
2764                         if (r < 0)
2765                                 return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
2766 
2767                         r = loop_device_flock(d, LOCK_EX);
2768                         if (r < 0)
2769                                 return log_error_errno(r, "Failed to lock loopback device: %m");
2770 
2771                         r = partition_encrypt(context, p, d->node, &cd, &encrypted, &encrypted_dev_fd);
2772                         if (r < 0)
2773                                 return log_error_errno(r, "Failed to encrypt device: %m");
2774 
2775                         if (flock(encrypted_dev_fd, LOCK_EX) < 0)
2776                                 return log_error_errno(errno, "Failed to lock LUKS device: %m");
2777 
2778                         target_fd = encrypted_dev_fd;
2779                 }  else {
2780                         if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
2781                                 return log_error_errno(errno, "Failed to seek to partition offset: %m");
2782 
2783                         target_fd = whole_fd;
2784                 }
2785 
2786                 log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64 ".",
2787                          p->copy_blocks_path, FORMAT_BYTES(p->copy_blocks_size), p->partno);
2788 
2789                 r = copy_bytes_full(p->copy_blocks_fd, target_fd, p->copy_blocks_size, 0, NULL, NULL, NULL, NULL);
2790                 if (r < 0)
2791                         return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
2792 
2793                 if (fsync(target_fd) < 0)
2794                         return log_error_errno(errno, "Failed to synchronize copied data blocks: %m");
2795 
2796                 if (p->encrypt != ENCRYPT_OFF) {
2797                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
2798 
2799                         r = deactivate_luks(cd, encrypted);
2800                         if (r < 0)
2801                                 return r;
2802 
2803                         sym_crypt_free(cd);
2804                         cd = NULL;
2805 
2806                         r = loop_device_sync(d);
2807                         if (r < 0)
2808                                 return log_error_errno(r, "Failed to sync loopback device: %m");
2809                 }
2810 
2811                 log_info("Copying in of '%s' on block level completed.", p->copy_blocks_path);
2812         }
2813 
2814         return 0;
2815 }
2816 
do_copy_files(Partition * p,const char * fs)2817 static int do_copy_files(Partition *p, const char *fs) {
2818         int r;
2819 
2820         assert(p);
2821         assert(fs);
2822 
2823         STRV_FOREACH_PAIR(source, target, p->copy_files) {
2824                 _cleanup_close_ int sfd = -1, pfd = -1, tfd = -1;
2825 
2826                 sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT|CHASE_WARN, O_CLOEXEC|O_NOCTTY, NULL);
2827                 if (sfd < 0)
2828                         return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source);
2829 
2830                 r = fd_verify_regular(sfd);
2831                 if (r < 0) {
2832                         if (r != -EISDIR)
2833                                 return log_error_errno(r, "Failed to check type of source file '%s': %m", *source);
2834 
2835                         /* We are looking at a directory */
2836                         tfd = chase_symlinks_and_open(*target, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2837                         if (tfd < 0) {
2838                                 _cleanup_free_ char *dn = NULL, *fn = NULL;
2839 
2840                                 if (tfd != -ENOENT)
2841                                         return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
2842 
2843                                 r = path_extract_filename(*target, &fn);
2844                                 if (r < 0)
2845                                         return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
2846 
2847                                 r = path_extract_directory(*target, &dn);
2848                                 if (r < 0)
2849                                         return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
2850 
2851                                 r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
2852                                 if (r < 0)
2853                                         return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
2854 
2855                                 pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2856                                 if (pfd < 0)
2857                                         return log_error_errno(pfd, "Failed to open parent directory of target: %m");
2858 
2859                                 r = copy_tree_at(
2860                                                 sfd, ".",
2861                                                 pfd, fn,
2862                                                 UID_INVALID, GID_INVALID,
2863                                                 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS);
2864                         } else
2865                                 r = copy_tree_at(
2866                                                 sfd, ".",
2867                                                 tfd, ".",
2868                                                 UID_INVALID, GID_INVALID,
2869                                                 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS);
2870                         if (r < 0)
2871                                 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
2872                 } else {
2873                         _cleanup_free_ char *dn = NULL, *fn = NULL;
2874 
2875                         /* We are looking at a regular file */
2876 
2877                         r = path_extract_filename(*target, &fn);
2878                         if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
2879                                 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
2880                                                        "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
2881                         if (r < 0)
2882                                 return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
2883 
2884                         r = path_extract_directory(*target, &dn);
2885                         if (r < 0)
2886                                 return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
2887 
2888                         r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
2889                         if (r < 0)
2890                                 return log_error_errno(r, "Failed to create parent directory: %m");
2891 
2892                         pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
2893                         if (pfd < 0)
2894                                 return log_error_errno(pfd, "Failed to open parent directory of target: %m");
2895 
2896                         tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
2897                         if (tfd < 0)
2898                                 return log_error_errno(errno, "Failed to create target file '%s': %m", *target);
2899 
2900                         r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_SIGINT);
2901                         if (r < 0)
2902                                 return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
2903 
2904                         (void) copy_xattr(sfd, tfd, COPY_ALL_XATTRS);
2905                         (void) copy_access(sfd, tfd);
2906                         (void) copy_times(sfd, tfd, 0);
2907                 }
2908         }
2909 
2910         return 0;
2911 }
2912 
do_make_directories(Partition * p,const char * fs)2913 static int do_make_directories(Partition *p, const char *fs) {
2914         int r;
2915 
2916         assert(p);
2917         assert(fs);
2918 
2919         STRV_FOREACH(d, p->make_directories) {
2920 
2921                 r = mkdir_p_root(fs, *d, UID_INVALID, GID_INVALID, 0755);
2922                 if (r < 0)
2923                         return log_error_errno(r, "Failed to create directory '%s' in file system: %m", *d);
2924         }
2925 
2926         return 0;
2927 }
2928 
partition_populate(Partition * p,const char * node)2929 static int partition_populate(Partition *p, const char *node) {
2930         int r;
2931 
2932         assert(p);
2933         assert(node);
2934 
2935         if (strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
2936                 return 0;
2937 
2938         log_info("Populating partition %" PRIu64 " with files.", p->partno);
2939 
2940         /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to
2941          * appear in the host namespace. Hence we fork a child that has its own file system namespace and
2942          * detached mount propagation. */
2943 
2944         r = safe_fork("(sd-copy)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
2945         if (r < 0)
2946                 return r;
2947         if (r == 0) {
2948                 static const char fs[] = "/run/systemd/mount-root";
2949                 /* This is a child process with its own mount namespace and propagation to host turned off */
2950 
2951                 r = mkdir_p(fs, 0700);
2952                 if (r < 0) {
2953                         log_error_errno(r, "Failed to create mount point: %m");
2954                         _exit(EXIT_FAILURE);
2955                 }
2956 
2957                 if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0)
2958                         _exit(EXIT_FAILURE);
2959 
2960                 if (do_copy_files(p, fs) < 0)
2961                         _exit(EXIT_FAILURE);
2962 
2963                 if (do_make_directories(p, fs) < 0)
2964                         _exit(EXIT_FAILURE);
2965 
2966                 r = syncfs_path(AT_FDCWD, fs);
2967                 if (r < 0) {
2968                         log_error_errno(r, "Failed to synchronize written files: %m");
2969                         _exit(EXIT_FAILURE);
2970                 }
2971 
2972                 _exit(EXIT_SUCCESS);
2973         }
2974 
2975         log_info("Successfully populated partition %" PRIu64 " with files.", p->partno);
2976         return 0;
2977 }
2978 
context_mkfs(Context * context)2979 static int context_mkfs(Context *context) {
2980         int fd = -1, r;
2981 
2982         assert(context);
2983 
2984         /* Make a file system */
2985 
2986         LIST_FOREACH(partitions, p, context->partitions) {
2987                 _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
2988                 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
2989                 _cleanup_free_ char *encrypted = NULL;
2990                 _cleanup_close_ int encrypted_dev_fd = -1;
2991                 const char *fsdev;
2992                 sd_id128_t fs_uuid;
2993 
2994                 if (p->dropped)
2995                         continue;
2996 
2997                 if (PARTITION_EXISTS(p)) /* Never format existing partitions */
2998                         continue;
2999 
3000                 if (!p->format)
3001                         continue;
3002 
3003                 assert(p->offset != UINT64_MAX);
3004                 assert(p->new_size != UINT64_MAX);
3005 
3006                 if (fd < 0)
3007                         assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
3008 
3009                 /* Loopback block devices are not only useful to turn regular files into block devices, but
3010                  * also to cut out sections of block devices into new block devices. */
3011 
3012                 r = loop_device_make(fd, O_RDWR, p->offset, p->new_size, 0, &d);
3013                 if (r < 0)
3014                         return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno);
3015 
3016                 r = loop_device_flock(d, LOCK_EX);
3017                 if (r < 0)
3018                         return log_error_errno(r, "Failed to lock loopback device: %m");
3019 
3020                 if (p->encrypt != ENCRYPT_OFF) {
3021                         r = partition_encrypt(context, p, d->node, &cd, &encrypted, &encrypted_dev_fd);
3022                         if (r < 0)
3023                                 return log_error_errno(r, "Failed to encrypt device: %m");
3024 
3025                         if (flock(encrypted_dev_fd, LOCK_EX) < 0)
3026                                 return log_error_errno(errno, "Failed to lock LUKS device: %m");
3027 
3028                         fsdev = encrypted;
3029                 } else
3030                         fsdev = d->node;
3031 
3032                 log_info("Formatting future partition %" PRIu64 ".", p->partno);
3033 
3034                 /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid",
3035                  * keyed off the partition UUID. */
3036                 r = derive_uuid(p->new_uuid, "file-system-uuid", &fs_uuid);
3037                 if (r < 0)
3038                         return r;
3039 
3040                 r = make_filesystem(fsdev, p->format, strempty(p->new_label), fs_uuid, arg_discard);
3041                 if (r < 0) {
3042                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
3043                         (void) deactivate_luks(cd, encrypted);
3044                         return r;
3045                 }
3046 
3047                 log_info("Successfully formatted future partition %" PRIu64 ".", p->partno);
3048 
3049                 /* The file system is now created, no need to delay udev further */
3050                 if (p->encrypt != ENCRYPT_OFF)
3051                         if (flock(encrypted_dev_fd, LOCK_UN) < 0)
3052                                 return log_error_errno(errno, "Failed to unlock LUKS device: %m");
3053 
3054                 r = partition_populate(p, fsdev);
3055                 if (r < 0) {
3056                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
3057                         (void) deactivate_luks(cd, encrypted);
3058                         return r;
3059                 }
3060 
3061                 /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and
3062                  * if we don't sync before detaching a block device the in-flight sectors possibly won't hit
3063                  * the disk. */
3064 
3065                 if (p->encrypt != ENCRYPT_OFF) {
3066                         if (fsync(encrypted_dev_fd) < 0)
3067                                 return log_error_errno(errno, "Failed to synchronize LUKS volume: %m");
3068                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
3069 
3070                         r = deactivate_luks(cd, encrypted);
3071                         if (r < 0)
3072                                 return r;
3073 
3074                         sym_crypt_free(cd);
3075                         cd = NULL;
3076                 }
3077 
3078                 r = loop_device_sync(d);
3079                 if (r < 0)
3080                         return log_error_errno(r, "Failed to sync loopback device: %m");
3081         }
3082 
3083         return 0;
3084 }
3085 
partition_acquire_uuid(Context * context,Partition * p,sd_id128_t * ret)3086 static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) {
3087         struct {
3088                 sd_id128_t type_uuid;
3089                 uint64_t counter;
3090         } _packed_  plaintext = {};
3091         union {
3092                 uint8_t md[SHA256_DIGEST_SIZE];
3093                 sd_id128_t id;
3094         } result;
3095 
3096         uint64_t k = 0;
3097         int r;
3098 
3099         assert(context);
3100         assert(p);
3101         assert(ret);
3102 
3103         /* Calculate a good UUID for the indicated partition. We want a certain degree of reproducibility,
3104          * hence we won't generate the UUIDs randomly. Instead we use a cryptographic hash (precisely:
3105          * HMAC-SHA256) to derive them from a single seed. The seed is generally the machine ID of the
3106          * installation we are processing, but if random behaviour is desired can be random, too. We use the
3107          * seed value as key for the HMAC (since the machine ID is something we generally don't want to leak)
3108          * and the partition type as plaintext. The partition type is suffixed with a counter (only for the
3109          * second and later partition of the same type) if we have more than one partition of the same
3110          * time. Or in other words:
3111          *
3112          * With:
3113          *     SEED := /etc/machine-id
3114          *
3115          * If first partition instance of type TYPE_UUID:
3116          *     PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID)
3117          *
3118          * For all later partition instances of type TYPE_UUID with INSTANCE being the LE64 encoded instance number:
3119          *     PARTITION_UUID := HMAC-SHA256(SEED, TYPE_UUID || INSTANCE)
3120          */
3121 
3122         LIST_FOREACH(partitions, q, context->partitions) {
3123                 if (p == q)
3124                         break;
3125 
3126                 if (!sd_id128_equal(p->type_uuid, q->type_uuid))
3127                         continue;
3128 
3129                 k++;
3130         }
3131 
3132         plaintext.type_uuid = p->type_uuid;
3133         plaintext.counter = htole64(k);
3134 
3135         hmac_sha256(context->seed.bytes, sizeof(context->seed.bytes),
3136                     &plaintext,
3137                     k == 0 ? sizeof(sd_id128_t) : sizeof(plaintext),
3138                     result.md);
3139 
3140         /* Take the first half, mark it as v4 UUID */
3141         assert_cc(sizeof(result.md) == sizeof(result.id) * 2);
3142         result.id = id128_make_v4_uuid(result.id);
3143 
3144         /* Ensure this partition UUID is actually unique, and there's no remaining partition from an earlier run? */
3145         LIST_FOREACH(partitions, q, context->partitions) {
3146                 if (p == q)
3147                         continue;
3148 
3149                 if (sd_id128_in_set(result.id, q->current_uuid, q->new_uuid)) {
3150                         log_warning("Partition UUID calculated from seed for partition %" PRIu64 " already used, reverting to randomized UUID.", p->partno);
3151 
3152                         r = sd_id128_randomize(&result.id);
3153                         if (r < 0)
3154                                 return log_error_errno(r, "Failed to generate randomized UUID: %m");
3155 
3156                         break;
3157                 }
3158         }
3159 
3160         *ret = result.id;
3161         return 0;
3162 }
3163 
partition_acquire_label(Context * context,Partition * p,char ** ret)3164 static int partition_acquire_label(Context *context, Partition *p, char **ret) {
3165         _cleanup_free_ char *label = NULL;
3166         const char *prefix;
3167         unsigned k = 1;
3168 
3169         assert(context);
3170         assert(p);
3171         assert(ret);
3172 
3173         prefix = gpt_partition_type_uuid_to_string(p->type_uuid);
3174         if (!prefix)
3175                 prefix = "linux";
3176 
3177         for (;;) {
3178                 const char *ll = label ?: prefix;
3179                 bool retry = false;
3180 
3181                 LIST_FOREACH(partitions, q, context->partitions) {
3182                         if (p == q)
3183                                 break;
3184 
3185                         if (streq_ptr(ll, q->current_label) ||
3186                             streq_ptr(ll, q->new_label)) {
3187                                 retry = true;
3188                                 break;
3189                         }
3190                 }
3191 
3192                 if (!retry)
3193                         break;
3194 
3195                 label = mfree(label);
3196                 if (asprintf(&label, "%s-%u", prefix, ++k) < 0)
3197                         return log_oom();
3198         }
3199 
3200         if (!label) {
3201                 label = strdup(prefix);
3202                 if (!label)
3203                         return log_oom();
3204         }
3205 
3206         *ret = TAKE_PTR(label);
3207         return 0;
3208 }
3209 
context_acquire_partition_uuids_and_labels(Context * context)3210 static int context_acquire_partition_uuids_and_labels(Context *context) {
3211         int r;
3212 
3213         assert(context);
3214 
3215         LIST_FOREACH(partitions, p, context->partitions) {
3216                 /* Never touch foreign partitions */
3217                 if (PARTITION_IS_FOREIGN(p)) {
3218                         p->new_uuid = p->current_uuid;
3219 
3220                         if (p->current_label) {
3221                                 r = free_and_strdup_warn(&p->new_label, strempty(p->current_label));
3222                                 if (r < 0)
3223                                         return r;
3224                         }
3225 
3226                         continue;
3227                 }
3228 
3229                 if (!sd_id128_is_null(p->current_uuid))
3230                         p->new_uuid = p->current_uuid; /* Never change initialized UUIDs */
3231                 else if (sd_id128_is_null(p->new_uuid)) {
3232                         /* Not explicitly set by user! */
3233                         r = partition_acquire_uuid(context, p, &p->new_uuid);
3234                         if (r < 0)
3235                                 return r;
3236                 }
3237 
3238                 if (!isempty(p->current_label)) {
3239                         /* never change initialized labels */
3240                         r = free_and_strdup_warn(&p->new_label, p->current_label);
3241                         if (r < 0)
3242                                 return r;
3243                 } else if (!p->new_label) {
3244                         /* Not explicitly set by user! */
3245 
3246                         r = partition_acquire_label(context, p, &p->new_label);
3247                         if (r < 0)
3248                                 return r;
3249                 }
3250         }
3251 
3252         return 0;
3253 }
3254 
set_gpt_flags(struct fdisk_partition * q,uint64_t flags)3255 static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
3256         _cleanup_free_ char *a = NULL;
3257 
3258         for (unsigned i = 0; i < sizeof(flags) * 8; i++) {
3259                 uint64_t bit = UINT64_C(1) << i;
3260                 char buf[DECIMAL_STR_MAX(unsigned)+1];
3261 
3262                 if (!FLAGS_SET(flags, bit))
3263                         continue;
3264 
3265                 xsprintf(buf, "%u", i);
3266                 if (!strextend_with_separator(&a, ",", buf))
3267                         return -ENOMEM;
3268         }
3269 
3270         return fdisk_partition_set_attrs(q, a);
3271 }
3272 
partition_merge_flags(Partition * p)3273 static uint64_t partition_merge_flags(Partition *p) {
3274         uint64_t f;
3275 
3276         assert(p);
3277 
3278         f = p->gpt_flags;
3279 
3280         if (p->no_auto >= 0) {
3281                 if (gpt_partition_type_knows_no_auto(p->type_uuid))
3282                         SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
3283                 else {
3284                         char buffer[SD_ID128_UUID_STRING_MAX];
3285                         log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
3286                                     yes_no(p->no_auto),
3287                                     gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3288                 }
3289         }
3290 
3291         if (p->read_only >= 0) {
3292                 if (gpt_partition_type_knows_read_only(p->type_uuid))
3293                         SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
3294                 else {
3295                         char buffer[SD_ID128_UUID_STRING_MAX];
3296                         log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
3297                                     yes_no(p->read_only),
3298                                     gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3299                 }
3300         }
3301 
3302         if (p->growfs >= 0) {
3303                 if (gpt_partition_type_knows_growfs(p->type_uuid))
3304                         SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
3305                 else {
3306                         char buffer[SD_ID128_UUID_STRING_MAX];
3307                         log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
3308                                     yes_no(p->growfs),
3309                                     gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
3310                 }
3311         }
3312 
3313         return f;
3314 }
3315 
context_mangle_partitions(Context * context)3316 static int context_mangle_partitions(Context *context) {
3317         int r;
3318 
3319         assert(context);
3320 
3321         LIST_FOREACH(partitions, p, context->partitions) {
3322                 if (p->dropped)
3323                         continue;
3324 
3325                 assert(p->new_size != UINT64_MAX);
3326                 assert(p->offset != UINT64_MAX);
3327                 assert(p->partno != UINT64_MAX);
3328 
3329                 if (PARTITION_EXISTS(p)) {
3330                         bool changed = false;
3331 
3332                         assert(p->current_partition);
3333 
3334                         if (p->new_size != p->current_size) {
3335                                 assert(p->new_size >= p->current_size);
3336                                 assert(p->new_size % context->sector_size == 0);
3337 
3338                                 r = fdisk_partition_size_explicit(p->current_partition, true);
3339                                 if (r < 0)
3340                                         return log_error_errno(r, "Failed to enable explicit sizing: %m");
3341 
3342                                 r = fdisk_partition_set_size(p->current_partition, p->new_size / context->sector_size);
3343                                 if (r < 0)
3344                                         return log_error_errno(r, "Failed to grow partition: %m");
3345 
3346                                 log_info("Growing existing partition %" PRIu64 ".", p->partno);
3347                                 changed = true;
3348                         }
3349 
3350                         if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
3351                                 assert(!sd_id128_is_null(p->new_uuid));
3352 
3353                                 r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
3354                                 if (r < 0)
3355                                         return log_error_errno(r, "Failed to set partition UUID: %m");
3356 
3357                                 log_info("Initializing UUID of existing partition %" PRIu64 ".", p->partno);
3358                                 changed = true;
3359                         }
3360 
3361                         if (!streq_ptr(p->new_label, p->current_label)) {
3362                                 r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
3363                                 if (r < 0)
3364                                         return log_error_errno(r, "Failed to set partition label: %m");
3365 
3366                                 log_info("Setting partition label of existing partition %" PRIu64 ".", p->partno);
3367                                 changed = true;
3368                         }
3369 
3370                         if (changed) {
3371                                 assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
3372 
3373                                 r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
3374                                 if (r < 0)
3375                                         return log_error_errno(r, "Failed to update partition: %m");
3376                         }
3377                 } else {
3378                         _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *q = NULL;
3379                         _cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
3380 
3381                         assert(!p->new_partition);
3382                         assert(p->offset % context->sector_size == 0);
3383                         assert(p->new_size % context->sector_size == 0);
3384                         assert(!sd_id128_is_null(p->new_uuid));
3385                         assert(p->new_label);
3386 
3387                         t = fdisk_new_parttype();
3388                         if (!t)
3389                                 return log_oom();
3390 
3391                         r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid));
3392                         if (r < 0)
3393                                 return log_error_errno(r, "Failed to initialize partition type: %m");
3394 
3395                         q = fdisk_new_partition();
3396                         if (!q)
3397                                 return log_oom();
3398 
3399                         r = fdisk_partition_set_type(q, t);
3400                         if (r < 0)
3401                                 return log_error_errno(r, "Failed to set partition type: %m");
3402 
3403                         r = fdisk_partition_size_explicit(q, true);
3404                         if (r < 0)
3405                                 return log_error_errno(r, "Failed to enable explicit sizing: %m");
3406 
3407                         r = fdisk_partition_set_start(q, p->offset / context->sector_size);
3408                         if (r < 0)
3409                                 return log_error_errno(r, "Failed to position partition: %m");
3410 
3411                         r = fdisk_partition_set_size(q, p->new_size / context->sector_size);
3412                         if (r < 0)
3413                                 return log_error_errno(r, "Failed to grow partition: %m");
3414 
3415                         r = fdisk_partition_set_partno(q, p->partno);
3416                         if (r < 0)
3417                                 return log_error_errno(r, "Failed to set partition number: %m");
3418 
3419                         r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
3420                         if (r < 0)
3421                                 return log_error_errno(r, "Failed to set partition UUID: %m");
3422 
3423                         r = fdisk_partition_set_name(q, strempty(p->new_label));
3424                         if (r < 0)
3425                                 return log_error_errno(r, "Failed to set partition label: %m");
3426 
3427                         /* Merge the no auto + read only + growfs setting with the literal flags, and set them for the partition */
3428                         r = set_gpt_flags(q, partition_merge_flags(p));
3429                         if (r < 0)
3430                                 return log_error_errno(r, "Failed to set GPT partition flags: %m");
3431 
3432                         log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
3433 
3434                         r = fdisk_add_partition(context->fdisk_context, q, NULL);
3435                         if (r < 0)
3436                                 return log_error_errno(r, "Failed to add partition: %m");
3437 
3438                         assert(!p->new_partition);
3439                         p->new_partition = TAKE_PTR(q);
3440                 }
3441         }
3442 
3443         return 0;
3444 }
3445 
context_write_partition_table(Context * context,const char * node,bool from_scratch)3446 static int context_write_partition_table(
3447                 Context *context,
3448                 const char *node,
3449                 bool from_scratch) {
3450 
3451         _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
3452         int capable, r;
3453 
3454         assert(context);
3455 
3456         if (arg_pretty > 0 ||
3457             (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0) ||
3458             !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
3459 
3460                 (void) context_dump_partitions(context, node);
3461 
3462                 putc('\n', stdout);
3463 
3464                 if (arg_json_format_flags & JSON_FORMAT_OFF)
3465                         (void) context_dump_partition_bar(context, node);
3466                 putc('\n', stdout);
3467                 fflush(stdout);
3468         }
3469 
3470         if (!from_scratch && !context_changed(context)) {
3471                 log_info("No changes.");
3472                 return 0;
3473         }
3474 
3475         if (arg_dry_run) {
3476                 log_notice("Refusing to repartition, please re-run with --dry-run=no.");
3477                 return 0;
3478         }
3479 
3480         log_info("Applying changes.");
3481 
3482         if (from_scratch) {
3483                 r = context_wipe_range(context, 0, context->total);
3484                 if (r < 0)
3485                         return r;
3486 
3487                 log_info("Wiped block device.");
3488 
3489                 r = context_discard_range(context, 0, context->total);
3490                 if (r == -EOPNOTSUPP)
3491                         log_info("Storage does not support discard, not discarding entire block device data.");
3492                 else if (r < 0)
3493                         return log_error_errno(r, "Failed to discard entire block device: %m");
3494                 else if (r > 0)
3495                         log_info("Discarded entire block device.");
3496         }
3497 
3498         r = fdisk_get_partitions(context->fdisk_context, &original_table);
3499         if (r < 0)
3500                 return log_error_errno(r, "Failed to acquire partition table: %m");
3501 
3502         /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the
3503          * gaps between partitions, just to be sure. */
3504         r = context_wipe_and_discard(context, from_scratch);
3505         if (r < 0)
3506                 return r;
3507 
3508         r = context_copy_blocks(context);
3509         if (r < 0)
3510                 return r;
3511 
3512         r = context_mkfs(context);
3513         if (r < 0)
3514                 return r;
3515 
3516         r = context_mangle_partitions(context);
3517         if (r < 0)
3518                 return r;
3519 
3520         log_info("Writing new partition table.");
3521 
3522         r = fdisk_write_disklabel(context->fdisk_context);
3523         if (r < 0)
3524                 return log_error_errno(r, "Failed to write partition table: %m");
3525 
3526         capable = blockdev_partscan_enabled(fdisk_get_devfd(context->fdisk_context));
3527         if (capable == -ENOTBLK)
3528                 log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
3529         else if (capable < 0)
3530                 return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
3531         else if (capable > 0) {
3532                 log_info("Telling kernel to reread partition table.");
3533 
3534                 if (from_scratch)
3535                         r = fdisk_reread_partition_table(context->fdisk_context);
3536                 else
3537                         r = fdisk_reread_changes(context->fdisk_context, original_table);
3538                 if (r < 0)
3539                         return log_error_errno(r, "Failed to reread partition table: %m");
3540         } else
3541                 log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
3542 
3543         log_info("All done.");
3544 
3545         return 0;
3546 }
3547 
context_read_seed(Context * context,const char * root)3548 static int context_read_seed(Context *context, const char *root) {
3549         int r;
3550 
3551         assert(context);
3552 
3553         if (!sd_id128_is_null(context->seed))
3554                 return 0;
3555 
3556         if (!arg_randomize) {
3557                 _cleanup_close_ int fd = -1;
3558 
3559                 fd = chase_symlinks_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, NULL);
3560                 if (fd == -ENOENT)
3561                         log_info("No machine ID set, using randomized partition UUIDs.");
3562                 else if (fd < 0)
3563                         return log_error_errno(fd, "Failed to determine machine ID of image: %m");
3564                 else {
3565                         r = id128_read_fd(fd, ID128_PLAIN_OR_UNINIT, &context->seed);
3566                         if (r == -ENOMEDIUM)
3567                                 log_info("No machine ID set, using randomized partition UUIDs.");
3568                         else if (r < 0)
3569                                 return log_error_errno(r, "Failed to parse machine ID of image: %m");
3570 
3571                         return 0;
3572                 }
3573         }
3574 
3575         r = sd_id128_randomize(&context->seed);
3576         if (r < 0)
3577                 return log_error_errno(r, "Failed to generate randomized seed: %m");
3578 
3579         return 0;
3580 }
3581 
context_factory_reset(Context * context,bool from_scratch)3582 static int context_factory_reset(Context *context, bool from_scratch) {
3583         size_t n = 0;
3584         int r;
3585 
3586         assert(context);
3587 
3588         if (arg_factory_reset <= 0)
3589                 return 0;
3590 
3591         if (from_scratch) /* Nothing to reset if we start from scratch */
3592                 return 0;
3593 
3594         if (arg_dry_run) {
3595                 log_notice("Refusing to factory reset, please re-run with --dry-run=no.");
3596                 return 0;
3597         }
3598 
3599         log_info("Applying factory reset.");
3600 
3601         LIST_FOREACH(partitions, p, context->partitions) {
3602 
3603                 if (!p->factory_reset || !PARTITION_EXISTS(p))
3604                         continue;
3605 
3606                 assert(p->partno != UINT64_MAX);
3607 
3608                 log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
3609 
3610                 r = fdisk_delete_partition(context->fdisk_context, p->partno);
3611                 if (r < 0)
3612                         return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
3613 
3614                 n++;
3615         }
3616 
3617         if (n == 0) {
3618                 log_info("Factory reset requested, but no partitions to delete found.");
3619                 return 0;
3620         }
3621 
3622         r = fdisk_write_disklabel(context->fdisk_context);
3623         if (r < 0)
3624                 return log_error_errno(r, "Failed to write disk label: %m");
3625 
3626         log_info("Successfully deleted %zu partitions.", n);
3627         return 1;
3628 }
3629 
context_can_factory_reset(Context * context)3630 static int context_can_factory_reset(Context *context) {
3631         assert(context);
3632 
3633         LIST_FOREACH(partitions, p, context->partitions)
3634                 if (p->factory_reset && PARTITION_EXISTS(p))
3635                         return true;
3636 
3637         return false;
3638 }
3639 
resolve_copy_blocks_auto_candidate(dev_t partition_devno,sd_id128_t partition_type_uuid,dev_t restrict_devno,sd_id128_t * ret_uuid)3640 static int resolve_copy_blocks_auto_candidate(
3641                 dev_t partition_devno,
3642                 sd_id128_t partition_type_uuid,
3643                 dev_t restrict_devno,
3644                 sd_id128_t *ret_uuid) {
3645 
3646         _cleanup_(blkid_free_probep) blkid_probe b = NULL;
3647         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
3648         _cleanup_close_ int fd = -1;
3649         const char *pttype, *t, *p;
3650         sd_id128_t pt_parsed, u;
3651         blkid_partition pp;
3652         dev_t whole_devno;
3653         blkid_partlist pl;
3654         int r;
3655 
3656         /* Checks if the specified partition has the specified GPT type UUID, and is located on the specified
3657          * 'restrict_devno' device. The type check is particularly relevant if we have Verity volume which is
3658          * backed by two separate partitions: the data and the hash partitions, and we need to find the right
3659          * one of the two. */
3660 
3661         r = block_get_whole_disk(partition_devno, &whole_devno);
3662         if (r < 0)
3663                 return log_error_errno(
3664                                 r,
3665                                 "Unable to determine containing block device of partition %u:%u: %m",
3666                                 major(partition_devno), minor(partition_devno));
3667 
3668         if (restrict_devno != (dev_t) -1 &&
3669             restrict_devno != whole_devno)
3670                 return log_error_errno(
3671                                 SYNTHETIC_ERRNO(EPERM),
3672                                 "Partition %u:%u is located outside of block device %u:%u, refusing.",
3673                                 major(partition_devno), minor(partition_devno),
3674                                 major(restrict_devno), minor(restrict_devno));
3675 
3676         r = sd_device_new_from_devnum(&dev, 'b', whole_devno);
3677         if (r < 0)
3678                 return log_error_errno(r, "Failed to create sd-device for block device %u:%u: %m",
3679                                        major(whole_devno), minor(whole_devno));
3680 
3681         r = sd_device_get_devname(dev, &p);
3682         if (r < 0)
3683                 return log_error_errno(r, "Failed to get name of block device %u:%u: %m",
3684                                        major(whole_devno), minor(whole_devno));
3685 
3686         fd = sd_device_open(dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
3687         if (fd < 0)
3688                 return log_error_errno(fd, "Failed to open block device %s: %m", p);
3689 
3690         b = blkid_new_probe();
3691         if (!b)
3692                 return log_oom();
3693 
3694         errno = 0;
3695         r = blkid_probe_set_device(b, fd, 0, 0);
3696         if (r != 0)
3697                 return log_error_errno(errno_or_else(ENOMEM), "Failed to open block device '%s': %m", p);
3698 
3699         (void) blkid_probe_enable_partitions(b, 1);
3700         (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
3701 
3702         errno = 0;
3703         r = blkid_do_safeprobe(b);
3704         if (IN_SET(r, -2, 1)) { /* nothing found or ambiguous result */
3705                 log_debug("Didn't find partition table on block device '%s'.", p);
3706                 return false;
3707         }
3708         if (r != 0)
3709                 return log_error_errno(errno_or_else(EIO), "Unable to probe for partition table of '%s': %m", p);
3710 
3711         (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
3712         if (!streq_ptr(pttype, "gpt")) {
3713                 log_debug("Didn't find a GPT partition table on '%s'.", p);
3714                 return false;
3715         }
3716 
3717         errno = 0;
3718         pl = blkid_probe_get_partitions(b);
3719         if (!pl)
3720                 return log_error_errno(errno_or_else(EIO), "Unable read partition table of '%s': %m", p);
3721         errno = 0;
3722 
3723         pp = blkid_partlist_devno_to_partition(pl, partition_devno);
3724         if (!pp) {
3725                 log_debug("Partition %u:%u has no matching partition table entry on '%s'.",
3726                           major(partition_devno), minor(partition_devno), p);
3727                 return false;
3728         }
3729 
3730         t = blkid_partition_get_type_string(pp);
3731         if (isempty(t)) {
3732                 log_debug("Partition %u:%u has no type on '%s'.",
3733                           major(partition_devno), minor(partition_devno), p);
3734                 return false;
3735         }
3736 
3737         r = sd_id128_from_string(t, &pt_parsed);
3738         if (r < 0) {
3739                 log_debug_errno(r, "Failed to parse partition type \"%s\": %m", t);
3740                 return false;
3741         }
3742 
3743         if (!sd_id128_equal(pt_parsed, partition_type_uuid)) {
3744                 log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
3745                           major(partition_devno), minor(partition_devno),
3746                           SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type_uuid));
3747                 return false;
3748         }
3749 
3750         t = blkid_partition_get_uuid(pp);
3751         if (isempty(t)) {
3752                 log_debug("Partition %u:%u has no UUID.",
3753                           major(partition_devno), minor(partition_devno));
3754                 return false;
3755         }
3756 
3757         r = sd_id128_from_string(t, &u);
3758         if (r < 0) {
3759                 log_debug_errno(r, "Failed to parse partition UUID \"%s\": %m", t);
3760                 return false;
3761         }
3762 
3763         log_debug("Automatically found partition %u:%u of right type " SD_ID128_FORMAT_STR ".",
3764                   major(partition_devno), minor(partition_devno),
3765                   SD_ID128_FORMAT_VAL(pt_parsed));
3766 
3767         if (ret_uuid)
3768                 *ret_uuid = u;
3769 
3770         return true;
3771 }
3772 
find_backing_devno(const char * path,const char * root,dev_t * ret)3773 static int find_backing_devno(
3774                 const char *path,
3775                 const char *root,
3776                 dev_t *ret) {
3777 
3778         _cleanup_free_ char *resolved = NULL;
3779         int r;
3780 
3781         assert(path);
3782 
3783         r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &resolved, NULL);
3784         if (r < 0)
3785                 return r;
3786 
3787         r = path_is_mount_point(resolved, NULL, 0);
3788         if (r < 0)
3789                 return r;
3790         if (r == 0) /* Not a mount point, then it's not a partition of its own, let's not automatically use it. */
3791                 return -ENOENT;
3792 
3793         r = get_block_device(resolved, ret);
3794         if (r < 0)
3795                 return r;
3796         if (r == 0) /* Not backed by physical file system, we can't use this */
3797                 return -ENOENT;
3798 
3799         return 0;
3800 }
3801 
resolve_copy_blocks_auto(sd_id128_t type_uuid,const char * root,dev_t restrict_devno,dev_t * ret_devno,sd_id128_t * ret_uuid)3802 static int resolve_copy_blocks_auto(
3803                 sd_id128_t type_uuid,
3804                 const char *root,
3805                 dev_t restrict_devno,
3806                 dev_t *ret_devno,
3807                 sd_id128_t *ret_uuid) {
3808 
3809         const char *try1 = NULL, *try2 = NULL;
3810         char p[SYS_BLOCK_PATH_MAX("/slaves")];
3811         _cleanup_(closedirp) DIR *d = NULL;
3812         sd_id128_t found_uuid = SD_ID128_NULL;
3813         dev_t devno, found = 0;
3814         int r;
3815 
3816         /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
3817          * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
3818          * and restrict block device references in the --image= case to loopback block device we set up.
3819          *
3820          * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
3821          * thus declares which device (and its partition subdevices) we shall limit access to. If
3822          * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
3823          * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
3824 
3825         if (restrict_devno == 0)
3826                 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
3827                                        "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
3828 
3829         /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
3830          * partitions in the host, using the appropriate directory as key and ensuring that the partition
3831          * type matches. */
3832 
3833         if (gpt_partition_type_is_root(type_uuid))
3834                 try1 = "/";
3835         else if (gpt_partition_type_is_usr(type_uuid))
3836                 try1 = "/usr/";
3837         else if (gpt_partition_type_is_root_verity(type_uuid))
3838                 try1 = "/";
3839         else if (gpt_partition_type_is_usr_verity(type_uuid))
3840                 try1 = "/usr/";
3841         else if (sd_id128_equal(type_uuid, GPT_ESP)) {
3842                 try1 = "/efi/";
3843                 try2 = "/boot/";
3844         } else if (sd_id128_equal(type_uuid, GPT_XBOOTLDR))
3845                 try1 = "/boot/";
3846         else
3847                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
3848                                        "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
3849                                        SD_ID128_FORMAT_VAL(type_uuid));
3850 
3851         r = find_backing_devno(try1, root, &devno);
3852         if (r == -ENOENT && try2)
3853                 r = find_backing_devno(try2, root, &devno);
3854         if (r < 0)
3855                 return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
3856                                        SD_ID128_FORMAT_VAL(type_uuid));
3857 
3858         xsprintf_sys_block_path(p, "/slaves", devno);
3859         d = opendir(p);
3860         if (d) {
3861                 struct dirent *de;
3862 
3863                 for (;;) {
3864                         _cleanup_free_ char *q = NULL, *t = NULL;
3865                         sd_id128_t u;
3866                         dev_t sl;
3867 
3868                         errno = 0;
3869                         de = readdir_no_dot(d);
3870                         if (!de) {
3871                                 if (errno != 0)
3872                                         return log_error_errno(errno, "Failed to read directory '%s': %m", p);
3873 
3874                                 break;
3875                         }
3876 
3877                         if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
3878                                 continue;
3879 
3880                         q = path_join(p, de->d_name, "/dev");
3881                         if (!q)
3882                                 return log_oom();
3883 
3884                         r = read_one_line_file(q, &t);
3885                         if (r < 0)
3886                                 return log_error_errno(r, "Failed to read %s: %m", q);
3887 
3888                         r = parse_devnum(t, &sl);
3889                         if (r < 0) {
3890                                 log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
3891                                 continue;
3892                         }
3893                         if (major(sl) == 0) {
3894                                 log_debug_errno(r, "Device backing %s is special, ignoring: %m", q);
3895                                 continue;
3896                         }
3897 
3898                         r = resolve_copy_blocks_auto_candidate(sl, type_uuid, restrict_devno, &u);
3899                         if (r < 0)
3900                                 return r;
3901                         if (r > 0) {
3902                                 /* We found a matching one! */
3903                                 if (found != 0)
3904                                         return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
3905                                                                "Multiple matching partitions found, refusing.");
3906 
3907                                 found = sl;
3908                                 found_uuid = u;
3909                         }
3910                 }
3911         } else if (errno != ENOENT)
3912                 return log_error_errno(errno, "Failed open %s: %m", p);
3913         else {
3914                 r = resolve_copy_blocks_auto_candidate(devno, type_uuid, restrict_devno, &found_uuid);
3915                 if (r < 0)
3916                         return r;
3917                 if (r > 0)
3918                         found = devno;
3919         }
3920 
3921         if (found == 0)
3922                 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
3923                                        "Unable to automatically discover suitable partition to copy blocks from.");
3924 
3925         if (ret_devno)
3926                 *ret_devno = found;
3927 
3928         if (ret_uuid)
3929                 *ret_uuid = found_uuid;
3930 
3931         return 0;
3932 }
3933 
context_open_copy_block_paths(Context * context,const char * root,dev_t restrict_devno)3934 static int context_open_copy_block_paths(
3935                 Context *context,
3936                 const char *root,
3937                 dev_t restrict_devno) {
3938 
3939         int r;
3940 
3941         assert(context);
3942 
3943         LIST_FOREACH(partitions, p, context->partitions) {
3944                 _cleanup_close_ int source_fd = -1;
3945                 _cleanup_free_ char *opened = NULL;
3946                 sd_id128_t uuid = SD_ID128_NULL;
3947                 uint64_t size;
3948                 struct stat st;
3949 
3950                 assert(p->copy_blocks_fd < 0);
3951                 assert(p->copy_blocks_size == UINT64_MAX);
3952 
3953                 if (PARTITION_EXISTS(p)) /* Never copy over partitions that already exist! */
3954                         continue;
3955 
3956                 if (p->copy_blocks_path) {
3957 
3958                         source_fd = chase_symlinks_and_open(p->copy_blocks_path, root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
3959                         if (source_fd < 0)
3960                                 return log_error_errno(source_fd, "Failed to open '%s': %m", p->copy_blocks_path);
3961 
3962                         if (fstat(source_fd, &st) < 0)
3963                                 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
3964 
3965                         if (!S_ISREG(st.st_mode) && restrict_devno != (dev_t) -1)
3966                                 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
3967                                                        "Copying from block device node is not permitted in --image=/--root= mode, refusing.");
3968 
3969                 } else if (p->copy_blocks_auto) {
3970                         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
3971                         const char *devname;
3972                         dev_t devno;
3973 
3974                         r = resolve_copy_blocks_auto(p->type_uuid, root, restrict_devno, &devno, &uuid);
3975                         if (r < 0)
3976                                 return r;
3977 
3978                         r = sd_device_new_from_devnum(&dev, 'b', devno);
3979                         if (r < 0)
3980                                 return log_error_errno(r, "Failed to create sd-device object for device %u:%u: %m", major(devno), minor(devno));
3981 
3982                         r = sd_device_get_devname(dev, &devname);
3983                         if (r < 0)
3984                                 return log_error_errno(r, "Failed to get device name of %u:%u: %m", major(devno), minor(devno));
3985 
3986                         opened = strdup(devname);
3987                         if (!opened)
3988                                 return log_oom();
3989 
3990                         source_fd = sd_device_open(dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
3991                         if (source_fd < 0)
3992                                 return log_error_errno(source_fd, "Failed to open automatically determined source block copy device '%s': %m", opened);
3993 
3994                         if (fstat(source_fd, &st) < 0)
3995                                 return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
3996                 } else
3997                         continue;
3998 
3999                 if (S_ISDIR(st.st_mode)) {
4000                         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
4001                         const char *bdev;
4002 
4003                         /* If the file is a directory, automatically find the backing block device */
4004 
4005                         if (major(st.st_dev) != 0)
4006                                 r = sd_device_new_from_devnum(&dev, 'b', st.st_dev);
4007                         else {
4008                                 dev_t devt;
4009 
4010                                 /* Special support for btrfs */
4011 
4012                                 r = btrfs_get_block_device_fd(source_fd, &devt);
4013                                 if (r == -EUCLEAN)
4014                                         return btrfs_log_dev_root(LOG_ERR, r, opened);
4015                                 if (r < 0)
4016                                         return log_error_errno(r, "Unable to determine backing block device of '%s': %m", opened);
4017 
4018                                 r = sd_device_new_from_devnum(&dev, 'b', devt);
4019                         }
4020                         if (r < 0)
4021                                 return log_error_errno(r, "Failed to create sd-device object for block device backing '%s': %m", opened);
4022 
4023                         r = sd_device_get_devpath(dev, &bdev);
4024                         if (r < 0)
4025                                 return log_error_errno(r, "Failed to get device name for block device backing '%s': %m", opened);
4026 
4027                         safe_close(source_fd);
4028 
4029                         source_fd = sd_device_open(dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
4030                         if (source_fd < 0)
4031                                 return log_error_errno(source_fd, "Failed to open block device '%s': %m", bdev);
4032 
4033                         if (fstat(source_fd, &st) < 0)
4034                                 return log_error_errno(errno, "Failed to stat block device '%s': %m", bdev);
4035                 }
4036 
4037                 if (S_ISREG(st.st_mode))
4038                         size = st.st_size;
4039                 else if (S_ISBLK(st.st_mode)) {
4040                         if (ioctl(source_fd, BLKGETSIZE64, &size) != 0)
4041                                 return log_error_errno(errno, "Failed to determine size of block device to copy from: %m");
4042                 } else
4043                         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);
4044 
4045                 if (size <= 0)
4046                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
4047                 if (size % 512 != 0)
4048                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
4049 
4050                 p->copy_blocks_fd = TAKE_FD(source_fd);
4051                 p->copy_blocks_size = size;
4052 
4053                 free_and_replace(p->copy_blocks_path, opened);
4054 
4055                 /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
4056                 if (sd_id128_is_null(p->new_uuid) && !sd_id128_is_null(uuid))
4057                         p->new_uuid = uuid;
4058         }
4059 
4060         return 0;
4061 }
4062 
help(void)4063 static int help(void) {
4064         _cleanup_free_ char *link = NULL;
4065         int r;
4066 
4067         r = terminal_urlify_man("systemd-repart", "1", &link);
4068         if (r < 0)
4069                 return log_oom();
4070 
4071         printf("%s [OPTIONS...] [DEVICE]\n"
4072                "\n%sGrow and add partitions to partition table.%s\n\n"
4073                "  -h --help               Show this help\n"
4074                "     --version            Show package version\n"
4075                "     --no-pager           Do not pipe output into a pager\n"
4076                "     --no-legend          Do not show the headers and footers\n"
4077                "     --dry-run=BOOL       Whether to run dry-run operation\n"
4078                "     --empty=MODE         One of refuse, allow, require, force, create; controls\n"
4079                "                          how to handle empty disks lacking partition tables\n"
4080                "     --discard=BOOL       Whether to discard backing blocks for new partitions\n"
4081                "     --pretty=BOOL        Whether to show pretty summary before doing changes\n"
4082                "     --factory-reset=BOOL Whether to remove data partitions before recreating\n"
4083                "                          them\n"
4084                "     --can-factory-reset  Test whether factory reset is defined\n"
4085                "     --root=PATH          Operate relative to root path\n"
4086                "     --image=PATH         Operate relative to image file\n"
4087                "     --definitions=DIR    Find partition definitions in specified directory\n"
4088                "     --key-file=PATH      Key to use when encrypting partitions\n"
4089                "     --tpm2-device=PATH   Path to TPM2 device node to use\n"
4090                "     --tpm2-pcrs=PCR1+PCR2+PCR3+…\n"
4091                "                          TPM2 PCR indexes to use for TPM2 enrollment\n"
4092                "     --seed=UUID          128bit seed UUID to derive all UUIDs from\n"
4093                "     --size=BYTES         Grow loopback file to specified size\n"
4094                "     --json=pretty|short|off\n"
4095                "                          Generate JSON output\n"
4096                "\nSee the %s for details.\n",
4097                program_invocation_short_name,
4098                ansi_highlight(),
4099                ansi_normal(),
4100                link);
4101 
4102         return 0;
4103 }
4104 
parse_argv(int argc,char * argv[])4105 static int parse_argv(int argc, char *argv[]) {
4106 
4107         enum {
4108                 ARG_VERSION = 0x100,
4109                 ARG_NO_PAGER,
4110                 ARG_NO_LEGEND,
4111                 ARG_DRY_RUN,
4112                 ARG_EMPTY,
4113                 ARG_DISCARD,
4114                 ARG_FACTORY_RESET,
4115                 ARG_CAN_FACTORY_RESET,
4116                 ARG_ROOT,
4117                 ARG_IMAGE,
4118                 ARG_SEED,
4119                 ARG_PRETTY,
4120                 ARG_DEFINITIONS,
4121                 ARG_SIZE,
4122                 ARG_JSON,
4123                 ARG_KEY_FILE,
4124                 ARG_TPM2_DEVICE,
4125                 ARG_TPM2_PCRS,
4126         };
4127 
4128         static const struct option options[] = {
4129                 { "help",              no_argument,       NULL, 'h'                   },
4130                 { "version",           no_argument,       NULL, ARG_VERSION           },
4131                 { "no-pager",          no_argument,       NULL, ARG_NO_PAGER          },
4132                 { "no-legend",         no_argument,       NULL, ARG_NO_LEGEND         },
4133                 { "dry-run",           required_argument, NULL, ARG_DRY_RUN           },
4134                 { "empty",             required_argument, NULL, ARG_EMPTY             },
4135                 { "discard",           required_argument, NULL, ARG_DISCARD           },
4136                 { "factory-reset",     required_argument, NULL, ARG_FACTORY_RESET     },
4137                 { "can-factory-reset", no_argument,       NULL, ARG_CAN_FACTORY_RESET },
4138                 { "root",              required_argument, NULL, ARG_ROOT              },
4139                 { "image",             required_argument, NULL, ARG_IMAGE             },
4140                 { "seed",              required_argument, NULL, ARG_SEED              },
4141                 { "pretty",            required_argument, NULL, ARG_PRETTY            },
4142                 { "definitions",       required_argument, NULL, ARG_DEFINITIONS       },
4143                 { "size",              required_argument, NULL, ARG_SIZE              },
4144                 { "json",              required_argument, NULL, ARG_JSON              },
4145                 { "key-file",          required_argument, NULL, ARG_KEY_FILE          },
4146                 { "tpm2-device",       required_argument, NULL, ARG_TPM2_DEVICE       },
4147                 { "tpm2-pcrs",         required_argument, NULL, ARG_TPM2_PCRS         },
4148                 {}
4149         };
4150 
4151         int c, r, dry_run = -1;
4152 
4153         assert(argc >= 0);
4154         assert(argv);
4155 
4156         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
4157 
4158                 switch (c) {
4159 
4160                 case 'h':
4161                         return help();
4162 
4163                 case ARG_VERSION:
4164                         return version();
4165 
4166                 case ARG_NO_PAGER:
4167                         arg_pager_flags |= PAGER_DISABLE;
4168                         break;
4169 
4170                 case ARG_NO_LEGEND:
4171                         arg_legend = false;
4172                         break;
4173 
4174                 case ARG_DRY_RUN:
4175                         r = parse_boolean_argument("--dry-run=", optarg, &arg_dry_run);
4176                         if (r < 0)
4177                                 return r;
4178                         break;
4179 
4180                 case ARG_EMPTY:
4181                         if (isempty(optarg) || streq(optarg, "refuse"))
4182                                 arg_empty = EMPTY_REFUSE;
4183                         else if (streq(optarg, "allow"))
4184                                 arg_empty = EMPTY_ALLOW;
4185                         else if (streq(optarg, "require"))
4186                                 arg_empty = EMPTY_REQUIRE;
4187                         else if (streq(optarg, "force"))
4188                                 arg_empty = EMPTY_FORCE;
4189                         else if (streq(optarg, "create")) {
4190                                 arg_empty = EMPTY_CREATE;
4191 
4192                                 if (dry_run < 0)
4193                                         dry_run = false; /* Imply --dry-run=no if we create the loopback file
4194                                                           * anew. After all we cannot really break anyone's
4195                                                           * partition tables that way. */
4196                         } else
4197                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4198                                                        "Failed to parse --empty= parameter: %s", optarg);
4199                         break;
4200 
4201                 case ARG_DISCARD:
4202                         r = parse_boolean_argument("--discard=", optarg, &arg_discard);
4203                         if (r < 0)
4204                                 return r;
4205                         break;
4206 
4207                 case ARG_FACTORY_RESET:
4208                         r = parse_boolean_argument("--factory-reset=", optarg, NULL);
4209                         if (r < 0)
4210                                 return r;
4211                         arg_factory_reset = r;
4212                         break;
4213 
4214                 case ARG_CAN_FACTORY_RESET:
4215                         arg_can_factory_reset = true;
4216                         break;
4217 
4218                 case ARG_ROOT:
4219                         r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
4220                         if (r < 0)
4221                                 return r;
4222                         break;
4223 
4224                 case ARG_IMAGE:
4225                         r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
4226                         if (r < 0)
4227                                 return r;
4228                         break;
4229 
4230                 case ARG_SEED:
4231                         if (isempty(optarg)) {
4232                                 arg_seed = SD_ID128_NULL;
4233                                 arg_randomize = false;
4234                         } else if (streq(optarg, "random"))
4235                                 arg_randomize = true;
4236                         else {
4237                                 r = sd_id128_from_string(optarg, &arg_seed);
4238                                 if (r < 0)
4239                                         return log_error_errno(r, "Failed to parse seed: %s", optarg);
4240 
4241                                 arg_randomize = false;
4242                         }
4243 
4244                         break;
4245 
4246                 case ARG_PRETTY:
4247                         r = parse_boolean_argument("--pretty=", optarg, NULL);
4248                         if (r < 0)
4249                                 return r;
4250                         arg_pretty = r;
4251                         break;
4252 
4253                 case ARG_DEFINITIONS:
4254                         r = parse_path_argument(optarg, false, &arg_definitions);
4255                         if (r < 0)
4256                                 return r;
4257                         break;
4258 
4259                 case ARG_SIZE: {
4260                         uint64_t parsed, rounded;
4261 
4262                         if (streq(optarg, "auto")) {
4263                                 arg_size = UINT64_MAX;
4264                                 arg_size_auto = true;
4265                                 break;
4266                         }
4267 
4268                         r = parse_size(optarg, 1024, &parsed);
4269                         if (r < 0)
4270                                 return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg);
4271 
4272                         rounded = round_up_size(parsed, 4096);
4273                         if (rounded == 0)
4274                                 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too small, refusing.");
4275                         if (rounded == UINT64_MAX)
4276                                 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Specified image size too large, refusing.");
4277 
4278                         if (rounded != parsed)
4279                                 log_warning("Specified size is not a multiple of 4096, rounding up automatically. (%" PRIu64 " → %" PRIu64 ")",
4280                                             parsed, rounded);
4281 
4282                         arg_size = rounded;
4283                         arg_size_auto = false;
4284                         break;
4285                 }
4286 
4287                 case ARG_JSON:
4288                         r = parse_json_argument(optarg, &arg_json_format_flags);
4289                         if (r <= 0)
4290                                 return r;
4291 
4292                         break;
4293 
4294                 case ARG_KEY_FILE: {
4295                         _cleanup_(erase_and_freep) char *k = NULL;
4296                         size_t n = 0;
4297 
4298                         r = read_full_file_full(
4299                                         AT_FDCWD, optarg, UINT64_MAX, SIZE_MAX,
4300                                         READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
4301                                         NULL,
4302                                         &k, &n);
4303                         if (r < 0)
4304                                 return log_error_errno(r, "Failed to read key file '%s': %m", optarg);
4305 
4306                         erase_and_free(arg_key);
4307                         arg_key = TAKE_PTR(k);
4308                         arg_key_size = n;
4309                         break;
4310                 }
4311 
4312                 case ARG_TPM2_DEVICE: {
4313                         _cleanup_free_ char *device = NULL;
4314 
4315                         if (streq(optarg, "list"))
4316                                 return tpm2_list_devices();
4317 
4318                         if (!streq(optarg, "auto")) {
4319                                 device = strdup(optarg);
4320                                 if (!device)
4321                                         return log_oom();
4322                         }
4323 
4324                         free(arg_tpm2_device);
4325                         arg_tpm2_device = TAKE_PTR(device);
4326                         break;
4327                 }
4328 
4329                 case ARG_TPM2_PCRS: {
4330                         uint32_t mask;
4331 
4332                         if (isempty(optarg)) {
4333                                 arg_tpm2_pcr_mask = 0;
4334                                 break;
4335                         }
4336 
4337                         r = tpm2_parse_pcrs(optarg, &mask);
4338                         if (r < 0)
4339                                 return r;
4340 
4341                         if (arg_tpm2_pcr_mask == UINT32_MAX)
4342                                 arg_tpm2_pcr_mask = mask;
4343                         else
4344                                 arg_tpm2_pcr_mask |= mask;
4345 
4346                         break;
4347                 }
4348 
4349                 case '?':
4350                         return -EINVAL;
4351 
4352                 default:
4353                         assert_not_reached();
4354                 }
4355 
4356         if (argc - optind > 1)
4357                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4358                                        "Expected at most one argument, the path to the block device.");
4359 
4360         if (arg_factory_reset > 0 && IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE))
4361                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4362                                        "Combination of --factory-reset=yes and --empty=force/--empty=require/--empty=create is invalid.");
4363 
4364         if (arg_can_factory_reset)
4365                 arg_dry_run = true; /* When --can-factory-reset is specified we don't make changes, hence
4366                                      * non-dry-run mode makes no sense. Thus, imply dry run mode so that we
4367                                      * open things strictly read-only. */
4368         else if (dry_run >= 0)
4369                 arg_dry_run = dry_run;
4370 
4371         if (arg_empty == EMPTY_CREATE && (arg_size == UINT64_MAX && !arg_size_auto))
4372                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4373                                        "If --empty=create is specified, --size= must be specified, too.");
4374 
4375         if (arg_image && arg_root)
4376                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
4377         else if (!arg_image && !arg_root && in_initrd()) {
4378 
4379                 /* By default operate on /sysusr/ or /sysroot/ when invoked in the initrd. We prefer the
4380                  * former, if it is mounted, so that we have deterministic behaviour on systems where /usr/
4381                  * is vendor-supplied but the root fs formatted on first boot. */
4382                 r = path_is_mount_point("/sysusr/usr", NULL, 0);
4383                 if (r <= 0) {
4384                         if (r < 0 && r != -ENOENT)
4385                                 log_debug_errno(r, "Unable to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
4386 
4387                         arg_root = strdup("/sysroot");
4388                 } else
4389                         arg_root = strdup("/sysusr");
4390                 if (!arg_root)
4391                         return log_oom();
4392         }
4393 
4394         arg_node = argc > optind ? argv[optind] : NULL;
4395 
4396         if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node && !arg_image)
4397                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4398                                        "A path to a device node or loopback file must be specified when --empty=force, --empty=require or --empty=create are used.");
4399 
4400         if (arg_tpm2_pcr_mask == UINT32_MAX)
4401                 arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT;
4402 
4403         return 1;
4404 }
4405 
parse_proc_cmdline_factory_reset(void)4406 static int parse_proc_cmdline_factory_reset(void) {
4407         bool b;
4408         int r;
4409 
4410         if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
4411                 return 0;
4412 
4413         if (!in_initrd()) /* Never honour kernel command line factory reset request outside of the initrd */
4414                 return 0;
4415 
4416         r = proc_cmdline_get_bool("systemd.factory_reset", &b);
4417         if (r < 0)
4418                 return log_error_errno(r, "Failed to parse systemd.factory_reset kernel command line argument: %m");
4419         if (r > 0) {
4420                 arg_factory_reset = b;
4421 
4422                 if (b)
4423                         log_notice("Honouring factory reset requested via kernel command line.");
4424         }
4425 
4426         return 0;
4427 }
4428 
parse_efi_variable_factory_reset(void)4429 static int parse_efi_variable_factory_reset(void) {
4430         _cleanup_free_ char *value = NULL;
4431         int r;
4432 
4433         if (arg_factory_reset >= 0) /* Never override what is specified on the process command line */
4434                 return 0;
4435 
4436         if (!in_initrd()) /* Never honour EFI variable factory reset request outside of the initrd */
4437                 return 0;
4438 
4439         r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(FactoryReset), &value);
4440         if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
4441                 return 0;
4442         if (r < 0)
4443                 return log_error_errno(r, "Failed to read EFI variable FactoryReset: %m");
4444 
4445         r = parse_boolean(value);
4446         if (r < 0)
4447                 return log_error_errno(r, "Failed to parse EFI variable FactoryReset: %m");
4448 
4449         arg_factory_reset = r;
4450         if (r)
4451                 log_notice("Factory reset requested via EFI variable FactoryReset.");
4452 
4453         return 0;
4454 }
4455 
remove_efi_variable_factory_reset(void)4456 static int remove_efi_variable_factory_reset(void) {
4457         int r;
4458 
4459         r = efi_set_variable(EFI_SYSTEMD_VARIABLE(FactoryReset), NULL, 0);
4460         if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
4461                 return 0;
4462         if (r < 0)
4463                 return log_error_errno(r, "Failed to remove EFI variable FactoryReset: %m");
4464 
4465         log_info("Successfully unset EFI variable FactoryReset.");
4466         return 0;
4467 }
4468 
acquire_root_devno(const char * p,const char * root,int mode,char ** ret,int * ret_fd)4469 static int acquire_root_devno(
4470                 const char *p,
4471                 const char *root,
4472                 int mode,
4473                 char **ret,
4474                 int *ret_fd) {
4475 
4476         _cleanup_free_ char *found_path = NULL;
4477         dev_t devno, fd_devno = MODE_INVALID;
4478         _cleanup_close_ int fd = -1;
4479         struct stat st;
4480         int r;
4481 
4482         assert(p);
4483         assert(ret);
4484         assert(ret_fd);
4485 
4486         fd = chase_symlinks_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
4487         if (fd < 0)
4488                 return fd;
4489 
4490         if (fstat(fd, &st) < 0)
4491                 return -errno;
4492 
4493         if (S_ISREG(st.st_mode)) {
4494                 *ret = TAKE_PTR(found_path);
4495                 *ret_fd = TAKE_FD(fd);
4496                 return 0;
4497         }
4498 
4499         if (S_ISBLK(st.st_mode)) {
4500                 /* Refuse referencing explicit block devices if a root dir is specified, after all we should
4501                  * not be able to leave the image the root path constrains us to. */
4502                 if (root)
4503                         return -EPERM;
4504 
4505                 fd_devno = devno = st.st_rdev;
4506         } else if (S_ISDIR(st.st_mode)) {
4507 
4508                 devno = st.st_dev;
4509                 if (major(devno) == 0) {
4510                         r = btrfs_get_block_device_fd(fd, &devno);
4511                         if (r == -ENOTTY) /* not btrfs */
4512                                 return -ENODEV;
4513                         if (r < 0)
4514                                 return r;
4515                 }
4516         } else
4517                 return -ENOTBLK;
4518 
4519         /* From dm-crypt to backing partition */
4520         r = block_get_originating(devno, &devno);
4521         if (r == -ENOENT)
4522                 log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
4523         else if (r < 0)
4524                 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
4525 
4526         /* From partition to whole disk containing it */
4527         r = block_get_whole_disk(devno, &devno);
4528         if (r < 0)
4529                 log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
4530 
4531         r = device_path_make_canonical(S_IFBLK, devno, ret);
4532         if (r < 0)
4533                 return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
4534 
4535         /* Only if we still look at the same block device we can reuse the fd. Otherwise return an
4536          * invalidated fd. */
4537         *ret_fd = fd_devno != MODE_INVALID && fd_devno == devno ? TAKE_FD(fd) : -1;
4538         return 0;
4539 }
4540 
find_root(char ** ret,int * ret_fd)4541 static int find_root(char **ret, int *ret_fd) {
4542         _cleanup_free_ char *device = NULL;
4543         int r;
4544 
4545         assert(ret);
4546         assert(ret_fd);
4547 
4548         if (arg_node) {
4549                 if (arg_empty == EMPTY_CREATE) {
4550                         _cleanup_close_ int fd = -1;
4551                         _cleanup_free_ char *s = NULL;
4552 
4553                         s = strdup(arg_node);
4554                         if (!s)
4555                                 return log_oom();
4556 
4557                         fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
4558                         if (fd < 0)
4559                                 return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
4560 
4561                         *ret = TAKE_PTR(s);
4562                         *ret_fd = TAKE_FD(fd);
4563                         return 0;
4564                 }
4565 
4566                 /* Note that we don't specify a root argument here: if the user explicitly configured a node
4567                  * we'll take it relative to the host, not the image */
4568                 r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
4569                 if (r == -EUCLEAN)
4570                         return btrfs_log_dev_root(LOG_ERR, r, arg_node);
4571                 if (r < 0)
4572                         return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node);
4573 
4574                 return 0;
4575         }
4576 
4577         assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
4578 
4579         /* If the root mount has been replaced by some form of volatile file system (overlayfs), the
4580          * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
4581          * here. */
4582         r = readlink_malloc("/run/systemd/volatile-root", &device);
4583         if (r == -ENOENT) { /* volatile-root not found */
4584                 /* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
4585                 * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
4586                 * (think: volatile setups) */
4587 
4588                 FOREACH_STRING(p, "/", "/usr") {
4589 
4590                         r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
4591                         if (r < 0) {
4592                                 if (r == -EUCLEAN)
4593                                         return btrfs_log_dev_root(LOG_ERR, r, p);
4594                                 if (r != -ENODEV)
4595                                         return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
4596                         } else
4597                                 return 0;
4598                 }
4599         } else if (r < 0)
4600                 return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
4601         else {
4602                 r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
4603                 if (r == -EUCLEAN)
4604                         return btrfs_log_dev_root(LOG_ERR, r, device);
4605                 if (r < 0)
4606                         return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", device);
4607 
4608                 return 0;
4609         }
4610 
4611         return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
4612 }
4613 
resize_pt(int fd)4614 static int resize_pt(int fd) {
4615         _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
4616         int r;
4617 
4618         /* After resizing the backing file we need to resize the partition table itself too, so that it takes
4619          * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
4620          * immediately write it again, with no changes. */
4621 
4622         c = fdisk_new_context();
4623         if (!c)
4624                 return log_oom();
4625 
4626         r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(fd), 0);
4627         if (r < 0)
4628                 return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
4629 
4630         r = fdisk_has_label(c);
4631         if (r < 0)
4632                 return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd));
4633         if (r == 0) {
4634                 log_debug("Not resizing partition table, as there currently is none.");
4635                 return 0;
4636         }
4637 
4638         r = fdisk_write_disklabel(c);
4639         if (r < 0)
4640                 return log_error_errno(r, "Failed to write resized partition table: %m");
4641 
4642         log_info("Resized partition table.");
4643         return 1;
4644 }
4645 
resize_backing_fd(const char * node,int * fd,const char * backing_file,LoopDevice * loop_device)4646 static int resize_backing_fd(
4647                 const char *node,           /* The primary way we access the disk image to operate on */
4648                 int *fd,                    /* An O_RDONLY fd referring to that inode */
4649                 const char *backing_file,   /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
4650                 LoopDevice *loop_device) {
4651 
4652         _cleanup_close_ int writable_fd = -1;
4653         uint64_t current_size;
4654         struct stat st;
4655         int r;
4656 
4657         assert(node);
4658         assert(fd);
4659 
4660         if (arg_size == UINT64_MAX) /* Nothing to do */
4661                 return 0;
4662 
4663         if (*fd < 0) {
4664                 /* Open the file if we haven't opened it yet. Note that we open it read-only here, just to
4665                  * keep a reference to the file we can pass around. */
4666                 *fd = open(node, O_RDONLY|O_CLOEXEC);
4667                 if (*fd < 0)
4668                         return log_error_errno(errno, "Failed to open '%s' in order to adjust size: %m", node);
4669         }
4670 
4671         if (fstat(*fd, &st) < 0)
4672                 return log_error_errno(errno, "Failed to stat '%s': %m", node);
4673 
4674         if (S_ISBLK(st.st_mode)) {
4675                 if (!backing_file)
4676                         return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot resize block device '%s'.", node);
4677 
4678                 assert(loop_device);
4679 
4680                 if (ioctl(*fd, BLKGETSIZE64, &current_size) < 0)
4681                         return log_error_errno(errno, "Failed to determine size of block device %s: %m", node);
4682         } else {
4683                 r = stat_verify_regular(&st);
4684                 if (r < 0)
4685                         return log_error_errno(r, "Specified path '%s' is not a regular file or loopback block device, cannot resize: %m", node);
4686 
4687                 assert(!backing_file);
4688                 assert(!loop_device);
4689                 current_size = st.st_size;
4690         }
4691 
4692         if (current_size >= arg_size) {
4693                 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)",
4694                          node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
4695                 return 0;
4696         }
4697 
4698         if (S_ISBLK(st.st_mode)) {
4699                 assert(backing_file);
4700 
4701                 /* This is a loopback device. We can't really grow those directly, but we can grow the
4702                  * backing file, hence let's do that. */
4703 
4704                 writable_fd = open(backing_file, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
4705                 if (writable_fd < 0)
4706                         return log_error_errno(errno, "Failed to open backing file '%s': %m", backing_file);
4707 
4708                 if (fstat(writable_fd, &st) < 0)
4709                         return log_error_errno(errno, "Failed to stat() backing file '%s': %m", backing_file);
4710 
4711                 r = stat_verify_regular(&st);
4712                 if (r < 0)
4713                         return log_error_errno(r, "Backing file '%s' of block device is not a regular file: %m", backing_file);
4714 
4715                 if ((uint64_t) st.st_size != current_size)
4716                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
4717                                                "Size of backing file '%s' of loopback block device '%s' don't match, refusing.",
4718                                                node, backing_file);
4719         } else {
4720                 assert(S_ISREG(st.st_mode));
4721                 assert(!backing_file);
4722 
4723                 /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
4724                  * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
4725                  * as fdisk can't accept it anyway. */
4726 
4727                 writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
4728                 if (writable_fd < 0)
4729                         return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
4730         }
4731 
4732         if (!arg_discard) {
4733                 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
4734                         if (!ERRNO_IS_NOT_SUPPORTED(errno))
4735                                 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by allocation: %m",
4736                                                        node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
4737 
4738                         /* Fallback to truncation, if fallocate() is not supported. */
4739                         log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
4740                 } else {
4741                         if (current_size == 0) /* Likely regular file just created by us */
4742                                 log_info("Allocated %s for '%s'.", FORMAT_BYTES(arg_size), node);
4743                         else
4744                                 log_info("File '%s' grown from %s to %s by allocation.",
4745                                          node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
4746 
4747                         goto done;
4748                 }
4749         }
4750 
4751         if (ftruncate(writable_fd, arg_size) < 0)
4752                 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
4753                                        node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
4754 
4755         if (current_size == 0) /* Likely regular file just created by us */
4756                 log_info("Sized '%s' to %s.", node, FORMAT_BYTES(arg_size));
4757         else
4758                 log_info("File '%s' grown from %s to %s by truncation.",
4759                          node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
4760 
4761 done:
4762         r = resize_pt(writable_fd);
4763         if (r < 0)
4764                 return r;
4765 
4766         if (loop_device) {
4767                 r = loop_device_refresh_size(loop_device, UINT64_MAX, arg_size);
4768                 if (r < 0)
4769                         return log_error_errno(r, "Failed to update loop device size: %m");
4770         }
4771 
4772         return 1;
4773 }
4774 
determine_auto_size(Context * c)4775 static int determine_auto_size(Context *c) {
4776         uint64_t sum;
4777 
4778         assert(c);
4779 
4780         sum = round_up_size(GPT_METADATA_SIZE, 4096);
4781 
4782         LIST_FOREACH(partitions, p, c->partitions) {
4783                 uint64_t m;
4784 
4785                 if (p->dropped)
4786                         continue;
4787 
4788                 m = partition_min_size_with_padding(c, p);
4789                 if (m > UINT64_MAX - sum)
4790                         return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Image would grow too large, refusing.");
4791 
4792                 sum += m;
4793         }
4794 
4795         if (c->total != UINT64_MAX)
4796                 /* Image already allocated? Then show its size. */
4797                 log_info("Automatically determined minimal disk image size as %s, current image size is %s.",
4798                          FORMAT_BYTES(sum), FORMAT_BYTES(c->total));
4799         else
4800                 /* If the image is being created right now, then it has no previous size, suppress any comment about it hence. */
4801                 log_info("Automatically determined minimal disk image size as %s.",
4802                          FORMAT_BYTES(sum));
4803 
4804         arg_size = sum;
4805         return 0;
4806 }
4807 
run(int argc,char * argv[])4808 static int run(int argc, char *argv[]) {
4809         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
4810         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
4811         _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
4812         _cleanup_(context_freep) Context* context = NULL;
4813         _cleanup_free_ char *node = NULL;
4814         _cleanup_close_ int backing_fd = -1;
4815         bool from_scratch, node_is_our_loop = false;
4816         int r;
4817 
4818         log_show_color(true);
4819         log_parse_environment();
4820         log_open();
4821 
4822         r = parse_argv(argc, argv);
4823         if (r <= 0)
4824                 return r;
4825 
4826         r = parse_proc_cmdline_factory_reset();
4827         if (r < 0)
4828                 return r;
4829 
4830         r = parse_efi_variable_factory_reset();
4831         if (r < 0)
4832                 return r;
4833 
4834 #if HAVE_LIBCRYPTSETUP
4835         cryptsetup_enable_logging(NULL);
4836 #endif
4837 
4838         if (arg_image) {
4839                 assert(!arg_root);
4840 
4841                 /* Mount this strictly read-only: we shall modify the partition table, not the file
4842                  * systems */
4843                 r = mount_image_privately_interactively(
4844                                 arg_image,
4845                                 DISSECT_IMAGE_MOUNT_READ_ONLY |
4846                                 (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) */
4847                                 DISSECT_IMAGE_GPT_ONLY |
4848                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
4849                                 DISSECT_IMAGE_USR_NO_ROOT |
4850                                 DISSECT_IMAGE_REQUIRE_ROOT,
4851                                 &mounted_dir,
4852                                 &loop_device,
4853                                 &decrypted_image);
4854                 if (r < 0)
4855                         return r;
4856 
4857                 arg_root = strdup(mounted_dir);
4858                 if (!arg_root)
4859                         return log_oom();
4860 
4861                 if (!arg_node) {
4862                         arg_node = strdup(loop_device->node);
4863                         if (!arg_node)
4864                                 return log_oom();
4865 
4866                         /* Remember that the device we are about to manipulate is actually the one we
4867                          * allocated here, and thus to increase its backing file we know what to do */
4868                         node_is_our_loop = true;
4869                 }
4870         }
4871 
4872         context = context_new(arg_seed);
4873         if (!context)
4874                 return log_oom();
4875 
4876         r = context_read_definitions(context, arg_definitions, arg_root);
4877         if (r < 0)
4878                 return r;
4879 
4880         if (context->n_partitions <= 0 && arg_empty == EMPTY_REFUSE) {
4881                 log_info("Didn't find any partition definition files, nothing to do.");
4882                 return 0;
4883         }
4884 
4885         r = find_root(&node, &backing_fd);
4886         if (r < 0)
4887                 return r;
4888 
4889         if (arg_size != UINT64_MAX) {
4890                 r = resize_backing_fd(
4891                                 node,
4892                                 &backing_fd,
4893                                 node_is_our_loop ? arg_image : NULL,
4894                                 node_is_our_loop ? loop_device : NULL);
4895                 if (r < 0)
4896                         return r;
4897         }
4898 
4899         r = context_load_partition_table(context, node, &backing_fd);
4900         if (r == -EHWPOISON)
4901                 return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't
4902                             * really an error when called at boot. */
4903         if (r < 0)
4904                 return r;
4905         from_scratch = r > 0; /* Starting from scratch */
4906 
4907         if (arg_can_factory_reset) {
4908                 r = context_can_factory_reset(context);
4909                 if (r < 0)
4910                         return r;
4911                 if (r == 0)
4912                         return EXIT_FAILURE;
4913 
4914                 return 0;
4915         }
4916 
4917         r = context_factory_reset(context, from_scratch);
4918         if (r < 0)
4919                 return r;
4920         if (r > 0) {
4921                 /* We actually did a factory reset! */
4922                 r = remove_efi_variable_factory_reset();
4923                 if (r < 0)
4924                         return r;
4925 
4926                 /* Reload the reduced partition table */
4927                 context_unload_partition_table(context);
4928                 r = context_load_partition_table(context, node, &backing_fd);
4929                 if (r < 0)
4930                         return r;
4931         }
4932 
4933 #if 0
4934         (void) context_dump_partitions(context, node);
4935         putchar('\n');
4936 #endif
4937 
4938         r = context_read_seed(context, arg_root);
4939         if (r < 0)
4940                 return r;
4941 
4942         /* Open all files to copy blocks from now, since we want to take their size into consideration */
4943         r = context_open_copy_block_paths(
4944                         context,
4945                         arg_root,
4946                         loop_device ? loop_device->devno :         /* if --image= is specified, only allow partitions on the loopback device */
4947                                       arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
4948                                       (dev_t) -1);                 /* if neither is specified, make no restrictions */
4949         if (r < 0)
4950                 return r;
4951 
4952         if (arg_size_auto) {
4953                 r = determine_auto_size(context);
4954                 if (r < 0)
4955                         return r;
4956 
4957                 /* Flush out everything again, and let's grow the file first, then start fresh */
4958                 context_unload_partition_table(context);
4959 
4960                 assert(arg_size != UINT64_MAX);
4961                 r = resize_backing_fd(
4962                                 node,
4963                                 &backing_fd,
4964                                 node_is_our_loop ? arg_image : NULL,
4965                                 node_is_our_loop ? loop_device : NULL);
4966                 if (r < 0)
4967                         return r;
4968 
4969                 r = context_load_partition_table(context, node, &backing_fd);
4970                 if (r < 0)
4971                         return r;
4972         }
4973 
4974         /* First try to fit new partitions in, dropping by priority until it fits */
4975         for (;;) {
4976                 uint64_t largest_free_area;
4977 
4978                 if (context_allocate_partitions(context, &largest_free_area))
4979                         break; /* Success! */
4980 
4981                 if (!context_drop_one_priority(context)) {
4982                         r = log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
4983                                             "Can't fit requested partitions into available free space (%s), refusing.",
4984                                             FORMAT_BYTES(largest_free_area));
4985                         determine_auto_size(context);
4986                         return r;
4987                 }
4988         }
4989 
4990         /* Now assign free space according to the weight logic */
4991         r = context_grow_partitions(context);
4992         if (r < 0)
4993                 return r;
4994 
4995         /* Now calculate where each new partition gets placed */
4996         context_place_partitions(context);
4997 
4998         /* Make sure each partition has a unique UUID and unique label */
4999         r = context_acquire_partition_uuids_and_labels(context);
5000         if (r < 0)
5001                 return r;
5002 
5003         r = context_write_partition_table(context, node, from_scratch);
5004         if (r < 0)
5005                 return r;
5006 
5007         return 0;
5008 }
5009 
5010 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
5011