summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2022-10-14 12:06:55 +0200
committerDaan De Meyer <daan.j.demeyer@gmail.com>2022-11-15 13:45:25 +0100
commit81d1098bc1f6b607c57798932c4117a118d84929 (patch)
tree72d54f5413be95f55fd44c032ca0a9ab92c354b5
parent00428745e3d1e42fe4481fc8a5c50d6316d4282a (diff)
downloadsystemd-81d1098bc1f6b607c57798932c4117a118d84929.tar.gz
repart: Add --include/--exclude-partitions
Let's allow filtering the partitions to operate on by partition type UUID. This is necessary when building bootable images with a verity protected root/usr partition as we can only build the UKI image when we have the verity roothash which means we cannot populate the EFI partition yet when we run repart initially to determine the verity roothash.
-rw-r--r--man/systemd-repart.xml17
-rw-r--r--src/partition/repart.c106
2 files changed, 123 insertions, 0 deletions
diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml
index 3585cbf107..6559fceedb 100644
--- a/man/systemd-repart.xml
+++ b/man/systemd-repart.xml
@@ -363,6 +363,23 @@
if <option>--split</option> is enabled.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--include-partitions=</option><arg rep="repeat">PARTITION</arg></term>
+ <term><option>--exclude-partitions=</option><arg rep="repeat">PARTITION</arg></term>
+
+ <listitem><para>These options specify which partition types <command>systemd-repart</command> should
+ operate on. If <option>--include-partitions=</option> is used, all partitions that aren't specified
+ are excluded. If <option>--exclude-partitions=</option> is used, all partitions that are specified
+ are excluded. Both options take a comma separated list of GPT partition type UUIDs or identifiers
+ (see <varname>Type=</varname> in
+ <citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>). All
+ partitions that are excluded using these options are still taken into account when calculating the
+ sizes and offsets of other partitions, but aren't actually written to the disk image. The net effect
+ of this option is that if you run <command>systemd-repart</command> again without these options, the
+ missing partitions will be added as if they had not been excluded the first time
+ <command>systemd-repart</command> was executed.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
diff --git a/src/partition/repart.c b/src/partition/repart.c
index c2051de659..f4c3708766 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -103,6 +103,14 @@ static enum {
EMPTY_CREATE, /* create disk as loopback file, create a partition table always */
} arg_empty = EMPTY_REFUSE;
+typedef enum {
+ FILTER_PARTITIONS_NONE,
+ FILTER_PARTITIONS_EXCLUDE,
+ FILTER_PARTITIONS_INCLUDE,
+ _FILTER_PARTITIONS_MAX,
+ _FILTER_PARTITIONS_INVALID = -EINVAL,
+} FilterPartitionsType;
+
static bool arg_dry_run = true;
static const char *arg_node = NULL;
static char *arg_root = NULL;
@@ -128,6 +136,9 @@ static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
static char *arg_tpm2_public_key = NULL;
static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX;
static bool arg_split = false;
+static sd_id128_t *arg_filter_partitions = NULL;
+static size_t arg_filter_partitions_size = 0;
+static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -137,6 +148,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_private_key, EVP_PKEY_freep);
STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
typedef struct Partition Partition;
typedef struct FreeArea FreeArea;
@@ -372,6 +384,19 @@ static void partition_foreignize(Partition *p) {
p->verity = VERITY_OFF;
}
+static bool partition_skip(const Partition *p) {
+ assert(p);
+
+ if (arg_filter_partitions_type == FILTER_PARTITIONS_NONE)
+ return false;
+
+ for (size_t i = 0; i < arg_filter_partitions_size; i++)
+ if (sd_id128_equal(p->type.uuid, arg_filter_partitions[i]))
+ return arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE;
+
+ return arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE;
+}
+
static Partition* partition_unlink_and_free(Context *context, Partition *p) {
if (!p)
return NULL;
@@ -2930,6 +2955,9 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) {
if (!p->allocated_to_area)
continue;
+ if (partition_skip(p))
+ continue;
+
r = context_wipe_partition(context, p);
if (r < 0)
return r;
@@ -3187,6 +3215,9 @@ static int context_copy_blocks(Context *context) {
if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */
continue;
+ if (partition_skip(p))
+ continue;
+
assert(p->new_size != UINT64_MAX);
assert(p->copy_blocks_size != UINT64_MAX);
assert(p->new_size >= p->copy_blocks_size);
@@ -3537,6 +3568,9 @@ static int context_mkfs(Context *context) {
if (p->copy_blocks_fd >= 0)
continue;
+ if (partition_skip(p))
+ continue;
+
assert(p->offset != UINT64_MAX);
assert(p->new_size != UINT64_MAX);
@@ -3708,6 +3742,9 @@ static int context_verity_hash(Context *context) {
if (p->verity != VERITY_HASH)
continue;
+ if (partition_skip(p))
+ continue;
+
assert_se(dp = p->siblings[VERITY_DATA]);
assert(!dp->dropped);
@@ -3870,6 +3907,9 @@ static int context_verity_sig(Context *context) {
if (p->verity != VERITY_SIG)
continue;
+ if (partition_skip(p))
+ continue;
+
assert_se(hp = p->siblings[VERITY_HASH]);
assert(!hp->dropped);
@@ -4171,6 +4211,9 @@ static int context_mangle_partitions(Context *context) {
if (p->dropped)
continue;
+ if (partition_skip(p))
+ continue;
+
assert(p->new_size != UINT64_MAX);
assert(p->offset != UINT64_MAX);
assert(p->partno != UINT64_MAX);
@@ -4411,6 +4454,9 @@ static int context_split(Context *context) {
if (!p->split_name_resolved)
continue;
+ if (partition_skip(p))
+ continue;
+
fname = strjoin(base, ".", p->split_name_resolved, ext);
if (!fname)
return log_oom();
@@ -5180,6 +5226,32 @@ static int context_minimize(Context *context) {
return 0;
}
+static int parse_filter_partitions(const char *p) {
+ int r;
+
+ for (;;) {
+ _cleanup_free_ char *name = NULL;
+ GptPartitionType type;
+
+ r = extract_first_word(&p, &name, ",", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
+ if (r == 0)
+ break;
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract partition designator: %s", optarg);
+
+ r = gpt_partition_type_from_string(name, &type);
+ if (r < 0)
+ return log_error_errno(r, "'%s' is not a valid partition designator", name);
+
+ if (!GREEDY_REALLOC(arg_filter_partitions, arg_filter_partitions_size + 1))
+ return log_oom();
+
+ arg_filter_partitions[arg_filter_partitions_size++] = type.uuid;
+ }
+
+ return 0;
+}
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@@ -5222,6 +5294,10 @@ static int help(void) {
" --json=pretty|short|off\n"
" Generate JSON output\n"
" --split=BOOL Whether to generate split artifacts\n"
+ " --include-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
+ " Only operate on partitions of the specified types\n"
+ " --exclude-partitions=PARTITION1,PARTITION2,PARTITION3,…\n"
+ " Don't operate on partitions of the specified types\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@@ -5257,6 +5333,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_TPM2_PUBLIC_KEY,
ARG_TPM2_PUBLIC_KEY_PCRS,
ARG_SPLIT,
+ ARG_INCLUDE_PARTITIONS,
+ ARG_EXCLUDE_PARTITIONS,
};
static const struct option options[] = {
@@ -5284,6 +5362,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
{ "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
{ "split", required_argument, NULL, ARG_SPLIT },
+ { "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS },
+ { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS },
{}
};
@@ -5538,6 +5618,32 @@ static int parse_argv(int argc, char *argv[]) {
arg_split = r;
break;
+ case ARG_INCLUDE_PARTITIONS:
+ if (arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Combination of --include-partitions= and --exclude-partitions= is invalid.");
+
+ r = parse_filter_partitions(optarg);
+ if (r < 0)
+ return r;
+
+ arg_filter_partitions_type = FILTER_PARTITIONS_INCLUDE;
+
+ break;
+
+ case ARG_EXCLUDE_PARTITIONS:
+ if (arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Combination of --include-partitions= and --exclude-partitions= is invalid.");
+
+ r = parse_filter_partitions(optarg);
+ if (r < 0)
+ return r;
+
+ arg_filter_partitions_type = FILTER_PARTITIONS_EXCLUDE;
+
+ break;
+
case '?':
return -EINVAL;