Tuesday, April 23, 2019

another meta-blog, no runtime, and a taste of Rust

I hate to blog about blogs, but I wanted to mention https://www.jsnover.com/blog/2011/10/16/on-becoming-a-senior-technical-individual-contributor/#more-49 and https://www.jsnover.com/blog/2011/12/24/focus-on-reality/#more-137, especially the quotation  “My job is to ship the best ideas not come up with them“. This quotation follows the sentiment of http://vzimmer.blogspot.com/2013/12/invention-and-innovation.html where I noted that invention is just a part of innovation, where innovation is delivering on an idea to the market. I enjoy this type of post, including more recent ones like https://blog.jessfraz.com/post/defining-a-distinguished-engineer/.

Speaking of 'shipping' things, one area of pain has been the support of UEFI run time variables, especially honoring the semantic of 'success means durably stored' and authenticated variables means 'no bypass of the SetVariable API to the SPI NOR storage,' as described in our design material https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Implementing_UEFI_Authenticated_Variables_in_SMM_with_EDKII_V2.pdf. Given those complexities, I am happy to see efforts toward having a UEFI conformant platform elide support for certain run time services. From https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf


Specifically the EFI_RT_SUPPORTED_SET_VARIABLE. This work was driven by the U-boot community implementing UEFI https://github.com/u-boot/u-boot/blob/master/doc/README.uefi since having a separate, isolated persistent storage if difficult, especially on 'single NAND' devices, for which many U-Boot devices can be found. In the future this could be the extended to a broad class of systems wherein the OS could elect to 'stage' UEFI variable writes during the pre-OS, such as saving to EFI system partition during OS run time and then setting on a subsequent boot prior to Exit Boot Services, in lieu of today's run time accesses. Some people refer to this as double-clutching.

This approach follows the existing UEFI PI Threat model https://members.uefi.org/learning_center/presentationsandvideos/Intel-UEFI-ThreatModel.pdf where the more secure environment is in the early boot. This is often referred to 'temporal isolation.' We historically considered all of the OEM code (SEC, PEI, DXE) to be trustworthy, but option ROM’s, OS loader, and the OS kernel to be potentially hostile. As such, having the boot service time manage the write is easier since the UEFI PI implementation manages the hardware. Although http://vzimmer.blogspot.com/2012/12/accessing-uefi-form-operating-system.html is historically the most accessed entry on this blog, I'd be happy to see the above UEFI 2.8 capability make that blog posting moot.

On the topic of isolation, EndOfDxe event is the last point at which only OEM code runs. Afterward, many more parties run on the platform. For pre-OS isolation from 3rd party hardware devices we have https://firmware.intel.com/sites/default/files/Intel_WhitePaper_Using_IOMMU_for_DMA_Protection_in_UEFI.pdf. And for isolation of pre-OS host agents we have defense in depth among ring 0 UEFI and DXE with   https://legacy.gitbook.com/book/edk2-docs/a-tour-beyond-bios-mitigate-buffer-overflow-in-ue/details and other options like pushing your PI implementation ring -1

In general eliding the UEFI runtime or isolating existing 3rd party binaries present challenges with compatibility for the existing catalog of .efi images generated since the late 90's. You cannot easily apply NX to .efi images that combine code and data sections, or to images that implement their own image loaders (i.e., turning a data page into a code executable). As such, UEFI and the existing code is now a 20 year compatibility surface. I was reminded by the power and challenges of binary compatibility when reading 

Beyond isolation, the fashionable idea in the air right now is to re-write a bunch of stuff in Rust https://firmwaresecurity.com/2017/11/05/biors-bios-implementation-in-rust-language/, but that doesn’t handle the existing catalog of potentially errant or malicious native code objects out in the market. The nice part of language based security (LBS) approaches like Rust, though, is that existing C artifacts can incrementally be migrated to Rust. And Rust seems to have the mind share momentum, with representative OS https://www.tockos.org/assets/papers/rust-kernel-apsys2017.pdf ports https://doc.redox-os.org/book/ in hand. And Hacker news reminded me of other advantages as I type up this blog https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/ https://kkimdev.github.io/posts/2019/04/22/Rust-Compile-Time-Memory-Safety.html.