core: change mount options settings so that last defined wins
Currently mount options are handled in such a way that the first definition for a given partition wins, and documented as such. Change them so that they behave like other options, and the last specified wins. Applies to RootImageOptions=, MountImages= and ExtensionImages=. Switch from a linked list to an array indexed by the partition specifier to store them.
This commit is contained in:
+91
-176
@@ -1547,6 +1547,77 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serialize_mount_options(const MountOptions *mount_options, char **s) {
|
||||
assert(s);
|
||||
|
||||
if (!mount_options)
|
||||
return 0;
|
||||
|
||||
for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
if (isempty(mount_options->options[i]))
|
||||
continue;
|
||||
|
||||
escaped = shell_escape(mount_options->options[i], ":");
|
||||
if (!escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(s,
|
||||
" ",
|
||||
partition_designator_to_string(i),
|
||||
":",
|
||||
escaped))
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int deserialize_mount_options(const char *s, MountOptions **ret_mount_options) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret_mount_options);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL, *mount_options = NULL, *partition = NULL;
|
||||
PartitionDesignator partition_designator;
|
||||
const char *p;
|
||||
|
||||
r = extract_first_word(&s, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
p = word;
|
||||
r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
if (r != 2) {
|
||||
log_warning("Failed to parse mount options entry '%s', ignoring.", word);
|
||||
continue;
|
||||
}
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0) {
|
||||
log_warning_errno(partition_designator, "Unknown partition designator '%s' in exec-context-root-image-options= entry, ignoring.", partition);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = mount_options_set_and_consume(&options, partition_designator, TAKE_PTR(mount_options));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret_mount_options = TAKE_PTR(options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
int r;
|
||||
|
||||
@@ -1594,22 +1665,9 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
if (c->root_image_options) {
|
||||
_cleanup_free_ char *options = NULL;
|
||||
|
||||
LIST_FOREACH(mount_options, o, c->root_image_options) {
|
||||
if (isempty(o->options))
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
escaped = shell_escape(o->options, ":");
|
||||
if (!escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&options,
|
||||
" ",
|
||||
partition_designator_to_string(o->partition_designator),
|
||||
":",
|
||||
escaped))
|
||||
return log_oom_debug();
|
||||
}
|
||||
r = serialize_mount_options(c->root_image_options, &options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_item(f, "exec-context-root-image-options", options);
|
||||
if (r < 0)
|
||||
@@ -2398,23 +2456,9 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
if (!s)
|
||||
return log_oom_debug();
|
||||
|
||||
LIST_FOREACH(mount_options, o, mount->mount_options) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
if (isempty(o->options))
|
||||
continue;
|
||||
|
||||
escaped = shell_escape(o->options, ":");
|
||||
if (!escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&s,
|
||||
" ",
|
||||
partition_designator_to_string(o->partition_designator),
|
||||
":",
|
||||
escaped))
|
||||
return log_oom_debug();
|
||||
}
|
||||
r = serialize_mount_options(mount->mount_options, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_item(f, "exec-context-mount-image", s);
|
||||
if (r < 0)
|
||||
@@ -2433,23 +2477,9 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
if (!s)
|
||||
return log_oom_debug();
|
||||
|
||||
LIST_FOREACH(mount_options, o, mount->mount_options) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
if (isempty(o->options))
|
||||
continue;
|
||||
|
||||
escaped = shell_escape(o->options, ":");
|
||||
if (!escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&s,
|
||||
" ",
|
||||
partition_designator_to_string(o->partition_designator),
|
||||
":",
|
||||
escaped))
|
||||
return log_oom_debug();
|
||||
}
|
||||
r = serialize_mount_options(mount->mount_options, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = serialize_item(f, "exec-context-extension-image", s);
|
||||
if (r < 0)
|
||||
@@ -2565,38 +2595,13 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
return k;
|
||||
free_and_replace(c->root_image, p);
|
||||
} else if ((val = startswith(l, "exec-context-root-image-options="))) {
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL, *mount_options = NULL, *partition = NULL;
|
||||
PartitionDesignator partition_designator;
|
||||
MountOptions *o = NULL;
|
||||
const char *p;
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
|
||||
r = extract_first_word(&val, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
r = deserialize_mount_options(val, &options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = word;
|
||||
r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0)
|
||||
return -EINVAL;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom_debug();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = partition_designator,
|
||||
.options = TAKE_PTR(mount_options),
|
||||
};
|
||||
LIST_APPEND(mount_options, c->root_image_options, o);
|
||||
}
|
||||
free_and_replace_full(c->root_image_options, options, mount_options_free_all);
|
||||
} else if ((val = startswith(l, "exec-context-root-verity="))) {
|
||||
r = free_and_strdup(&c->root_verity, val);
|
||||
if (r < 0)
|
||||
@@ -3538,54 +3543,9 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
if (isempty(destination))
|
||||
continue;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *tuple = NULL, *partition = NULL, *opts = NULL;
|
||||
PartitionDesignator partition_designator;
|
||||
MountOptions *o = NULL;
|
||||
const char *p;
|
||||
|
||||
r = extract_first_word(&val, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
p = tuple;
|
||||
r = extract_many_words(&p,
|
||||
":",
|
||||
EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS,
|
||||
&partition,
|
||||
&opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
if (r == 1) {
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom_debug();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = PARTITION_ROOT,
|
||||
.options = TAKE_PTR(partition),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0)
|
||||
continue;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom_debug();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = partition_designator,
|
||||
.options = TAKE_PTR(opts),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
}
|
||||
r = deserialize_mount_options(val, &options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_image_add(&c->mount_images, &c->n_mount_images,
|
||||
&(MountImage) {
|
||||
@@ -3618,54 +3578,9 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
s++;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *tuple = NULL, *partition = NULL, *opts = NULL;
|
||||
PartitionDesignator partition_designator;
|
||||
MountOptions *o = NULL;
|
||||
const char *p;
|
||||
|
||||
r = extract_first_word(&val, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
p = tuple;
|
||||
r = extract_many_words(&p,
|
||||
":",
|
||||
EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS,
|
||||
&partition,
|
||||
&opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
if (r == 1) {
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom_debug();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = PARTITION_ROOT,
|
||||
.options = TAKE_PTR(partition),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0)
|
||||
continue;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom_debug();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = partition_designator,
|
||||
.options = TAKE_PTR(opts),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
}
|
||||
r = deserialize_mount_options(val, &options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_image_add(&c->extension_images, &c->n_extension_images,
|
||||
&(MountImage) {
|
||||
|
||||
Reference in New Issue
Block a user