Merge pull request #16686 from bluca/mount_images_opts
core: add mount options support for MountImages
This commit is contained in:
+133
-41
@@ -802,12 +802,14 @@ static int property_get_root_image_options(
|
||||
assert(property);
|
||||
assert(reply);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(us)");
|
||||
r = sd_bus_message_open_container(reply, 'a', "(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(mount_options, m, c->root_image_options) {
|
||||
r = sd_bus_message_append(reply, "(us)", m->partition_number, m->options);
|
||||
r = sd_bus_message_append(reply, "(ss)",
|
||||
partition_designator_to_string(m->partition_designator),
|
||||
m->options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -832,18 +834,39 @@ static int property_get_mount_images(
|
||||
assert(property);
|
||||
assert(reply);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(ssb)");
|
||||
r = sd_bus_message_open_container(reply, 'a', "(ssba(ss))");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (size_t i = 0; i < c->n_mount_images; i++) {
|
||||
MountOptions *m;
|
||||
|
||||
r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "ssba(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_append(
|
||||
reply, "(ssb)",
|
||||
reply, "ssb",
|
||||
c->mount_images[i].source,
|
||||
c->mount_images[i].destination,
|
||||
c->mount_images[i].ignore_enoent);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_open_container(reply, 'a', "(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
LIST_FOREACH(mount_options, m, c->mount_images[i].mount_options) {
|
||||
r = sd_bus_message_append(reply, "(ss)",
|
||||
partition_designator_to_string(m->partition_designator),
|
||||
m->options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = sd_bus_message_close_container(reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_close_container(reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
@@ -891,13 +914,13 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootImageOptions", "a(us)", property_get_root_image_options, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootImageOptions", "a(ss)", property_get_root_image_options, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL, offsetof(ExecContext, root_hash_sig_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MountImages", "a(ssb)", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MountImages", "a(ssba(ss))", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1338,6 +1361,74 @@ static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint6
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
|
||||
|
||||
/* ret_format_str is an accumulator, so if it has any pre-existing content, new options will be appended to it */
|
||||
static int read_mount_options(sd_bus_message *message, sd_bus_error *error, MountOptions **ret_options, char **ret_format_str, const char *separator) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
_cleanup_free_ char *format_str = NULL;
|
||||
const char *mount_options, *partition;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(ret_options);
|
||||
assert(ret_format_str);
|
||||
assert(separator);
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) {
|
||||
_cleanup_free_ char *previous = NULL, *escaped = NULL;
|
||||
_cleanup_free_ MountOptions *o = NULL;
|
||||
int partition_designator;
|
||||
|
||||
if (chars_intersect(mount_options, WHITESPACE))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid mount options string, contains whitespace character(s): %s", mount_options);
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid partition name %s", partition);
|
||||
|
||||
/* Need to store them in the unit with the escapes, so that they can be parsed again */
|
||||
escaped = shell_escape(mount_options, ":");
|
||||
if (!escaped)
|
||||
return -ENOMEM;
|
||||
|
||||
previous = TAKE_PTR(format_str);
|
||||
format_str = strjoin(previous, previous ? separator : "", partition, ":", escaped);
|
||||
if (!format_str)
|
||||
return -ENOMEM;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return -ENOMEM;
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = partition_designator,
|
||||
.options = strdup(mount_options),
|
||||
};
|
||||
if (!o->options)
|
||||
return -ENOMEM;
|
||||
LIST_APPEND(mount_options, options, TAKE_PTR(o));
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!LIST_IS_EMPTY(options)) {
|
||||
char *final = strjoin(*ret_format_str, !isempty(*ret_format_str) ? separator : "", format_str);
|
||||
if (!final)
|
||||
return -ENOMEM;
|
||||
free_and_replace(*ret_format_str, final);
|
||||
LIST_JOIN(mount_options, *ret_options, options);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_exec_context_set_transient_property(
|
||||
Unit *u,
|
||||
ExecContext *c,
|
||||
@@ -1371,39 +1462,8 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "RootImageOptions")) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
_cleanup_free_ char *format_str = NULL;
|
||||
const char *mount_options;
|
||||
unsigned partition_number;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(us)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(us)", &partition_number, &mount_options)) > 0) {
|
||||
_cleanup_free_ char *previous = TAKE_PTR(format_str);
|
||||
_cleanup_free_ MountOptions *o = NULL;
|
||||
|
||||
if (chars_intersect(mount_options, WHITESPACE))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid mount options string, contains whitespace character(s): %s", mount_options);
|
||||
|
||||
if (asprintf(&format_str, "%s%s%u:%s", strempty(previous), previous ? " " : "", partition_number, mount_options) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return -ENOMEM;
|
||||
*o = (MountOptions) {
|
||||
.partition_number = partition_number,
|
||||
.options = strdup(mount_options),
|
||||
};
|
||||
if (!o->options)
|
||||
return -ENOMEM;
|
||||
LIST_APPEND(mount_options, options, TAKE_PTR(o));
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
r = read_mount_options(message, error, &options, &format_str, " ");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2938,13 +2998,23 @@ int bus_exec_context_set_transient_property(
|
||||
char *source, *destination;
|
||||
int permissive;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ssb)");
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ssba(ss))");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ssb)", &source, &destination, &permissive)) > 0) {
|
||||
for (;;) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
_cleanup_free_ char *source_escaped = NULL, *destination_escaped = NULL;
|
||||
char *tuple;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'r', "ssba(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_read(message, "ssb", &source, &destination, &permissive);
|
||||
if (r <= 0)
|
||||
break;
|
||||
|
||||
if (!path_is_absolute(source))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
|
||||
if (!path_is_normalized(source))
|
||||
@@ -2954,15 +3024,37 @@ int bus_exec_context_set_transient_property(
|
||||
if (!path_is_normalized(destination))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination);
|
||||
|
||||
tuple = strjoin(format_str, format_str ? " " : "", permissive ? "-" : "", source, ":", destination);
|
||||
/* Need to store them in the unit with the escapes, so that they can be parsed again */
|
||||
source_escaped = shell_escape(source, ":");
|
||||
if (!source_escaped)
|
||||
return -ENOMEM;
|
||||
destination_escaped = shell_escape(destination, ":");
|
||||
if (!destination_escaped)
|
||||
return -ENOMEM;
|
||||
|
||||
tuple = strjoin(format_str,
|
||||
format_str ? " " : "",
|
||||
permissive ? "-" : "",
|
||||
source_escaped,
|
||||
":",
|
||||
destination_escaped);
|
||||
if (!tuple)
|
||||
return -ENOMEM;
|
||||
free_and_replace(format_str, tuple);
|
||||
|
||||
r = read_mount_options(message, error, &options, &format_str, ":");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_image_add(&mount_images, &n_mount_images,
|
||||
&(MountImage) {
|
||||
.source = source,
|
||||
.destination = destination,
|
||||
.mount_options = options,
|
||||
.ignore_enoent = permissive,
|
||||
});
|
||||
if (r < 0)
|
||||
|
||||
+15
-4
@@ -4634,7 +4634,9 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
fprintf(f, "%sRootImageOptions:", prefix);
|
||||
LIST_FOREACH(mount_options, o, c->root_image_options)
|
||||
if (!isempty(o->options))
|
||||
fprintf(f, " %u:%s", o->partition_number, o->options);
|
||||
fprintf(f, " %s:%s",
|
||||
partition_designator_to_string(o->partition_designator),
|
||||
o->options);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
@@ -5035,11 +5037,20 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
fprintf(f, "%d\n", c->syscall_errno);
|
||||
}
|
||||
|
||||
for (i = 0; i < c->n_mount_images; i++)
|
||||
fprintf(f, "%sMountImages: %s%s:%s\n", prefix,
|
||||
for (i = 0; i < c->n_mount_images; i++) {
|
||||
MountOptions *o;
|
||||
|
||||
fprintf(f, "%sMountImages: %s%s:%s%s", prefix,
|
||||
c->mount_images[i].ignore_enoent ? "-": "",
|
||||
c->mount_images[i].source,
|
||||
c->mount_images[i].destination);
|
||||
c->mount_images[i].destination,
|
||||
LIST_IS_EMPTY(c->mount_images[i].mount_options) ? "": ":");
|
||||
LIST_FOREACH(mount_options, o, c->mount_images[i].mount_options)
|
||||
fprintf(f, "%s:%s",
|
||||
partition_designator_to_string(o->partition_designator),
|
||||
o->options);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool exec_context_maintains_privileges(const ExecContext *c) {
|
||||
|
||||
+101
-53
@@ -1429,9 +1429,10 @@ int config_parse_root_image_options(
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **first = NULL, **second = NULL;
|
||||
ExecContext *c = data;
|
||||
const Unit *u = userdata;
|
||||
const char *p = rvalue;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
@@ -1444,44 +1445,32 @@ int config_parse_root_image_options(
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *mount_options_resolved = NULL, *first = NULL, *tuple = NULL;
|
||||
const char *mount_options = NULL, *second = NULL;
|
||||
r = strv_split_colon_pairs(&l, rvalue);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH_PAIR(first, second, l) {
|
||||
MountOptions *o = NULL;
|
||||
unsigned int partition_number = 0;
|
||||
_cleanup_free_ char *mount_options_resolved = NULL;
|
||||
const char *mount_options = NULL, *partition = "root";
|
||||
int partition_designator;
|
||||
|
||||
r = extract_first_word(&p, &tuple, WHITESPACE, EXTRACT_UNQUOTE);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
second = tuple;
|
||||
r = extract_first_word(&second, &first, ":", EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r == 0)
|
||||
continue;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Format is either '0:foo' or 'foo' (0 is implied) */
|
||||
if (!isempty(second) && second[-1] == ':') {
|
||||
mount_options = second;
|
||||
r = safe_atou(first, &partition_number);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition number from \"%s\", ignoring: %m", first);
|
||||
continue;
|
||||
}
|
||||
/* Format is either 'root:foo' or 'foo' (root is implied) */
|
||||
if (!isempty(*second)) {
|
||||
partition = *first;
|
||||
mount_options = *second;
|
||||
} else
|
||||
mount_options = first;
|
||||
mount_options = *first;
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Invalid partition name %s, ignoring", partition);
|
||||
continue;
|
||||
}
|
||||
r = unit_full_printf(u, mount_options, &mount_options_resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", mount_options);
|
||||
@@ -1492,10 +1481,10 @@ int config_parse_root_image_options(
|
||||
if (!o)
|
||||
return log_oom();
|
||||
*o = (MountOptions) {
|
||||
.partition_number = partition_number,
|
||||
.partition_designator = partition_designator,
|
||||
.options = TAKE_PTR(mount_options_resolved),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
LIST_APPEND(mount_options, options, TAKE_PTR(o));
|
||||
}
|
||||
|
||||
/* empty spaces/separators only */
|
||||
@@ -4633,10 +4622,9 @@ int config_parse_mount_images(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
ExecContext *c = data;
|
||||
const Unit *u = userdata;
|
||||
char **source = NULL, **destination = NULL;
|
||||
const char *p = rvalue;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
@@ -4650,23 +4638,31 @@ int config_parse_mount_images(
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = strv_split_colon_pairs(&l, rvalue);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH_PAIR(source, destination, l) {
|
||||
for (;;) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
_cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL;
|
||||
_cleanup_free_ char *sresolved = NULL, *dresolved = NULL;
|
||||
const char *q = NULL;
|
||||
char *s = NULL;
|
||||
bool permissive = false;
|
||||
|
||||
r = unit_full_printf(u, *source, &sresolved);
|
||||
r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
q = tuple;
|
||||
r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = unit_full_printf(u, first, &sresolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", *source);
|
||||
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", first);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4680,15 +4676,15 @@ int config_parse_mount_images(
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
if (isempty(*destination)) {
|
||||
if (isempty(second)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Missing destination in %s, ignoring: %s", lvalue, rvalue);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = unit_full_printf(u, *destination, &dresolved);
|
||||
r = unit_full_printf(u, second, &dresolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to resolve specifiers in \"%s\", ignoring: %m", *destination);
|
||||
"Failed to resolve specifiers in \"%s\", ignoring: %m", second);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4696,10 +4692,62 @@ int config_parse_mount_images(
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *partition = NULL, *mount_options = NULL, *mount_options_resolved = NULL;
|
||||
MountOptions *o = NULL;
|
||||
int partition_designator;
|
||||
|
||||
r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
/* Single set of options, applying to the root partition/single filesystem */
|
||||
if (r == 1) {
|
||||
r = unit_full_printf(u, partition, &mount_options_resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", first);
|
||||
continue;
|
||||
}
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = PARTITION_ROOT,
|
||||
.options = TAKE_PTR(mount_options_resolved),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
partition_designator = partition_designator_from_string(partition);
|
||||
if (partition_designator < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Invalid partition name %s, ignoring", partition);
|
||||
continue;
|
||||
}
|
||||
r = unit_full_printf(u, mount_options, &mount_options_resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", mount_options);
|
||||
continue;
|
||||
}
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return log_oom();
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = partition_designator,
|
||||
.options = TAKE_PTR(mount_options_resolved),
|
||||
};
|
||||
LIST_APPEND(mount_options, options, o);
|
||||
}
|
||||
|
||||
r = mount_image_add(&c->mount_images, &c->n_mount_images,
|
||||
&(MountImage) {
|
||||
.source = s,
|
||||
.destination = dresolved,
|
||||
.mount_options = options,
|
||||
.ignore_enoent = permissive,
|
||||
});
|
||||
if (r < 0)
|
||||
|
||||
+26
-3
@@ -73,7 +73,7 @@ typedef struct MountEntry {
|
||||
char *options_malloc;
|
||||
unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */
|
||||
unsigned n_followed;
|
||||
LIST_FIELDS(MountEntry, mount_entry);
|
||||
LIST_HEAD(MountOptions, image_options);
|
||||
} MountEntry;
|
||||
|
||||
/* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted
|
||||
@@ -247,6 +247,7 @@ static void mount_entry_done(MountEntry *p) {
|
||||
p->path_malloc = mfree(p->path_malloc);
|
||||
p->source_malloc = mfree(p->source_malloc);
|
||||
p->options_malloc = mfree(p->options_malloc);
|
||||
p->image_options = mount_options_free_all(p->image_options);
|
||||
}
|
||||
|
||||
static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, bool forcibly_require_prefix) {
|
||||
@@ -339,6 +340,7 @@ static int append_mount_images(MountEntry **p, const MountImage *mount_images, s
|
||||
.path_const = m->destination,
|
||||
.mode = MOUNT_IMAGES,
|
||||
.source_const = m->source,
|
||||
.image_options = m->mount_options,
|
||||
.ignore = m->ignore_enoent,
|
||||
};
|
||||
}
|
||||
@@ -925,10 +927,10 @@ static int mount_images(const MountEntry *m) {
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create loop device for image: %m");
|
||||
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, NULL, dissect_image_flags, &dissected_image);
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags, &dissected_image);
|
||||
/* No partition table? Might be a single-filesystem image, try again */
|
||||
if (!verity_data && r < 0 && r == -ENOPKG)
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, NULL, dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE, &dissected_image);
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE, &dissected_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to dissect image: %m");
|
||||
|
||||
@@ -1838,6 +1840,7 @@ MountImage* mount_image_free_many(MountImage *m, size_t *n) {
|
||||
for (i = 0; i < *n; i++) {
|
||||
free(m[i].source);
|
||||
free(m[i].destination);
|
||||
mount_options_free_all(m[i].mount_options);
|
||||
}
|
||||
|
||||
free(m);
|
||||
@@ -1847,6 +1850,8 @@ MountImage* mount_image_free_many(MountImage *m, size_t *n) {
|
||||
|
||||
int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
|
||||
_cleanup_free_ char *s = NULL, *d = NULL;
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
MountOptions *i;
|
||||
MountImage *c;
|
||||
|
||||
assert(m);
|
||||
@@ -1861,6 +1866,23 @@ int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
LIST_FOREACH(mount_options, i, item->mount_options) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *o;
|
||||
|
||||
o = new(MountOptions, 1);
|
||||
if (!o)
|
||||
return -ENOMEM;
|
||||
|
||||
*o = (MountOptions) {
|
||||
.partition_designator = i->partition_designator,
|
||||
.options = strdup(i->options),
|
||||
};
|
||||
if (!o->options)
|
||||
return -ENOMEM;
|
||||
|
||||
LIST_APPEND(mount_options, options, TAKE_PTR(o));
|
||||
}
|
||||
|
||||
c = reallocarray(*m, *n + 1, sizeof(MountImage));
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
@@ -1870,6 +1892,7 @@ int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
|
||||
c[(*n) ++] = (MountImage) {
|
||||
.source = TAKE_PTR(s),
|
||||
.destination = TAKE_PTR(d),
|
||||
.mount_options = TAKE_PTR(options),
|
||||
.ignore_enoent = item->ignore_enoent,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ typedef struct NamespaceInfo NamespaceInfo;
|
||||
typedef struct BindMount BindMount;
|
||||
typedef struct TemporaryFileSystem TemporaryFileSystem;
|
||||
typedef struct MountImage MountImage;
|
||||
typedef struct MountEntry MountEntry;
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -77,6 +76,7 @@ struct TemporaryFileSystem {
|
||||
struct MountImage {
|
||||
char *source;
|
||||
char *destination;
|
||||
LIST_HEAD(MountOptions, mount_options);
|
||||
bool ignore_enoent;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user