From 2db844dd8c60c2326e89cefb9bf8960a7e6e93a2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Sep 2022 18:23:11 -0700 Subject: [PATCH 1/2] On Windows, make `maybe_dir(true)` disable deletion and renaming. Similar to `dir_options()`, on Windows, when `maybe_dir` is set, clear the share flag for deletion and remaining, to protect cap-std's sandboxed path lookup. And, add a coment to cap-fs-ext's documentation for `maybe_dir`. --- cap-fs-ext/src/open_options_maybe_dir_ext.rs | 14 ++++++++------ cap-primitives/src/windows/fs/oflags.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cap-fs-ext/src/open_options_maybe_dir_ext.rs b/cap-fs-ext/src/open_options_maybe_dir_ext.rs index 52b687f8..a286adf0 100644 --- a/cap-fs-ext/src/open_options_maybe_dir_ext.rs +++ b/cap-fs-ext/src/open_options_maybe_dir_ext.rs @@ -1,11 +1,13 @@ /// Extension trait for `cap_primitives::fs::OpenOptions` which adds -/// `maybe_dir`, a function for controlling whether an open should -/// attempt to succeed on a directory. On Posix-ish platforms, opening -/// a directory always succeeds, but on Windows, opening a directory -/// needs this option. +/// `maybe_dir`, a function for controlling whether an open should attempt to +/// succeed on a directory. On Posix-ish platforms, opening a directory always +/// succeeds, but on Windows, opening a directory needs this option. pub trait OpenOptionsMaybeDirExt { - /// Sets the option for disabling an error that might be generated - /// by the opened object being a directory. + /// Sets the option for disabling an error that might be generated by the + /// opened object being a directory. + /// + /// On some platforms, this may prevent the directory from being deleted + /// or renamed while the handle is open. fn maybe_dir(&mut self, maybe_dir: bool) -> &mut Self; } diff --git a/cap-primitives/src/windows/fs/oflags.rs b/cap-primitives/src/windows/fs/oflags.rs index f2867e0a..fda6a6e6 100644 --- a/cap-primitives/src/windows/fs/oflags.rs +++ b/cap-primitives/src/windows/fs/oflags.rs @@ -24,8 +24,15 @@ pub(in super::super) fn open_options_to_std(opts: &OpenOptions) -> (fs::OpenOpti opts.ext.custom_flags | FILE_FLAG_OPEN_REPARSE_POINT } }; + let mut share_mode = opts.ext.share_mode; if opts.maybe_dir { custom_flags |= FILE_FLAG_BACKUP_SEMANTICS; + + // Only allow `FILE_SHARE_READ` and `FILE_SHARE_WRITE`; this mirrors + // the values in `dir_options()` and is done to prevent directories + // from being deleted or renamed underneath cap-std's sandboxed path + // lookups on Windows. + share_mode &= !FILE_SHARE_DELETE; } let mut std_opts = fs::OpenOptions::new(); std_opts @@ -35,7 +42,7 @@ pub(in super::super) fn open_options_to_std(opts: &OpenOptions) -> (fs::OpenOpti .truncate(trunc) .create(opts.create) .create_new(opts.create_new) - .share_mode(opts.ext.share_mode) + .share_mode(share_mode) .custom_flags(custom_flags) .attributes(opts.ext.attributes); From 6659c2f7504abd968aff7a1aeb94f45c40a17fef Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Sep 2022 16:13:16 -0700 Subject: [PATCH 2/2] Fix compilation. --- cap-primitives/src/windows/fs/oflags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cap-primitives/src/windows/fs/oflags.rs b/cap-primitives/src/windows/fs/oflags.rs index fda6a6e6..8f5022a5 100644 --- a/cap-primitives/src/windows/fs/oflags.rs +++ b/cap-primitives/src/windows/fs/oflags.rs @@ -2,7 +2,7 @@ use crate::fs::{FollowSymlinks, OpenOptions}; use std::fs; use std::os::windows::fs::OpenOptionsExt; use windows_sys::Win32::Storage::FileSystem::{ - FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, + FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, }; /// Translate the given `cap_std` into `std` options. Also return a bool