]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: execute merge even if no extensions are installed as long as --mutable= is on
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Mar 2025 13:22:54 +0000 (14:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2025 09:27:51 +0000 (10:27 +0100)
This way we can make an immutable OS mutable, without any extensions or
so.

Fixes: #34445
src/sysext/sysext.c

index 92c60c49ae28b11940c17c8b0c01f64007921a57..dec0becda03bad385b14d457a9c97d3cecbd73f9 100644 (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);