From: Lennart Poettering Date: Wed, 5 Mar 2025 13:22:54 +0000 (+0100) Subject: sysext: execute merge even if no extensions are installed as long as --mutable= is on X-Git-Tag: v258-rc1~1164^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42c589eae530f04ce41cbf1ce721dc1405509d03;p=thirdparty%2Fsystemd.git 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 --- diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 92c60c49ae2..dec0becda03 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -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);