{"record":{"id":"d7296908223d3d78","repo":"rustdesk/rustdesk","slug":"invalid-ipc-path-path","errorCode":null,"errorMessage":"invalid ipc path: {path}","messagePattern":"invalid ipc path: (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"src/ipc/fs.rs","lineNumber":183,"sourceCode":"}\n\n/// Remove one entry from the IPC parent directory through a no-follow fd on that directory.\n///\n/// Prefer this over `std::fs::remove_file` for anything about to be bound: `remove_file` is\n/// `unlink(2)`, which returns EISDIR against a directory-typed squatter and leaves it in place,\n/// and the bind that follows then fails EADDRINUSE. `remove_parent_entry_via_fd` fstats the\n/// entry first and picks `AT_REMOVEDIR` when it needs to.\n///\n/// `AT_REMOVEDIR` is `rmdir(2)`, so the directory case this closes is the EMPTY one; a non-empty\n/// squatter still yields ENOTEMPTY and still blocks the bind that follows. That is deliberate, and\n/// the \"obvious\" fix is worse than the bug: removing it recursively would be root deleting a tree\n/// an unprivileged process planted. What the caller gains there is a named error to log ahead of\n/// the bind's own failure, not a successful bind.\npub(crate) fn remove_ipc_entry_via_secure_parent_fd(path: &str) -> ResultType<()> {\n    let entry_name = Path::new(path)\n        .file_name()\n        .and_then(|n| n.to_str())\n        .ok_or_else(|| Error::new(ErrorKind::InvalidInput, format!(\"invalid ipc path: {path}\")))?\n        .to_owned();\n    let parent_dir = Path::new(path)\n        .parent()\n        .ok_or_else(|| Error::new(ErrorKind::InvalidInput, format!(\"invalid ipc path: {path}\")))?;\n    let parent_c = CString::new(parent_dir.as_os_str().as_bytes().to_vec())?;\n    let fd = match open_ipc_parent_dir_fd(&parent_c) {\n        Ok(fd) => fd,\n        Err(open_err) => {\n            if open_err.kind() == ErrorKind::NotFound {\n                return Ok(());\n            }\n            return Err(Error::new(\n                open_err.kind(),\n                format!(\n                    \"failed to open ipc parent dir for stale socket cleanup (no-follow): path={}, parent={}, err={}\",\n                    path,\n                    parent_dir.display(),\n                    open_err","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/rustdesk/rustdesk/blob/91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540/src/ipc/fs.rs#L165-L201","documentation":"remove_ipc_entry_via_secure_parent_fd splits the IPC path into a final entry name and a parent directory. If Path::file_name() yields nothing usable (path ends in '..', is empty, or is a bare root/relative dot path), the path cannot name a removable entry and this InvalidInput error is returned.","triggerScenarios":"Calling remove_ipc_entry_via_secure_parent_fd (used by new_drm_listener and remove_ipc_socket_via_secure_parent_fd) with a path like \"\", \"/\", \".\", \"..\", or any path whose file_name component is not valid UTF-8 or is missing.","commonSituations":"Empty or unexpanded config/template variable for the IPC socket path; a path built from user input that collapsed to a root; non-UTF8 locale paths on Unix.","solutions":["Supply a full, absolute path ending in a concrete file name (e.g. /run/user/1000/rustdesk/drm.sock)","Validate the configured IPC path is non-empty and has a file_name before calling","Fix the config/env source producing the empty or malformed path","Convert non-UTF8 paths or avoid them; this API requires UTF-8 names"],"exampleFix":"// before\nremove_ipc_entry_via_secure_parent_fd(&cfg.ipc_path)?; // may be \"\"\n// after\nlet path = cfg.ipc_path;\nif std::path::Path::new(&path).file_name().is_none() {\n    anyhow::bail!(\"configured ipc path has no entry name: {path:?}\");\n}\nremove_ipc_entry_via_secure_parent_fd(&path)?;","handlingStrategy":"validation","validationCode":"fn ipc_path_has_entry_name(path: &str) -> bool {\n    std::path::Path::new(path).file_name().map(|n| n.to_str().is_some()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"if !ipc_path_has_entry_name(&path) {\n    anyhow::bail!(\"bad ipc path {path:?}: no file name component\");\n}\nremove_ipc_entry_via_secure_parent_fd(&path)?;","preventionTips":["Always configure absolute paths ending in a concrete socket file name","Validate configured IPC paths at startup, before any listener setup","Avoid paths derived from unexpanded templates or empty env vars","Require UTF-8 paths (check to_str()) on Unix"],"tags":["ipc","path-validation","config","filesystem"],"backgroundTag":"invalid-argument-format","analyzedSha":"91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540","analyzedAt":"2026-09-10T19:53:44.083Z","contentChangedAt":"2026-09-10T19:53:44.083Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}