1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #25001 from DaanDeMeyer/repart-filter

repart: Add --include/--exclude-partitions
This commit is contained in:
Daan De Meyer 2022-11-15 20:07:24 +01:00 committed by GitHub
commit 2b0cff0469
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 375 additions and 434 deletions

View File

@ -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" />

View File

@ -123,10 +123,13 @@ static int verb_show(int argc, char **argv, void *userdata) {
if (have_uuid)
id = gpt_partition_type_uuid_to_string(uuid) ?: "XYZ";
else {
r = gpt_partition_type_uuid_from_string(*p, &uuid);
GptPartitionType type;
r = gpt_partition_type_from_string(*p, &type);
if (r < 0)
return log_error_errno(r, "Unknown identifier \"%s\".", *p);
uuid = type.uuid;
id = *p;
}

View File

@ -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;
@ -164,7 +176,7 @@ struct Partition {
char *definition_path;
char **drop_in_files;
sd_id128_t type_uuid;
GptPartitionType type;
sd_id128_t current_uuid, new_uuid;
bool new_uuid_is_set;
char *current_label, *new_label;
@ -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;
@ -1025,21 +1050,30 @@ static int context_grow_partitions(Context *context) {
return 0;
}
static void context_place_partitions(Context *context) {
static uint64_t find_first_unused_partno(Context *context) {
uint64_t partno = 0;
assert(context);
/* Determine next partition number to assign */
LIST_FOREACH(partitions, p, context->partitions) {
if (!PARTITION_EXISTS(p))
continue;
for (bool changed = true; changed;) {
changed = false;
assert(p->partno != UINT64_MAX);
if (p->partno >= partno)
partno = p->partno + 1;
LIST_FOREACH(partitions, p, context->partitions) {
if (p->partno != UINT64_MAX && p->partno == partno) {
partno++;
changed = true;
break;
}
}
}
return partno;
}
static void context_place_partitions(Context *context) {
assert(context);
for (size_t i = 0; i < context->n_free_areas; i++) {
FreeArea *a = context->free_areas[i];
_unused_ uint64_t left;
@ -1062,7 +1096,7 @@ static void context_place_partitions(Context *context) {
continue;
p->offset = start;
p->partno = partno++;
p->partno = find_first_unused_partno(context);
assert(left >= p->new_size);
start += p->new_size;
@ -1087,12 +1121,12 @@ static int config_parse_type(
void *data,
void *userdata) {
sd_id128_t *type_uuid = ASSERT_PTR(data);
GptPartitionType *type = ASSERT_PTR(data);
int r;
assert(rvalue);
r = gpt_partition_type_uuid_from_string(rvalue, type_uuid);
r = gpt_partition_type_from_string(rvalue, type);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue);
@ -1478,7 +1512,7 @@ static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_verity, verity_mode, V
static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
ConfigTableItem table[] = {
{ "Partition", "Type", config_parse_type, 0, &p->type_uuid },
{ "Partition", "Type", config_parse_type, 0, &p->type },
{ "Partition", "Label", config_parse_label, 0, &p->new_label },
{ "Partition", "UUID", config_parse_uuid, 0, p },
{ "Partition", "Priority", config_parse_int32, 0, &p->priority },
@ -1535,7 +1569,7 @@ static int partition_read_definition(Partition *p, const char *path, const char
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
"PaddingMinBytes= larger than PaddingMaxBytes=, refusing.");
if (sd_id128_is_null(p->type_uuid))
if (sd_id128_is_null(p->type.uuid))
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
"Type= not defined, refusing.");
@ -1599,13 +1633,13 @@ static int partition_read_definition(Partition *p, const char *path, const char
verity_mode_to_string(p->verity));
/* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
if ((gpt_partition_type_is_root_verity(p->type_uuid) ||
gpt_partition_type_is_usr_verity(p->type_uuid)) &&
if ((p->type.designator == PARTITION_ROOT_VERITY ||
p->type.designator == PARTITION_USR_VERITY) &&
p->read_only < 0)
p->read_only = true;
/* Default to "growfs" on, unless read-only */
if (gpt_partition_type_knows_growfs(p->type_uuid) &&
if (gpt_partition_type_knows_growfs(p->type) &&
p->read_only <= 0)
p->growfs = true;
@ -2099,7 +2133,7 @@ static int context_load_partition_table(
LIST_FOREACH(partitions, pp, context->partitions) {
last = pp;
if (!sd_id128_equal(pp->type_uuid, ptid))
if (!sd_id128_equal(pp->type.uuid, ptid))
continue;
if (!pp->current_partition) {
@ -2136,7 +2170,7 @@ static int context_load_partition_table(
return log_oom();
np->current_uuid = id;
np->type_uuid = ptid;
np->type = gpt_partition_type_from_uuid(ptid);
np->current_size = sz;
np->offset = start;
np->partno = partno;
@ -2295,7 +2329,7 @@ static const char *partition_label(const Partition *p) {
if (p->current_label)
return p->current_label;
return gpt_partition_type_uuid_to_string(p->type_uuid);
return gpt_partition_type_uuid_to_string(p->type.uuid);
}
static int context_dump_partitions(Context *context, const char *node) {
@ -2369,7 +2403,7 @@ static int context_dump_partitions(Context *context, const char *node) {
r = table_add_many(
t,
TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type.uuid, uuid_buffer),
TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
TABLE_UUID, p->new_uuid_is_set ? p->new_uuid : p->current_uuid,
TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
@ -2503,7 +2537,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
else if (!sd_id128_is_null(p->current_uuid))
id = p->current_uuid;
else
id = p->type_uuid;
id = p->type.uuid;
buf = strdup(SD_ID128_TO_UUID_STRING(id));
@ -2921,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;
@ -3178,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);
@ -3463,7 +3503,7 @@ static int make_copy_files_denylist(Context *context, Set **ret) {
assert(ret);
LIST_FOREACH(partitions, p, context->partitions) {
const char *sources = gpt_partition_type_mountpoint_nulstr(p->type_uuid);
const char *sources = gpt_partition_type_mountpoint_nulstr(p->type);
if (!sources)
continue;
@ -3528,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);
@ -3699,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);
@ -3861,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);
@ -3955,13 +4004,13 @@ static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *re
if (p == q)
break;
if (!sd_id128_equal(p->type_uuid, q->type_uuid))
if (!sd_id128_equal(p->type.uuid, q->type.uuid))
continue;
k++;
}
plaintext.type_uuid = p->type_uuid;
plaintext.type_uuid = p->type.uuid;
plaintext.counter = htole64(k);
hmac_sha256(context->seed.bytes, sizeof(context->seed.bytes),
@ -4002,7 +4051,7 @@ static int partition_acquire_label(Context *context, Partition *p, char **ret) {
assert(p);
assert(ret);
prefix = gpt_partition_type_uuid_to_string(p->type_uuid);
prefix = gpt_partition_type_uuid_to_string(p->type.uuid);
if (!prefix)
prefix = "linux";
@ -4118,35 +4167,35 @@ static uint64_t partition_merge_flags(Partition *p) {
f = p->gpt_flags;
if (p->no_auto >= 0) {
if (gpt_partition_type_knows_no_auto(p->type_uuid))
if (gpt_partition_type_knows_no_auto(p->type))
SET_FLAG(f, SD_GPT_FLAG_NO_AUTO, p->no_auto);
else {
char buffer[SD_ID128_UUID_STRING_MAX];
log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->no_auto),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
}
}
if (p->read_only >= 0) {
if (gpt_partition_type_knows_read_only(p->type_uuid))
if (gpt_partition_type_knows_read_only(p->type))
SET_FLAG(f, SD_GPT_FLAG_READ_ONLY, p->read_only);
else {
char buffer[SD_ID128_UUID_STRING_MAX];
log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->read_only),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
}
}
if (p->growfs >= 0) {
if (gpt_partition_type_knows_growfs(p->type_uuid))
if (gpt_partition_type_knows_growfs(p->type))
SET_FLAG(f, SD_GPT_FLAG_GROWFS, p->growfs);
else {
char buffer[SD_ID128_UUID_STRING_MAX];
log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->growfs),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer));
}
}
@ -4162,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);
@ -4225,7 +4277,7 @@ static int context_mangle_partitions(Context *context) {
if (!t)
return log_oom();
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid));
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid));
if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m");
@ -4284,8 +4336,8 @@ static int split_name_printf(Partition *p) {
assert(p);
const Specifier table[] = {
{ 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type_uuid) },
{ 'T', specifier_id128, &p->type_uuid },
{ 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type.uuid) },
{ 'T', specifier_id128, &p->type.uuid },
{ 'U', specifier_id128, &p->new_uuid },
{ 'n', specifier_uint64, &p->partno },
@ -4402,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();
@ -4614,7 +4669,7 @@ static int context_can_factory_reset(Context *context) {
static int resolve_copy_blocks_auto_candidate(
dev_t partition_devno,
sd_id128_t partition_type_uuid,
GptPartitionType partition_type,
dev_t restrict_devno,
sd_id128_t *ret_uuid) {
@ -4706,10 +4761,10 @@ static int resolve_copy_blocks_auto_candidate(
return false;
}
if (!sd_id128_equal(pt_parsed, partition_type_uuid)) {
if (!sd_id128_equal(pt_parsed, partition_type.uuid)) {
log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
major(partition_devno), minor(partition_devno),
SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type_uuid));
SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type.uuid));
return false;
}
@ -4766,7 +4821,7 @@ static int find_backing_devno(
}
static int resolve_copy_blocks_auto(
sd_id128_t type_uuid,
GptPartitionType type,
const char *root,
dev_t restrict_devno,
dev_t *ret_devno,
@ -4796,30 +4851,30 @@ static int resolve_copy_blocks_auto(
* partitions in the host, using the appropriate directory as key and ensuring that the partition
* type matches. */
if (gpt_partition_type_is_root(type_uuid))
if (type.designator == PARTITION_ROOT)
try1 = "/";
else if (gpt_partition_type_is_usr(type_uuid))
else if (type.designator == PARTITION_USR)
try1 = "/usr/";
else if (gpt_partition_type_is_root_verity(type_uuid))
else if (type.designator == PARTITION_ROOT_VERITY)
try1 = "/";
else if (gpt_partition_type_is_usr_verity(type_uuid))
else if (type.designator == PARTITION_USR_VERITY)
try1 = "/usr/";
else if (sd_id128_equal(type_uuid, SD_GPT_ESP)) {
else if (type.designator == PARTITION_ESP) {
try1 = "/efi/";
try2 = "/boot/";
} else if (sd_id128_equal(type_uuid, SD_GPT_XBOOTLDR))
} else if (type.designator == PARTITION_XBOOTLDR)
try1 = "/boot/";
else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
SD_ID128_FORMAT_VAL(type_uuid));
SD_ID128_FORMAT_VAL(type.uuid));
r = find_backing_devno(try1, root, &devno);
if (r == -ENOENT && try2)
r = find_backing_devno(try2, root, &devno);
if (r < 0)
return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
SD_ID128_FORMAT_VAL(type_uuid));
SD_ID128_FORMAT_VAL(type.uuid));
xsprintf_sys_block_path(p, "/slaves", devno);
d = opendir(p);
@ -4861,7 +4916,7 @@ static int resolve_copy_blocks_auto(
continue;
}
r = resolve_copy_blocks_auto_candidate(sl, type_uuid, restrict_devno, &u);
r = resolve_copy_blocks_auto_candidate(sl, type, restrict_devno, &u);
if (r < 0)
return r;
if (r > 0) {
@ -4877,7 +4932,7 @@ static int resolve_copy_blocks_auto(
} else if (errno != ENOENT)
return log_error_errno(errno, "Failed open %s: %m", p);
else {
r = resolve_copy_blocks_auto_candidate(devno, type_uuid, restrict_devno, &found_uuid);
r = resolve_copy_blocks_auto_candidate(devno, type, restrict_devno, &found_uuid);
if (r < 0)
return r;
if (r > 0)
@ -4934,7 +4989,7 @@ static int context_open_copy_block_paths(
} else if (p->copy_blocks_auto) {
dev_t devno;
r = resolve_copy_blocks_auto(p->type_uuid, p->copy_blocks_root, restrict_devno, &devno, &uuid);
r = resolve_copy_blocks_auto(p->type, p->copy_blocks_root, restrict_devno, &devno, &uuid);
if (r < 0)
return r;
@ -5171,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;
@ -5213,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(),
@ -5248,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[] = {
@ -5275,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 },
{}
};
@ -5529,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;

View File

@ -333,6 +333,27 @@ static int open_partition(const char *node, bool is_partition, const LoopDevice
return TAKE_FD(fd);
}
static int compare_arch(Architecture a, Architecture b) {
if (a == b)
return 0;
if (a == native_architecture())
return 1;
if (b == native_architecture())
return -1;
#ifdef ARCHITECTURE_SECONDARY
if (a == ARCHITECTURE_SECONDARY)
return 1;
if (b == ARCHITECTURE_SECONDARY)
return -1;
#endif
return 0;
}
static int dissect_image(
DissectedImage *m,
int fd,
@ -606,10 +627,9 @@ static int dissect_image(
}
if (is_gpt) {
PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
Architecture architecture = _ARCHITECTURE_INVALID;
const char *stype, *sid, *fstype = NULL, *label;
sd_id128_t type_id, id;
GptPartitionType type;
bool rw = true, growfs = false;
sid = blkid_partition_get_uuid(pp);
@ -624,9 +644,11 @@ static int dissect_image(
if (sd_id128_from_string(stype, &type_id) < 0)
continue;
type = gpt_partition_type_from_uuid(type_id);
label = blkid_partition_get_name(pp); /* libblkid returns NULL here if empty */
if (sd_id128_equal(type_id, SD_GPT_HOME)) {
if (type.designator == PARTITION_HOME) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -634,11 +656,10 @@ static int dissect_image(
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_HOME;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, SD_GPT_SRV)) {
} else if (type.designator == PARTITION_SRV) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -646,11 +667,10 @@ static int dissect_image(
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_SRV;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, SD_GPT_ESP)) {
} else if (type.designator == PARTITION_ESP) {
/* Note that we don't check the SD_GPT_FLAG_NO_AUTO flag for the ESP, as it is
* not defined there. We instead check the SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as
@ -660,10 +680,9 @@ static int dissect_image(
if (pflags & SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL)
continue;
designator = PARTITION_ESP;
fstype = "vfat";
} else if (sd_id128_equal(type_id, SD_GPT_XBOOTLDR)) {
} else if (type.designator == PARTITION_XBOOTLDR) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -671,11 +690,10 @@ static int dissect_image(
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_XBOOTLDR;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (gpt_partition_type_is_root(type_id)) {
} else if (type.designator == PARTITION_ROOT) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -687,12 +705,10 @@ static int dissect_image(
if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id))
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_root_of_arch(architecture);
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (gpt_partition_type_is_root_verity(type_id)) {
} else if (type.designator == PARTITION_ROOT_VERITY) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
@ -712,12 +728,10 @@ static int dissect_image(
if (!sd_id128_is_null(root_verity_uuid) && !sd_id128_equal(root_verity_uuid, id))
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_verity_of(partition_root_of_arch(architecture));
fstype = "DM_verity_hash";
rw = false;
} else if (gpt_partition_type_is_root_verity_sig(type_id)) {
} else if (type.designator == PARTITION_ROOT_VERITY_SIG) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
@ -732,12 +746,10 @@ static int dissect_image(
if (verity->designator >= 0 && verity->designator != PARTITION_ROOT)
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_verity_sig_of(partition_root_of_arch(architecture));
fstype = "verity_hash_signature";
rw = false;
} else if (gpt_partition_type_is_usr(type_id)) {
} else if (type.designator == PARTITION_USR) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -749,12 +761,10 @@ static int dissect_image(
if (!sd_id128_is_null(usr_uuid) && !sd_id128_equal(usr_uuid, id))
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_usr_of_arch(architecture);
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (gpt_partition_type_is_usr_verity(type_id)) {
} else if (type.designator == PARTITION_USR_VERITY) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
@ -773,12 +783,10 @@ static int dissect_image(
if (!sd_id128_is_null(usr_verity_uuid) && !sd_id128_equal(usr_verity_uuid, id))
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_verity_of(partition_usr_of_arch(architecture));
fstype = "DM_verity_hash";
rw = false;
} else if (gpt_partition_type_is_usr_verity_sig(type_id)) {
} else if (type.designator == PARTITION_USR_VERITY_SIG) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY);
@ -793,21 +801,17 @@ static int dissect_image(
if (verity->designator >= 0 && verity->designator != PARTITION_USR)
continue;
assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0);
designator = partition_verity_sig_of(partition_usr_of_arch(architecture));
fstype = "verity_hash_signature";
rw = false;
} else if (sd_id128_equal(type_id, SD_GPT_SWAP)) {
} else if (type.designator == PARTITION_SWAP) {
check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO);
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_SWAP;
} else if (sd_id128_equal(type_id, SD_GPT_LINUX_GENERIC)) {
} else if (type.designator == PARTITION_LINUX_GENERIC) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -827,7 +831,7 @@ static int dissect_image(
return -ENOMEM;
}
} else if (sd_id128_equal(type_id, SD_GPT_TMP)) {
} else if (type.designator == PARTITION_TMP) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -835,11 +839,10 @@ static int dissect_image(
if (pflags & SD_GPT_FLAG_NO_AUTO)
continue;
designator = PARTITION_TMP;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
} else if (sd_id128_equal(type_id, SD_GPT_VAR)) {
} else if (type.designator == PARTITION_VAR) {
check_partition_flags(node, pflags,
SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS);
@ -868,27 +871,29 @@ static int dissect_image(
}
}
designator = PARTITION_VAR;
rw = !(pflags & SD_GPT_FLAG_READ_ONLY);
growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS);
}
if (designator != _PARTITION_DESIGNATOR_INVALID) {
if (type.designator != _PARTITION_DESIGNATOR_INVALID) {
_cleanup_free_ char *t = NULL, *o = NULL, *l = NULL;
_cleanup_close_ int mount_node_fd = -1;
const char *options = NULL;
if (m->partitions[designator].found) {
if (m->partitions[type.designator].found) {
/* For most partition types the first one we see wins. Except for the
* rootfs and /usr, where we do a version compare of the label, and
* let the newest version win. This permits a simple A/B versioning
* scheme in OS images. */
if (!partition_designator_is_versioned(designator) ||
strverscmp_improved(m->partitions[designator].label, label) >= 0)
if (compare_arch(type.arch, m->partitions[type.designator].architecture) <= 0)
continue;
dissected_partition_done(m->partitions + designator);
if (!partition_designator_is_versioned(type.designator) ||
strverscmp_improved(m->partitions[type.designator].label, label) >= 0)
continue;
dissected_partition_done(m->partitions + type.designator);
}
if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
@ -909,19 +914,19 @@ static int dissect_image(
return -ENOMEM;
}
options = mount_options_from_designator(mount_options, designator);
options = mount_options_from_designator(mount_options, type.designator);
if (options) {
o = strdup(options);
if (!o)
return -ENOMEM;
}
m->partitions[designator] = (DissectedPartition) {
m->partitions[type.designator] = (DissectedPartition) {
.found = true,
.partno = nr,
.rw = rw,
.growfs = growfs,
.architecture = architecture,
.architecture = type.arch,
.node = TAKE_PTR(node),
.fstype = TAKE_PTR(t),
.label = TAKE_PTR(l),
@ -1001,121 +1006,21 @@ static int dissect_image(
}
}
if (m->partitions[PARTITION_ROOT].found) {
/* If we found the primary arch, then invalidate the secondary and other arch to avoid any
* ambiguities, since we never want to mount the secondary or other arch in this case. */
m->partitions[PARTITION_ROOT_SECONDARY].found = false;
m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found = false;
m->partitions[PARTITION_USR_SECONDARY].found = false;
m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false;
m->partitions[PARTITION_ROOT_OTHER].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false;
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
} else if (m->partitions[PARTITION_ROOT_VERITY].found ||
m->partitions[PARTITION_ROOT_VERITY_SIG].found)
return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */
else if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
/* No root partition found but there's one for the secondary architecture? Then upgrade
* secondary arch to first and invalidate the other arch. */
log_debug("No root partition found of the native architecture, falling back to a root "
"partition of the secondary architecture.");
m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY]);
m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_ROOT_OTHER].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false;
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
} else if (m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found ||
m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found)
return -EADDRNOTAVAIL; /* as above */
else if (m->partitions[PARTITION_ROOT_OTHER].found) {
/* No root or secondary partition found but there's one for another architecture? Then
* upgrade the other architecture to first. */
log_debug("No root partition found of the native architecture or the secondary architecture, "
"falling back to a root partition of a non-native architecture (%s).",
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER]);
m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
if (!m->partitions[PARTITION_ROOT].found &&
(m->partitions[PARTITION_ROOT_VERITY].found ||
m->partitions[PARTITION_ROOT_VERITY_SIG].found))
return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */
/* Hmm, we found a signature partition but no Verity data? Something is off. */
if (m->partitions[PARTITION_ROOT_VERITY_SIG].found && !m->partitions[PARTITION_ROOT_VERITY].found)
return -EADDRNOTAVAIL;
if (m->partitions[PARTITION_USR].found) {
/* Invalidate secondary and other arch /usr/ if we found the primary arch */
m->partitions[PARTITION_USR_SECONDARY].found = false;
m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false;
if (!m->partitions[PARTITION_USR].found &&
(m->partitions[PARTITION_USR_VERITY].found ||
m->partitions[PARTITION_USR_VERITY_SIG].found))
return -EADDRNOTAVAIL; /* as above */
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
} else if (m->partitions[PARTITION_USR_VERITY].found ||
m->partitions[PARTITION_USR_VERITY_SIG].found)
return -EADDRNOTAVAIL; /* as above */
else if (m->partitions[PARTITION_USR_SECONDARY].found) {
log_debug("No usr partition found of the native architecture, falling back to a usr "
"partition of the secondary architecture.");
/* Upgrade secondary arch to primary */
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false;
} else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found ||
m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found)
return -EADDRNOTAVAIL; /* as above */
else if (m->partitions[PARTITION_USR_OTHER].found) {
log_debug("No usr partition found of the native architecture or the secondary architecture, "
"falling back to a usr partition of a non-native architecture (%s).",
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
/* Upgrade other arch to primary */
m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
/* Hmm, we found a signature partition but no Verity data? Something is off. */
/* as above */
if (m->partitions[PARTITION_USR_VERITY_SIG].found && !m->partitions[PARTITION_USR_VERITY].found)
return -EADDRNOTAVAIL;

View File

@ -23,23 +23,11 @@ bool partition_designator_is_versioned(PartitionDesignator d) {
return IN_SET(d,
PARTITION_ROOT,
PARTITION_ROOT_SECONDARY,
PARTITION_ROOT_OTHER,
PARTITION_USR,
PARTITION_USR_SECONDARY,
PARTITION_USR_OTHER,
PARTITION_ROOT_VERITY,
PARTITION_ROOT_SECONDARY_VERITY,
PARTITION_ROOT_OTHER_VERITY,
PARTITION_USR_VERITY,
PARTITION_USR_SECONDARY_VERITY,
PARTITION_USR_OTHER_VERITY,
PARTITION_ROOT_VERITY_SIG,
PARTITION_ROOT_SECONDARY_VERITY_SIG,
PARTITION_ROOT_OTHER_VERITY_SIG,
PARTITION_USR_VERITY_SIG,
PARTITION_USR_SECONDARY_VERITY_SIG,
PARTITION_USR_OTHER_VERITY_SIG);
PARTITION_USR_VERITY_SIG);
}
PartitionDesignator partition_verity_of(PartitionDesignator p) {
@ -48,21 +36,9 @@ PartitionDesignator partition_verity_of(PartitionDesignator p) {
case PARTITION_ROOT:
return PARTITION_ROOT_VERITY;
case PARTITION_ROOT_SECONDARY:
return PARTITION_ROOT_SECONDARY_VERITY;
case PARTITION_ROOT_OTHER:
return PARTITION_ROOT_OTHER_VERITY;
case PARTITION_USR:
return PARTITION_USR_VERITY;
case PARTITION_USR_SECONDARY:
return PARTITION_USR_SECONDARY_VERITY;
case PARTITION_USR_OTHER:
return PARTITION_USR_OTHER_VERITY;
default:
return _PARTITION_DESIGNATOR_INVALID;
}
@ -74,82 +50,27 @@ PartitionDesignator partition_verity_sig_of(PartitionDesignator p) {
case PARTITION_ROOT:
return PARTITION_ROOT_VERITY_SIG;
case PARTITION_ROOT_SECONDARY:
return PARTITION_ROOT_SECONDARY_VERITY_SIG;
case PARTITION_ROOT_OTHER:
return PARTITION_ROOT_OTHER_VERITY_SIG;
case PARTITION_USR:
return PARTITION_USR_VERITY_SIG;
case PARTITION_USR_SECONDARY:
return PARTITION_USR_SECONDARY_VERITY_SIG;
case PARTITION_USR_OTHER:
return PARTITION_USR_OTHER_VERITY_SIG;
default:
return _PARTITION_DESIGNATOR_INVALID;
}
}
PartitionDesignator partition_root_of_arch(Architecture arch) {
switch (arch) {
case native_architecture():
return PARTITION_ROOT;
#ifdef ARCHITECTURE_SECONDARY
case ARCHITECTURE_SECONDARY:
return PARTITION_ROOT_SECONDARY;
#endif
default:
return PARTITION_ROOT_OTHER;
}
}
PartitionDesignator partition_usr_of_arch(Architecture arch) {
switch (arch) {
case native_architecture():
return PARTITION_USR;
#ifdef ARCHITECTURE_SECONDARY
case ARCHITECTURE_SECONDARY:
return PARTITION_USR_SECONDARY;
#endif
default:
return PARTITION_USR_OTHER;
}
}
static const char *const partition_designator_table[] = {
[PARTITION_ROOT] = "root",
[PARTITION_ROOT_SECONDARY] = "root-secondary",
[PARTITION_ROOT_OTHER] = "root-other",
[PARTITION_USR] = "usr",
[PARTITION_USR_SECONDARY] = "usr-secondary",
[PARTITION_USR_OTHER] = "usr-other",
[PARTITION_HOME] = "home",
[PARTITION_SRV] = "srv",
[PARTITION_ESP] = "esp",
[PARTITION_XBOOTLDR] = "xbootldr",
[PARTITION_SWAP] = "swap",
[PARTITION_ROOT_VERITY] = "root-verity",
[PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity",
[PARTITION_ROOT_OTHER_VERITY] = "root-other-verity",
[PARTITION_USR_VERITY] = "usr-verity",
[PARTITION_USR_SECONDARY_VERITY] = "usr-secondary-verity",
[PARTITION_USR_OTHER_VERITY] = "usr-other-verity",
[PARTITION_ROOT_VERITY_SIG] = "root-verity-sig",
[PARTITION_ROOT_SECONDARY_VERITY_SIG] = "root-secondary-verity-sig",
[PARTITION_ROOT_OTHER_VERITY_SIG] = "root-other-verity-sig",
[PARTITION_USR_VERITY_SIG] = "usr-verity-sig",
[PARTITION_USR_SECONDARY_VERITY_SIG] = "usr-secondary-verity-sig",
[PARTITION_USR_OTHER_VERITY_SIG] = "usr-other-verity-sig",
[PARTITION_TMP] = "tmp",
[PARTITION_VAR] = "var",
[PARTITION_USER_HOME] = "user-home",
@ -160,11 +81,7 @@ DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator);
static const char *const partition_mountpoint_table[] = {
[PARTITION_ROOT] = "/\0",
[PARTITION_ROOT_SECONDARY] = "/\0",
[PARTITION_ROOT_OTHER] = "/\0",
[PARTITION_USR] = "/usr\0",
[PARTITION_USR_SECONDARY] = "/usr\0",
[PARTITION_USR_OTHER] = "/usr\0",
[PARTITION_HOME] = "/home\0",
[PARTITION_SRV] = "/srv\0",
[PARTITION_ESP] = "/efi\0/boot\0",
@ -176,12 +93,12 @@ static const char *const partition_mountpoint_table[] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(partition_mountpoint, PartitionDesignator);
#define _GPT_ARCH_SEXTET(arch, name) \
{ SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER }, \
{ SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY }, \
{ SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY_SIG }, \
{ SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER }, \
{ SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY }, \
{ SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY_SIG }
{ SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .designator = PARTITION_ROOT }, \
{ SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_VERITY }, \
{ SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_VERITY_SIG }, \
{ SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .designator = PARTITION_USR }, \
{ SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_USR_VERITY }, \
{ SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_USR_VERITY_SIG }
const GptPartitionType gpt_partition_type_table[] = {
_GPT_ARCH_SEXTET(ALPHA, "alpha"),
@ -212,12 +129,12 @@ const GptPartitionType gpt_partition_type_table[] = {
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG },
#endif
#ifdef SD_GPT_ROOT_SECONDARY
{ SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT_SECONDARY },
{ SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY },
{ SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY_SIG },
{ SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR_SECONDARY },
{ SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY },
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY_SIG },
{ SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT },
{ SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_VERITY },
{ SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_VERITY_SIG },
{ SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR },
{ SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_VERITY },
{ SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG },
#endif
{ SD_GPT_ESP, "esp", _ARCHITECTURE_INVALID, .designator = PARTITION_ESP },
@ -266,17 +183,27 @@ const char *gpt_partition_type_uuid_to_string_harder(
return sd_id128_to_uuid_string(id, buffer);
}
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) {
int gpt_partition_type_from_string(const char *s, GptPartitionType *ret) {
sd_id128_t id;
int r;
assert(s);
for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
if (streq(s, gpt_partition_type_table[i].name)) {
if (ret)
*ret = gpt_partition_type_table[i].uuid;
*ret = gpt_partition_type_table[i];
return 0;
}
return sd_id128_from_string(s, ret);
r = sd_id128_from_string(s, &id);
if (r < 0)
return r;
if (ret)
*ret = gpt_partition_type_from_uuid(id);
return 0;
}
Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id) {
@ -299,7 +226,7 @@ int gpt_partition_label_valid(const char *s) {
return char16_strlen(recoded) <= GPT_LABEL_MAX;
}
static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
const GptPartitionType *pt;
pt = gpt_partition_type_find_by_uuid(id);
@ -313,91 +240,45 @@ static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
};
}
bool gpt_partition_type_is_root(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type) {
return partition_mountpoint_to_string(type.designator);
}
bool gpt_partition_type_knows_read_only(GptPartitionType type) {
return IN_SET(type.designator,
PARTITION_ROOT,
PARTITION_ROOT_SECONDARY,
PARTITION_ROOT_OTHER);
}
bool gpt_partition_type_is_root_verity(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_ROOT_VERITY,
PARTITION_ROOT_SECONDARY_VERITY,
PARTITION_ROOT_OTHER_VERITY);
}
bool gpt_partition_type_is_root_verity_sig(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_ROOT_VERITY_SIG,
PARTITION_ROOT_SECONDARY_VERITY_SIG,
PARTITION_ROOT_OTHER_VERITY_SIG);
}
bool gpt_partition_type_is_usr(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_USR,
PARTITION_USR_SECONDARY,
PARTITION_USR_OTHER);
}
bool gpt_partition_type_is_usr_verity(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
/* pretty much implied, but let's set the bit to make things really clear */
PARTITION_ROOT_VERITY,
PARTITION_USR_VERITY,
PARTITION_USR_SECONDARY_VERITY,
PARTITION_USR_OTHER_VERITY);
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR);
}
bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id) {
return IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_USR_VERITY_SIG,
PARTITION_USR_SECONDARY_VERITY_SIG,
PARTITION_USR_OTHER_VERITY_SIG);
bool gpt_partition_type_knows_growfs(GptPartitionType type) {
return IN_SET(type.designator,
PARTITION_ROOT,
PARTITION_USR,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR);
}
const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id) {
PartitionDesignator d = gpt_partition_type_from_uuid(id).designator;
if (d < 0)
return NULL;
return partition_mountpoint_to_string(d);
}
bool gpt_partition_type_knows_read_only(sd_id128_t id) {
return gpt_partition_type_is_root(id) ||
gpt_partition_type_is_usr(id) ||
/* pretty much implied, but let's set the bit to make things really clear */
gpt_partition_type_is_root_verity(id) ||
gpt_partition_type_is_usr_verity(id) ||
IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR);
}
bool gpt_partition_type_knows_growfs(sd_id128_t id) {
return gpt_partition_type_is_root(id) ||
gpt_partition_type_is_usr(id) ||
IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR);
}
bool gpt_partition_type_knows_no_auto(sd_id128_t id) {
return gpt_partition_type_is_root(id) ||
gpt_partition_type_is_root_verity(id) ||
gpt_partition_type_is_usr(id) ||
gpt_partition_type_is_usr_verity(id) ||
IN_SET(gpt_partition_type_from_uuid(id).designator,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR,
PARTITION_SWAP);
bool gpt_partition_type_knows_no_auto(GptPartitionType type) {
return IN_SET(type.designator,
PARTITION_ROOT,
PARTITION_ROOT_VERITY,
PARTITION_USR,
PARTITION_USR_VERITY,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_VAR,
PARTITION_TMP,
PARTITION_XBOOTLDR,
PARTITION_SWAP);
}

View File

@ -12,28 +12,16 @@
typedef enum PartitionDesignator {
PARTITION_ROOT, /* Primary architecture */
PARTITION_ROOT_SECONDARY, /* Secondary architecture */
PARTITION_ROOT_OTHER, /* Any architecture not covered by the primary or secondary architecture. */
PARTITION_USR,
PARTITION_USR_SECONDARY,
PARTITION_USR_OTHER,
PARTITION_HOME,
PARTITION_SRV,
PARTITION_ESP,
PARTITION_XBOOTLDR,
PARTITION_SWAP,
PARTITION_ROOT_VERITY, /* verity data for the PARTITION_ROOT partition */
PARTITION_ROOT_SECONDARY_VERITY, /* verity data for the PARTITION_ROOT_SECONDARY partition */
PARTITION_ROOT_OTHER_VERITY,
PARTITION_USR_VERITY,
PARTITION_USR_SECONDARY_VERITY,
PARTITION_USR_OTHER_VERITY,
PARTITION_ROOT_VERITY_SIG, /* PKCS#7 signature for root hash for the PARTITION_ROOT partition */
PARTITION_ROOT_SECONDARY_VERITY_SIG, /* ditto for the PARTITION_ROOT_SECONDARY partition */
PARTITION_ROOT_OTHER_VERITY_SIG,
PARTITION_USR_VERITY_SIG,
PARTITION_USR_SECONDARY_VERITY_SIG,
PARTITION_USR_OTHER_VERITY_SIG,
PARTITION_TMP,
PARTITION_VAR,
PARTITION_USER_HOME,
@ -46,8 +34,6 @@ bool partition_designator_is_versioned(PartitionDesignator d);
PartitionDesignator partition_verity_of(PartitionDesignator p);
PartitionDesignator partition_verity_sig_of(PartitionDesignator p);
PartitionDesignator partition_root_of_arch(Architecture arch);
PartitionDesignator partition_usr_of_arch(Architecture arch);
const char* partition_designator_to_string(PartitionDesignator d) _const_;
PartitionDesignator partition_designator_from_string(const char *name) _pure_;
@ -56,7 +42,6 @@ const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id,
char buffer[static SD_ID128_UUID_STRING_MAX]);
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret);
#define GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(id) \
gpt_partition_type_uuid_to_string_harder((id), (char[SD_ID128_UUID_STRING_MAX]) {})
@ -74,15 +59,11 @@ extern const GptPartitionType gpt_partition_type_table[];
int gpt_partition_label_valid(const char *s);
bool gpt_partition_type_is_root(sd_id128_t id);
bool gpt_partition_type_is_root_verity(sd_id128_t id);
bool gpt_partition_type_is_root_verity_sig(sd_id128_t id);
bool gpt_partition_type_is_usr(sd_id128_t id);
bool gpt_partition_type_is_usr_verity(sd_id128_t id);
bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id);
GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id);
int gpt_partition_type_from_string(const char *s, GptPartitionType *ret);
const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id);
const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type);
bool gpt_partition_type_knows_read_only(sd_id128_t id);
bool gpt_partition_type_knows_growfs(sd_id128_t id);
bool gpt_partition_type_knows_no_auto(sd_id128_t id);
bool gpt_partition_type_knows_read_only(GptPartitionType type);
bool gpt_partition_type_knows_growfs(GptPartitionType type);
bool gpt_partition_type_knows_no_auto(GptPartitionType type);

