From: Krzesimir Nowak Date: Thu, 28 Mar 2024 14:15:45 +0000 (+0100) Subject: sysext: Make sure that merged hierarchy does not change its permissions X-Git-Tag: v256-rc1~86^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3de7ce7fe772415ba7853cc46e9063fde988df8d;p=thirdparty%2Fsystemd.git sysext: Make sure that merged hierarchy does not change its permissions The merged overlayfs filesystem mountpoint has a mode of its top layer. We have been creating all the directories to be used as layers with mode 0700, so the result was a merged hierarchy with such mode - it rendered the merged hierarchy to be accesible only by root. Change the mode of a directory serving as the top layer to match the hierarchy to avoid such situations. --- diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 44ee20f709e..07a9619bd12 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -725,6 +725,7 @@ static int work_dir_for_hierarchy( typedef struct OverlayFSPaths { char *hierarchy; + mode_t hierarchy_mode; char *resolved_hierarchy; char *resolved_mutable_directory; @@ -822,6 +823,8 @@ static int resolve_mutable_directory( static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path, OverlayFSPaths **ret_op) { _cleanup_free_ char *hierarchy_copy = NULL, *resolved_hierarchy = NULL, *resolved_mutable_directory = NULL; + mode_t hierarchy_mode; + int r; assert (hierarchy); @@ -834,6 +837,16 @@ static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path r = resolve_hierarchy(hierarchy, &resolved_hierarchy); if (r < 0) return r; + + if (resolved_hierarchy) { + struct stat st; + + if (stat(resolved_hierarchy, &st) < 0) + return log_error_errno(errno, "Failed to stat '%s': %m", resolved_hierarchy); + hierarchy_mode = st.st_mode & 0777; + } else + hierarchy_mode = 0755; + r = resolve_mutable_directory(hierarchy, workspace_path, &resolved_mutable_directory); if (r < 0) return r; @@ -845,6 +858,7 @@ static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path *op = (OverlayFSPaths) { .hierarchy = TAKE_PTR(hierarchy_copy), + .hierarchy_mode = hierarchy_mode, .resolved_hierarchy = TAKE_PTR(resolved_hierarchy), .resolved_mutable_directory = TAKE_PTR(resolved_mutable_directory), }; @@ -1137,6 +1151,7 @@ static int mount_overlayfs_with_op( const char *meta_path) { int r; + const char* top_layer = NULL; assert(op); assert(overlay_path); @@ -1153,8 +1168,19 @@ static int mount_overlayfs_with_op( r = mkdir_p(op->work_dir, 0700); if (r < 0) return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir); + top_layer = op->upper_dir; + } else { + assert(!strv_isempty(op->lower_dirs)); + top_layer = op->lower_dirs[0]; } + /* Overlayfs merged directory has the same mode as the top layer (either first lowerdir in options in + * read-only case, or upperdir for mutable case. Set up top overlayfs layer to the same mode as the + * unmerged hierarchy, otherwise we might end up with merged hierarchy owned by root and with mode + * being 0700. */ + if (chmod(top_layer, op->hierarchy_mode) < 0) + return log_error_errno(errno, "Failed to set permissions of '%s' to %04o: %m", top_layer, op->hierarchy_mode); + r = mount_overlayfs(image_class, noexec, overlay_path, op->lower_dirs, op->upper_dir, op->work_dir); if (r < 0) return r;