rhboot / shim

UEFI shim loader
Other
868 stars 293 forks source link

Uninstalling earlier shim protocol does not actually do anything, fails silently #221

Open julian-klode opened 4 years ago

julian-klode commented 4 years ago

While analyzing https://bugs.launchpad.net/bugs/1865515 I found out that the earlier shim protocol uninstalling actually does nothing.

In src/shim.c inside install_shim_protocols() we attempt to uninstall the old shim by calling uninstall_shim_protocols(). This does nothing, and hence loading two shims and then a kernel fails.

What happens is that when we enter uninstall_shim_protocols() we have shim_lock_handle == NULL, which is an invalid argument (and hence UninstallProtocolInterface() fails with invalid argument error). It's NULL because we have not yet installed our new shim protocol, or made any attempt to get the old handle.

Furthermore, the protocol interface we try to remove in there is shim_lock_interface, but that is our new interface - the old one we located was only stored in a local variable in shim_lock.

How can we fix this?

One solution I found involves asking the old shim to uninstall itself, by extending its protocol (or realistically, adding a new one, for ABI reasons I suppose). The old shim knows its handle and interface, and hence uninstall_shim_protocols there just works.

Another attempt could be made by locating the old shim's handle with LibLocateHandle() or LocateHandle() or LocateHandleBuffer() similar to how we locate the protocol using LibLocateProtocol(), and then uninstall that.

We should also add error checking to the uninstall code, so we actually see errors there as well.

julian-klode commented 4 years ago

This basically means commit c8ca1c569664913e580340105bceb75b5aecad57 by @cyphermox never did anything, but this is confusing :/

vathpela commented 4 years ago

I have an idea for how to make this a lot better, but it requires a couple of other features first: Add two protocols that shim provides and installs:

SHIM_VOLATILE_KEYS_PROTOCOL:

SHIM_IMAGE_PROTOCOL:

the handle on the LoadedImage object this is basically just a pointer to a struct that's opaque to everyone but shim, but it gives us: