]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: Check if preexisting mutable directory has a valid mode
authorKrzesimir Nowak <knowak@microsoft.com>
Thu, 28 Mar 2024 14:21:08 +0000 (15:21 +0100)
committerKrzesimir Nowak <knowak@microsoft.com>
Fri, 19 Apr 2024 05:18:34 +0000 (07:18 +0200)
Preexisting mutable directory is likely set by the admin, so we expect it to be
set up properly instead of changing the mode of the directory behind admin's
back.

src/sysext/sysext.c

index 07a9619bd12a4f6fb6882b7fc1a223f59a004560..47ba78ab3a6e0d90ba39c53975bdeaf86ca9705e 100644 (file)
@@ -768,8 +768,37 @@ static int resolve_hierarchy(const char *hierarchy, char **ret_resolved_hierarch
         return 0;
 }
 
+static int mutable_directory_mode_matches_hierarchy(
+                const char *root_or_null,
+                const char *path,
+                mode_t hierarchy_mode) {
+
+        _cleanup_free_ char *path_in_root = NULL;
+        struct stat st;
+        mode_t actual_mode;
+
+        assert(path);
+
+        path_in_root = path_join(root_or_null, path);
+        if (!path_in_root)
+                return log_oom();
+
+        if (stat(path_in_root, &st) < 0) {
+                if (errno == ENOENT)
+                        return 0;
+                return log_error_errno(errno, "Failed to stat mutable directory '%s': %m", path_in_root);
+        }
+
+        actual_mode = st.st_mode & 0777;
+        if (actual_mode != hierarchy_mode)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Mutable directory '%s' has mode %04o, ought to have mode %04o", path_in_root, actual_mode, hierarchy_mode);
+
+        return 0;
+}
+
 static int resolve_mutable_directory(
                 const char *hierarchy,
+                mode_t hierarchy_mode,
                 const char *workspace,
                 char **ret_resolved_mutable_directory) {
 
@@ -801,6 +830,15 @@ static int resolve_mutable_directory(
         if (!path)
                 return log_oom();
 
+        if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_AUTO)) {
+                /* If there already is a mutable directory, check if its mode matches hierarchy. Merged
+                 * hierarchy will have the same mode as the mutable directory, so we want no surprising mode
+                 * changes here. */
+                r = mutable_directory_mode_matches_hierarchy(root, path, hierarchy_mode);
+                if (r < 0)
+                        return r;
+        }
+
         if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT)) {
                 _cleanup_free_ char *path_in_root = NULL;
 
@@ -847,7 +885,7 @@ static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path
         } else
                 hierarchy_mode = 0755;
 
-        r = resolve_mutable_directory(hierarchy, workspace_path, &resolved_mutable_directory);
+        r = resolve_mutable_directory(hierarchy, hierarchy_mode, workspace_path, &resolved_mutable_directory);
         if (r < 0)
                 return r;