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.
This commit is contained in:
Krzesimir Nowak
2024-04-19 07:15:01 +02:00
parent cb409e9074
commit 3de7ce7fe7
+26
View File
@@ -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;