sysext: execute merge even if no extensions are installed as long as --mutable= is on

This way we can make an immutable OS mutable, without any extensions or
so.

Fixes: #34445
This commit is contained in:
Lennart Poettering
2025-03-05 14:22:54 +01:00
parent c0af4859d0
commit 42c589eae5

View File

@@ -1045,7 +1045,7 @@ static int determine_used_extensions(const char *hierarchy, char **paths, char *
continue;
}
r = strv_consume_with_size (&used_paths, &n, TAKE_PTR(resolved));
r = strv_consume_with_size(&used_paths, &n, TAKE_PTR(resolved));
if (r < 0)
return log_oom();
}
@@ -1143,15 +1143,11 @@ static int determine_top_lower_dirs(OverlayFSPaths *op, const char *meta_path) {
}
static int determine_middle_lower_dirs(OverlayFSPaths *op, char **paths) {
int r;
assert(op);
assert(paths);
/* The paths were already determined in determine_used_extensions, so we just take them as is. */
r = strv_extend_strv(&op->lower_dirs, paths, false);
if (r < 0)
return log_oom ();
if (strv_extend_strv(&op->lower_dirs, paths, /* filter_duplicates= */ false) < 0)
return log_oom();
return 0;
}
@@ -1227,7 +1223,6 @@ static int determine_lower_dirs(
int r;
assert(op);
assert(paths);
assert(meta_path);
r = determine_top_lower_dirs(op, meta_path);
@@ -1363,7 +1358,6 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons
_cleanup_free_ char *f = NULL, *buf = NULL;
int r;
assert(extensions);
assert(meta_path);
/* Let's generate a metadata file that lists all extensions we took into account for this
@@ -1373,15 +1367,20 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons
if (!f)
return log_oom();
buf = strv_join(extensions, "\n");
if (!buf)
return log_oom();
if (!strv_isempty(extensions)) {
buf = strv_join(extensions, "\n");
if (!buf)
return log_oom();
if (!strextend(&buf, "\n")) /* manually append newline since we want to suppress newline if zero extensions are applied */
return log_oom();
}
_cleanup_free_ char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
if (!hierarchy_path)
return log_oom();
r = write_string_file_full(AT_FDCWD,f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL, /* ts= */ NULL, hierarchy_path);
r = write_string_file_full(AT_FDCWD, f, strempty(buf), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_AVOID_NEWLINE, /* ts= */ NULL, hierarchy_path);
if (r < 0)
return log_error_errno(r, "Failed to write extension meta file '%s': %m", f);
@@ -1470,7 +1469,6 @@ static int store_info_in_meta(
int r;
assert(extensions);
assert(meta_path);
assert(overlay_path);
/* work_dir may be NULL */
@@ -1559,7 +1557,6 @@ static int merge_hierarchy(
int r;
assert(hierarchy);
assert(extensions);
assert(paths);
assert(meta_path);
assert(overlay_path);
@@ -1571,7 +1568,7 @@ static int merge_hierarchy(
if (r < 0)
return r;
if (extensions_used == 0) /* No extension with files in this hierarchy? Then don't do anything. */
if (extensions_used == 0 && arg_mutable == MUTABLE_NO) /* No extension with files in this hierarchy? Then don't do anything. */
return 0;
r = overlayfs_paths_new(hierarchy, workspace_path, &op);
@@ -1644,7 +1641,7 @@ static int merge_subprocess(
Hashmap *images,
const char *workspace) {
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_api_level = NULL, *buf = NULL, *filename = NULL;
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_api_level = NULL, *filename = NULL;
_cleanup_strv_free_ char **extensions = NULL, **extensions_v = NULL, **paths = NULL;
size_t n_extensions = 0;
unsigned n_ignored = 0;
@@ -1843,7 +1840,7 @@ static int merge_subprocess(
}
/* Nothing left? Then shortcut things */
if (n_extensions == 0) {
if (n_extensions == 0 && arg_mutable == MUTABLE_NO) {
if (n_ignored > 0)
log_info("No suitable extensions found (%u ignored due to incompatible image(s)).", n_ignored);
else
@@ -1855,11 +1852,16 @@ static int merge_subprocess(
typesafe_qsort(extensions, n_extensions, strverscmp_improvedp);
typesafe_qsort(extensions_v, n_extensions, strverscmp_improvedp);
buf = strv_join(extensions_v, "', '");
if (!buf)
return log_oom();
if (n_extensions == 0) {
assert(arg_mutable != MUTABLE_NO);
log_info("No extensions found, proceeding in mutable mode.");
} else {
_cleanup_free_ char *buf = strv_join(extensions_v, "', '");
if (!buf)
return log_oom();
log_info("Using extensions '%s'.", buf);
log_info("Using extensions '%s'.", buf);
}
/* Build table of extension paths (in reverse order) */
paths = new0(char*, n_extensions + 1);