-
-
Notifications
You must be signed in to change notification settings - Fork 170
Handle
may be dropped by firmware unexpectedly, leading to unsoundness
#359
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
Comments
Thanks for looking into this. First question I have is: how common is firmware that is still on EFI <= 1.10? As far as I understand that's the last version of plain old EFI from before UEFI, and deprecated since 2005. So in theory nobody should have produced such firmware in 17 years. I think we could reasonably decide not to support >15 year old hardware, but of course companies sometimes do crazy things, so maybe there's more recent devices that would be impacted by this bug. Do you have any specific hardware/firmware in mind here? |
I haven't found anything in the wild that still uses EFI < 1.10, but theoretically this would also affect any UEFI drivers or applications written without the use of EDIT: If we decide to not support EFI <= 1.10, I suppose the deprecation warning on |
Some followup thoughts and questions: Taking another look at
It then goes on to describe how this has been fixed by adding To me that section makes it sound like "solved" it in pre-1.10 by just not allowing public handles to be dropped, in which case we don't need to worry about it in older firmware. Instead the issue seems to be worse with modern firmware, since now I took another look at the other suggested mitigations and I don't think they would work:
If I understand correctly, UEFI switches between tasks with interrupts. So even if you tried to validate a handle every time with
I think the same issues exist even if you ban safe copy/clone of a handle, since the original handle being copied from could also become invalid, so having a copy or not seems irrelevant to me. Interested to hear your thoughts on all the above. This stuff is tricky and I'm not at all sure I've correctly understood everything :) |
This method has the same problems as `handle_protocol`; it does not mark the handle and protocol as in use. Calls to `locate_protocol` can be replaced by calling `get_handle_for_protocol` and `open_protocol`. rust-osdev#359
This method has the same problems as `handle_protocol`; it does not mark the handle and protocol as in use. Calls to `locate_protocol` can be replaced by calling `get_handle_for_protocol` and `open_protocol`. rust-osdev#359
This stuff is indeed tricky! With UEFI switching between tasks with interrupts, I'm not sure how any kind of meaningful validation could be done. I'm very on-board with your recent PR that marks |
This method has the same problems as `handle_protocol`; it does not mark the handle and protocol as in use. Calls to `locate_protocol` can be replaced by calling `get_handle_for_protocol` and `open_protocol`. rust-osdev#359
* Add BootServices::get_handle_for_protocol This is a convenience method to get any arbitrary handle that supports a particular `Protocol`. * Use open_protocol in shim-lock test * Use open_protocol in multiprocessor test * Use open_protocol in device path test * Use open_protocol in pointer test * Use open_protocol in graphics test * Use open_protocol in file system test * Use open_protocol in the serial device test * Simplify event callback with context test Rather than opening the Output protocol, which isn't important for this test, just write through the context pointer and assert that the expected data was written. * Mark handle_protocol as unsafe This function is already marked deprecated, mark it unsafe as well and update the documentation to describe why. * Deprecate BootServices::locate_protocol and mark it unsafe This method has the same problems as `handle_protocol`; it does not mark the handle and protocol as in use. Calls to `locate_protocol` can be replaced by calling `get_handle_for_protocol` and `open_protocol`. #359
* Add BootServices::get_handle_for_protocol This is a convenience method to get any arbitrary handle that supports a particular `Protocol`. * Use open_protocol in shim-lock test * Use open_protocol in multiprocessor test * Use open_protocol in device path test * Use open_protocol in pointer test * Use open_protocol in graphics test * Use open_protocol in file system test * Use open_protocol in the serial device test * Simplify event callback with context test Rather than opening the Output protocol, which isn't important for this test, just write through the context pointer and assert that the expected data was written. * Mark handle_protocol as unsafe This function is already marked deprecated, mark it unsafe as well and update the documentation to describe why. * Deprecate BootServices::locate_protocol and mark it unsafe This method has the same problems as `handle_protocol`; it does not mark the handle and protocol as in use. Calls to `locate_protocol` can be replaced by calling `get_handle_for_protocol` and `open_protocol`. rust-osdev#359
I think we can call this one done now. We've made some good improvements in the protocol interface that should help keep things sound, although to a certain extent we'll always be at the mercy of UEFI implementations. |
Affected: Firmware targeting EFI < 1.10 and UEFI drivers that do not use
BootServices.open_protocol
andBootServices.close_protocol
.Prior to EFI 1.10, the
EFI_BOOT_SERVICES.UninstallProtocolInterface
function lacks the safety checks that were added in 1.10. It simply removes a protocol from a handle, and if the last protocol is removed from a handle, that handle is freed by firmware and no longer valid. It is entirely up to the caller to ensure that there are no remaining references to that protocol and potentially that handle. Post-1.10, the firmware is able to see any consumers that have usedopen_protocol
orclose_protocol
and attempt to disconnect those consumers before removing the protocol, failing if it is unable to do so.As far as I can tell, the firmware does not have a direct mechanism to let you know that a handle has been removed and is invalid. I've got a couple ideas about how to go about this:
locate_handle
, though that requires a protocol to search for. There isn't another UEFI function that would be suitable, as the rest of the protocol-related functions need to be passed a valid handle.Copy
andClone
fromHandle
, add anunsafe_clone
, and note the unsafety, trusting the caller.This feels like a can of worms; some input before I start working on an implementation would be appreciated. :)
The text was updated successfully, but these errors were encountered: