astrid-runtime/astrid · error

mount data has NUL

Error message

mount data has NUL

What it means

mount_overlay converts the overlayfs data option string (lowerdir=/upperdir=/workdir=...) to a CString for mount(2). If the assembled data string contains an embedded NUL byte, CString::new fails and the function returns InvalidInput 'mount data has NUL'.

Solutions

  1. Validate each layer path (lowerdir/upperdir/workdir) for NUL bytes before assembling the data string
  2. Since validate inputs are Paths, check as_os_str().as_bytes().contains(&0) upstream
  3. Reject NUL-containing paths at the workspace configuration boundary
  4. Log the data string (NUL-escaped) to find which layer path is bad

Example fix

// before
let data = format!("lowerdir={},upperdir={},workdir={}", lower, upper, work);
mount_overlay(target, &data)?;
// after
for p in [&lower, &upper, &work] {
    if p.as_os_str().as_bytes().contains(&0) { return Err(...); }
}
mount_overlay(target, &data)?;
Defensive patterns

Strategy: validation

Validate before calling

for p in [&lower, &upper, &work] { if p.as_os_str().as_bytes().contains(&0) { return Err(io::Error::new(io::ErrorKind::InvalidInput, "layer path contains NUL")); } }

Type guard

fn layer_ok(p: &Path) -> bool { !p.as_os_str().as_bytes().contains(&0) }

Try / catch

match mount(target, &layers) { Err(e) if e.kind() == io::ErrorKind::InvalidInput => { /* inspect layer paths for NUL, fail the workspace setup */ }, other => other, }

Prevention

When it happens

Trigger: Calling mount (→ mount_overlay) when the data string built from layer directory paths contains an interior '\0' — i.e. one of the layer paths fed into the option string contains NUL.

Common situations: Layer/workspace paths derived from binary data or untrimmed buffers; corrupted configuration supplying layer directories with embedded NULs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/e14b9577bfa11d43. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-vfs/src/workspace_cow/overlayfs.rs:500

fn path_hash(path: &Path) -> String {
    use std::collections::hash_map::DefaultHasher;
    use std::hash::{Hash, Hasher};
    let key = std::fs::canonicalize(path).unwrap_or_else(|_| path.to_path_buf());
    let mut hasher = DefaultHasher::new();
    key.hash(&mut hasher);
    format!("{:016x}", hasher.finish())
}

/// `mount("overlay", target, "overlay", 0, data)`.
fn mount_overlay(target: &Path, data: &str) -> io::Result<()> {
    let src = CString::new("overlay")
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "mount source has NUL"))?;
    let fstype = CString::new("overlay")
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "mount fstype has NUL"))?;
    let target_c = CString::new(target.as_os_str().as_bytes())
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "mount target has NUL"))?;
    let data_c = CString::new(data)
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "mount data has NUL"))?;
    // SAFETY: all four pointers are valid, NUL-terminated C strings that outlive
    // the call; `mount` reads them and returns a status code, retaining no
    // pointers. `data` is the overlayfs option string.
    let rc = unsafe {
        libc::mount(
            src.as_ptr(),
            target_c.as_ptr(),
            fstype.as_ptr(),
            0,
            data_c.as_ptr().cast(),
        )
    };
    if rc != 0 {
        return Err(io::Error::last_os_error());
    }
    Ok(())
}

View on GitHub (pinned to affd8760f4)