Skip to content

[SECURITY ISSUE] Directory permissions permanently widened to 0755 during copy-up in create_node_directory() #470

Description

@zeon-nf

A flaw was identified in the copy-up logic within copyup.rs. When a directory originating from a lower layer with restrictive permissions (e.g., 0700) undergoes a copy-up operation (for example, when a file is created inside it or an attribute is changed), its permissions are permanently widened in the upper layer without being restored to their original state.

This introduces a confidentiality vulnerability/information disclosure regression. In multi-tenant environments or rootless container scenarios (e.g., Podman/Buildah sharing an upperdir), other local users or containers can list and traverse directories that were intended to be private.

Technical Analysis

In create_node_directory(), the temporary directory is created by widening the original mode with 0o755 to ensure it remains writable during the setup of extended attributes (xattrs) and timestamps:

fs::mkdirat(workdir_fd, &c_wd_name, st.st_mode | 0o755)?;

However, unlike the regular file path further down in copyup(), there is no subsequent fchmod call to restore the original mode before the directory is renamed to its final destination.

For regular files, the pattern correctly widens, writes, and restores:

let dfd = openat2::safe_openat(
    workdir_fd, wd_name.as_bytes(),
    libc::O_CREAT | libc::O_WRONLY,
    mode | 0o200,          // temporarily widen
)?;
...
// Restore original mode
let _ = crate::sys::fs::fchmod(dfd.as_raw_fd(), mode);   // <-- Restores here

For directories, it follows a widen -> write -> rename pattern, completely omitting the restoration step. This causes a 0600 or 0700 directory to permanently become 0755 (or worse, st.st_mode | 0o755) in the upper layer.

Impact

  • Vulnerability Type: Information Disclosure / Permissions Bypass
  • Severity: Medium/High (depending on the environment deployment, especially critical in rootless container environments sharing underlying storage layers).
  • Exploitability: Trivial. Any standard modification inside a restricted lower-layer directory triggers the copy-up and flattens the security bounds.

Suggested Fix

Mirror the file path logic by explicitly restoring the original mode via fchmod right before the directory is renamed:

let _ = fs::fchmod(dfd.as_raw_fd(), st.st_mode & 0o7777);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions