Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: fix soundness hole in Handle API #998

Merged
merged 8 commits into from
Aug 28, 2024

Conversation

CBenoit
Copy link
Member

@CBenoit CBenoit commented Aug 28, 2024

The API of Handle in win-api-wrappers is allowing UB without unsafe code. I adjusted the API to fix the hole.
Note that this PR is not fixing any vulnerability or bug per se. It only fixes the unsound safe API that we are using correctly in this repository only.

cc @kbouchard-dev

@CBenoit CBenoit enabled auto-merge (squash) August 28, 2024 08:12
Comment on lines 49 to 68
// Wraps a borrowed Windows [`HANDLE`].
pub fn new_borrowed(handle: HANDLE) -> Self {
// SAFETY: It’s safe to wrap a non-owning Handle as we’ll not call `CloseHandle` on it.
unsafe { Self::new(handle, false) }
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we know that the handle is not owned in a static way, we can use the safe function new_borrowed which never causes any UB.

Comment on lines 22 to 57
pub fn new(handle: HANDLE, owned: bool) -> Self {
// Wraps a Windows [`HANDLE`].
//
// # Safety
//
// When `owned` is `true`:
//
// - `handle` is a valid handle to an open object.
// - `handle` is not a pseudohandle.
// - The caller is actually responsible for freeing the `HANDLE` when the value goes out of scope.
//
// When `owned` is `false`: no outstanding precondition.
pub unsafe fn new(handle: HANDLE, owned: bool) -> Self {
Self { raw: handle, owned }
}

// Wraps an owned Windows [`HANDLE`].
//
// # Safety
//
// - `handle` is a valid handle to an open object.
// - `handle` is not a pseudohandle.
// - The caller is actually responsible for freeing the `HANDLE` when the value goes out of scope.
pub unsafe fn new_owned(handle: HANDLE) -> Self {
// SAFETY: Same preconditions as the called function.
unsafe { Self::new(handle, true) }
Copy link
Member Author

@CBenoit CBenoit Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Drop implementation is assuming we constructed the Handle object in a sane way to call CloseHandle, but there is no way for us to verify that the handle is actually owned outside of the callsite. Conceptually, calling Handle::new_owned(handle) or Handle::new(handle, true) is like calling the unsafe function CloseHandle and thus must inherits its safety preconditions.

@CBenoit CBenoit force-pushed the refactor/fix-soundness-hole branch from 83bf8da to 7b2f5c5 Compare August 28, 2024 09:47
@CBenoit CBenoit merged commit b09086d into master Aug 28, 2024
23 checks passed
@CBenoit CBenoit deleted the refactor/fix-soundness-hole branch August 28, 2024 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants