-
Notifications
You must be signed in to change notification settings - Fork 511
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
The Curious Case Of HANDLE and SOCKET #1643
Comments
Hi @Gankra, apologies in advance. Are you reporting an issue or have a question? I think I missed it. Happy to help if you do. |
Oh sorry, I was told to file this by @yoshuawuyts, I assumed he would be the one to "get" the issue! |
Ok! Will defer to @yoshuawuyts, but without an issue or question, it's a bit difficult to justify keeping this open. In the meantime, I read over this thread https://twitter.com/Gankra_/status/1508586681762566147. And I hear ya. We are working on Historically, a As Windows evolved over the years, so did developer needs to represent more things. And bigger things. So as you can imagine, some of the fundamental data types changed. A So with that understanding of handles, socket handles are just a specialization of a base handle, with socket programming-related semantics/constraints. Does that help you any? |
From a brief skim of types in https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types that typedef to HANDLE, I found 2 that seem to actually be publically documented to be pointers:
|
I think the conclusion here is that the metadata project (and thus windows-rs by extension) are likely as right as one can be and |
@nico-abram's comment suggests that This is not a "problem" if the pointer is something from the kernel that is opaque to us, but it is a problem if user code gets to understand it's a pointer and actually deref it. |
Yes, there is definitely code out there which uses an HINSTANCE as a pointer. |
Non-specialized handles are currently |
If it may hold a pointer, it must be a pointer. It's okay if it's sometimes an integer, there's no rule against representing arbitrary integers as pointers ( |
Yeah basically if a type is |
The Windows metadata - which as Ryan pointed out is what drives |
I'm not aware of any cases where a returned handle is designed to be used as a pointer by the developer. The developer isn't meant to know these handle integers are pointers. As is the case with most abstractions, I recognize they leak sometimes. 🙃 |
Also keep in mind that Windows has many different handle types. The discussion here and in #1622 (rust-lang/rust#87074) seem to imply that Windows only has two handle types, which is far from the truth. |
Just to be clear: It is also a problem if the user is expected to take a pointer and cast it to an (integer) HANDLE that the kernel or whatever else will proceed to read/write through. This is because under the strictest interpretations of provenance the compiler will not view this as "exposing" the pointer and think it's unaliased and miscompile your code. (This is indeed a very strict model, but we are hoping to encourage developers to follow it whenever they can, because it means their code will trivially work under any memory model, and it is Very Simple to understand and validate.) |
(emphasis mine) Don't think this is the case for any Windows APIs. If you have one in mind, please do share. |
If that indeed never happens, then I am totally happy! I am just not very familiar with this type hierarchy and am getting thrown off by all the different things that "are" "handles". Thanks for your help! |
I'm still trying to find it, so apologies that I can't be more specific, but I'm sure I've seen MFC code before which directly casts a pointer (to some kind of static resource) into a corresponding handle type via a C macro. Maybe I am just misremembering... |
One commonly auto baseAddress = reinterpret_cast<std::uintptr_t*>GetModuleHandle("foo");
// Do something with this pointer, like scribble in process memory 🎉💀 |
If the pointer-ness or integer-ness isn't supposed to ever be used, I wonder if it would make sense for Obviously that wouldn't stop people from |
I filed rust-lang/rust#95490 upstream(?) for discussing if Rust should do anything to match windows-sys here. |
For anyone subscribed to this thread, it looks like the types are changed back to pointers recently: microsoft/win32metadata#1924 Looks like this on a regen: 96b9a27 |
Here is a list of type definitions from many different sources:
wintnt.h:
WinSock.h / WinSock2.h
windows_sys::Win32::Foundation::HANDLE
windows_sys::Win32::Networking::WinSock::SOCKET
rust\library\std\src\sys\windows\c.rs:
rust\library\std\src\os\windows\c.rs:
std::os::windows::raw::HANDLE:
std::os::windows::raw::SOCKET:
Windows Socket Handles Docs
(I'm assuming this is talking about SOCKET, Microsoft's docs really hate linking these types.)
So as part of strict_provenance I have been trying to make code more consistent / honest about values which are "pointers" vs "integers". These APIs are the bane of my existence.
This made me very confused, and every time I checked a definition it was Slightly Different.
As far as I can tell both of these types are actually always integers (the kernel can't just hand userspace a pointer and then expect it to be a useful pointer if it's ever passed back to it, so it "must" be an integer and if you ask anyone with knowledge of the kernel they will say as much). Presumably HANDLE is just so ancient that Microsoft handn't figured out the Magic of
UINT_PTR
yet.So windows_sys is, in some sense, the one being Honest here. If these types are in fact always integers this mess is actually fine because under strict provenance it's "always ok for an integer to pretend to be a pointer For Fun". It's just, very hard to tell that this is what's Happening based on the surface definitions and types.
The text was updated successfully, but these errors were encountered: