From 768142d3294a307e4d054b5d5e9ffe066c4e028b Mon Sep 17 00:00:00 2001 From: Andy Kittner Date: Sat, 13 Apr 2024 20:03:10 +0200 Subject: [PATCH] Avoid false negatice permission denied error message (#9046) The unix implementation of cd fails with a permission error when classical unix permissions deny access to a directory, but additional mechanisms like ACLs actually grant the user access Fix this by miroring the windows implementation: if we can read_dir() without error => allow the cd to proceed. Addtionally we also handle the case where it is the other way round: unix permissions grant access but additional security modules (SElinux, apparmor, etc.) deny the current user/context. --- crates/nu-utils/src/filesystem.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/nu-utils/src/filesystem.rs b/crates/nu-utils/src/filesystem.rs index 588f0fccff..75d1ffc43d 100644 --- a/crates/nu-utils/src/filesystem.rs +++ b/crates/nu-utils/src/filesystem.rs @@ -33,6 +33,24 @@ pub fn have_permission(dir: impl AsRef) -> PermissionResult<'static> { #[cfg(unix)] pub fn have_permission(dir: impl AsRef) -> PermissionResult<'static> { + match dir.as_ref().read_dir() { + Err(_) => { + // this might produce a friendlier error message + match have_permission_by_metadata(dir) { + PermissionResult::PermissionOk => { + // handle false positive, metadata said we should be able to read but we + // actually tried to do that and failed (could be SELinux or similar in effect) + PermissionResult::PermissionDenied("Folder is unable to be read") + } + result => result, + } + } + Ok(_) => PermissionResult::PermissionOk, + } +} + +#[cfg(unix)] +fn have_permission_by_metadata(dir: impl AsRef) -> PermissionResult<'static> { match dir.as_ref().metadata() { Ok(metadata) => { let mode = Mode::from_bits_truncate(metadata.mode() as mode_t);