summaryrefslogtreecommitdiffstats
path: root/src/sysext/sysext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sysext/sysext.c')
-rw-r--r--src/sysext/sysext.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index 07a9619bd1..47ba78ab3a 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -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;