rustdesk/rustdesk · error · std::io::Error

failed to open ipc parent dir (no-follow): postfix={}, paren

Error message

failed to open ipc parent dir (no-follow): postfix={}, parent={}, err={}

What it means

After creating (or confirming existence of) the IPC parent directory via mkdir, ensure_secure_ipc_parent_dir re-opens it with O_NOFOLLOW|O_DIRECTORY to get an fd for fchown/fchmod hardening. If this open fails, the errno is wrapped into this error. A failure here usually means the freshly-created path is not actually an openable real directory — most notably ELOOP when it is a symlink, or EACCES/EPERM.

Source

Thrown at src/ipc/fs.rs:281

                    let mkdir_err = std::io::Error::last_os_error();
                    // Handle a race where another process created the directory first.
                    if mkdir_err.raw_os_error() != Some(hbb_common::libc::EEXIST) {
                        return Err(Error::new(
                            mkdir_err.kind(),
                            format!(
                                "failed to mkdir ipc parent dir: postfix={}, parent={}, err={}",
                                postfix,
                                parent_dir.display(),
                                mkdir_err
                            ),
                        )
                        .into());
                    }
                }
                match open_ipc_parent_dir_fd(&parent_c) {
                    Ok(fd) => fd,
                    Err(err) => {
                        return Err(Error::new(
                            err.kind(),
                            format!(
                                "failed to open ipc parent dir (no-follow): postfix={}, parent={}, err={}",
                                postfix,
                                parent_dir.display(),
                                err
                            ),
                        )
                        .into());
                    }
                }
            } else {
                return Err(Error::new(
                    open_err.kind(),
                    format!(
                        "failed to open ipc parent dir (no-follow): postfix={}, parent={}, err={}",
                        postfix,
                        parent_dir.display(),

View on GitHub (pinned to 91c9fccbb0)

Solutions

  1. Inspect the parent path: if it is a symlink, remove it and let the code create a real directory (the O_NOFOLLOW check exists to reject exactly this).
  2. Verify ownership and permissions of the directory after recreation (owned by the running user, mode 0700).
  3. If another process races on the same path, coordinate cleanup — stop the other instance, remove stale dirs, and retry.
  4. Re-run after fixing environment restrictions that block opening directories with O_NOFOLLOW.

Example fix

// before: /tmp/rustdesk is a symlink planted by another user
lrwxrwxrwx /tmp/rustdesk -> /home/attacker/x
// after: replace with a real directory owned by the running user
rm /tmp/rustdesk && mkdir -m 700 /tmp/rustdesk
Defensive patterns

Strategy: try-catch

Validate before calling

let m = std::fs::symlink_metadata("/tmp/rustdesk");
if let Ok(m) = m {
    if m.file_type().is_symlink() {
        eprintln!("/tmp/rustdesk is a symlink; remove it before starting");
    }
}

Type guard

fn is_real_dir(path: &str) -> bool {
    std::fs::symlink_metadata(path)
        .map(|m| m.is_dir() && !m.file_type().is_symlink())
        .unwrap_or(false)
}

Try / catch

match new_drm_listener(&path) {
    Err(e) if e.to_string().contains("failed to open ipc parent dir") => {
        // likely symlink or permission issue; recreate the dir
        let _ = std::fs::remove_dir_all(parent_if_symlink(&path));
        new_drm_listener(&path)
    }
    other => other,
}

Prevention

When it happens

Trigger: new_listener or new_drm_listener when open_ipc_parent_dir_fd fails after a successful/raced mkdir: the created 'directory' is a symlink planted between mkdir and open, permissions changed so the user cannot open it, or another component in the path is not a directory.

Common situations: A malicious or misconfigured pre-existing symlink at the IPC directory location (TOCTOU hardening doing its job); an attacker or leftover state replaced the dir; restricted environments where O_NOFOLLOW directory opens are denied.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of rustdesk/rustdesk@91c9fccbb0 (2026-09-10). Data as JSON: /api/errors/6b98cebcb9be1075. Report an issue: GitHub.