View File

@ -111,6 +111,7 @@ int read_partition_info(
struct fdisk_parttype *pt;
uint64_t start, size, flags;
sd_id128_t ptid, id;
GptPartitionType type;
size_t partno;
int r;
@ -178,6 +179,8 @@ int read_partition_info(
if (!label_copy)
return log_oom();
type = gpt_partition_type_from_uuid(ptid);
*ret = (PartitionInfo) {
.partno = partno,
.start = start,
@ -187,9 +190,9 @@ int read_partition_info(
.uuid = id,
.label = TAKE_PTR(label_copy),
.device = TAKE_PTR(device),
.no_auto = FLAGS_SET(flags, SD_GPT_FLAG_NO_AUTO) && gpt_partition_type_knows_no_auto(ptid),
.read_only = FLAGS_SET(flags, SD_GPT_FLAG_READ_ONLY) && gpt_partition_type_knows_read_only(ptid),
.growfs = FLAGS_SET(flags, SD_GPT_FLAG_GROWFS) && gpt_partition_type_knows_growfs(ptid),
.no_auto = FLAGS_SET(flags, SD_GPT_FLAG_NO_AUTO) && gpt_partition_type_knows_no_auto(type),
.read_only = FLAGS_SET(flags, SD_GPT_FLAG_READ_ONLY) && gpt_partition_type_knows_read_only(type),
.growfs = FLAGS_SET(flags, SD_GPT_FLAG_GROWFS) && gpt_partition_type_knows_growfs(type),
};
return 1; /* found! */
@ -269,6 +272,7 @@ int patch_partition(
_cleanup_(fdisk_unref_partitionp) struct fdisk_partition *pa = NULL;
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
bool tweak_no_auto, tweak_read_only, tweak_growfs;
GptPartitionType type;
int r, fd;
assert(device);
@ -313,16 +317,18 @@ int patch_partition(
return log_error_errno(r, "Failed to update partition UUID: %m");
}
type = gpt_partition_type_from_uuid(info->type);
/* Tweak the read-only flag, but only if supported by the partition type */
tweak_no_auto =
FLAGS_SET(change, PARTITION_NO_AUTO) &&
gpt_partition_type_knows_no_auto(info->type);
gpt_partition_type_knows_no_auto(type);
tweak_read_only =
FLAGS_SET(change, PARTITION_READ_ONLY) &&
gpt_partition_type_knows_read_only(info->type);
gpt_partition_type_knows_read_only(type);
tweak_growfs =
FLAGS_SET(change, PARTITION_GROWFS) &&
gpt_partition_type_knows_growfs(info->type);
gpt_partition_type_knows_growfs(type);
if (change & PARTITION_FLAGS) {
uint64_t flags;

View File

@ -194,7 +194,7 @@ static int resource_load_from_blockdev(Resource *rr) {
continue;
/* Check if partition type matches */
if (rr->partition_type_set && !sd_id128_equal(pinfo.type, rr->partition_type))
if (rr->partition_type_set && !sd_id128_equal(pinfo.type, rr->partition_type.uuid))
continue;
/* A label of "_empty" means "not used so far" for us */

View File

@ -5,8 +5,7 @@
#include <stdbool.h>
#include <sys/types.h>
#include "sd-id128.h"
#include "gpt.h"
#include "hashmap.h"
#include "macro.h"
@ -74,7 +73,7 @@ struct Resource {
char *path;
bool path_auto; /* automatically find root path (only available if target resource, not source resource) */
char **patterns;
sd_id128_t partition_type;
GptPartitionType partition_type;
bool partition_type_set;
/* All instances of this resource we found */

View File

@ -344,7 +344,7 @@ static int config_parse_resource_ptype(
assert(rvalue);
r = gpt_partition_type_uuid_from_string(rvalue, &rr->partition_type);
r = gpt_partition_type_from_string(rvalue, &rr->partition_type);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed parse partition type, ignoring: %s", rvalue);
@ -654,18 +654,18 @@ int transfer_vacuum(
if (t->target.n_empty + t->target.n_instances < 2)
return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
"Partition table has less than two partition slots of the right type " SD_ID128_UUID_FORMAT_STR " (%s), refusing.",
SD_ID128_FORMAT_VAL(t->target.partition_type),
gpt_partition_type_uuid_to_string(t->target.partition_type));
SD_ID128_FORMAT_VAL(t->target.partition_type.uuid),
gpt_partition_type_uuid_to_string(t->target.partition_type.uuid));
if (space > t->target.n_empty + t->target.n_instances)
return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
"Partition table does not have enough partition slots of right type " SD_ID128_UUID_FORMAT_STR " (%s) for operation.",
SD_ID128_FORMAT_VAL(t->target.partition_type),
gpt_partition_type_uuid_to_string(t->target.partition_type));
SD_ID128_FORMAT_VAL(t->target.partition_type.uuid),
gpt_partition_type_uuid_to_string(t->target.partition_type.uuid));
if (space == t->target.n_empty + t->target.n_instances)
return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
"Asked to empty all partition table slots of the right type " SD_ID128_UUID_FORMAT_STR " (%s), can't allow that. One instance must always remain.",
SD_ID128_FORMAT_VAL(t->target.partition_type),
gpt_partition_type_uuid_to_string(t->target.partition_type));
SD_ID128_FORMAT_VAL(t->target.partition_type.uuid),
gpt_partition_type_uuid_to_string(t->target.partition_type.uuid));
rm = LESS_BY(space, t->target.n_empty);
remain = LESS_BY(t->target.n_instances, rm);
@ -858,7 +858,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
r = find_suitable_partition(
t->target.path,
i->metadata.size,
t->target.partition_type_set ? &t->target.partition_type : NULL,
t->target.partition_type_set ? &t->target.partition_type.uuid : NULL,
&t->partition_info);
if (r < 0)
return r;

View File

@ -19,13 +19,13 @@ TEST(gpt_types_against_architectures) {
for (Architecture a = 0; a < _ARCHITECTURE_MAX; a++)
FOREACH_STRING(suffix, "", "-verity", "-verity-sig") {
_cleanup_free_ char *joined = NULL;
sd_id128_t id;
GptPartitionType type;
joined = strjoin(prefix, architecture_to_string(a), suffix);
if (!joined)
return (void) log_oom();
r = gpt_partition_type_uuid_from_string(joined, &id);
r = gpt_partition_type_from_string(joined, &type);
if (r < 0) {
printf("%s %s\n", RED_CROSS_MARK(), joined);
continue;
@ -34,15 +34,15 @@ TEST(gpt_types_against_architectures) {
printf("%s %s\n", GREEN_CHECK_MARK(), joined);
if (streq(prefix, "root-") && streq(suffix, ""))
assert_se(gpt_partition_type_is_root(id));
assert_se(type.designator == PARTITION_ROOT);
if (streq(prefix, "root-") && streq(suffix, "-verity"))
assert_se(gpt_partition_type_is_root_verity(id));
assert_se(type.designator == PARTITION_ROOT_VERITY);
if (streq(prefix, "usr-") && streq(suffix, ""))
assert_se(gpt_partition_type_is_usr(id));
assert_se(type.designator == PARTITION_USR);
if (streq(prefix, "usr-") && streq(suffix, "-verity"))
assert_se(gpt_partition_type_is_usr_verity(id));
assert_se(type.designator == PARTITION_USR_VERITY);
assert_se(gpt_partition_type_uuid_to_arch(id) == a);
assert_se(type.arch == a);
}
}

View File

@ -133,6 +133,40 @@ SizeMaxBytes=64M
PaddingMinBytes=92M
EOF
systemd-repart --definitions="$defs" \
--dry-run=no \
--seed="$seed" \
--include-partitions=home,swap \
"$imgs/zzz"
output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
assert_eq "$output" "label: gpt
label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
device: $imgs/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
systemd-repart --definitions="$defs" \
--dry-run=no \
--seed="$seed" \
--exclude-partitions=root \
"$imgs/zzz"
output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
assert_eq "$output" "label: gpt
label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
device: $imgs/zzz
unit: sectors
first-lba: 2048
last-lba: 2097118
$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
systemd-repart --definitions="$defs" \
--dry-run=no \
--seed="$seed" \