34
LinuxBoot progress: boot anything from Linux Chris Koch ( @hugelgupf) Google Ofir Weisse UMich Platform Security Summit - October 1, 2019 with Ron Minnich, Ryan O’Leary, Gan Shun Lim, Max Shegai, Trammell Hudson, Jean-Marie Verdun, David Hendricks, Andrea Barberio, Philipp Deppenwiese and many others www.linuxboot.org @hugelgupf

LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

LinuxBoot progress: boot anything from LinuxChris Koch (@hugelgupf) GoogleOfir Weisse UMich

Platform Security Summit - October 1, 2019

with

Ron Minnich, Ryan O’Leary, Gan Shun Lim, Max Shegai, Trammell Hudson, Jean-Marie Verdun, David Hendricks, Andrea Barberio, Philipp Deppenwiese and many others

www.linuxboot.org

@hugelgupf

Page 2: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Recap: LinuxBoot on UEFI

Boot Device Selector (BDS)

Linux + initramfs

We remove most DXEs.

We keep the DXECore around for ACPI and some device initialization.

We kexec next kernel (space).

Most DXEs are removed

Linux knows how to initialize devices.

Compile kernelas a PE32 executable: EFI_STUB

Real Kernel

kexec

@hugelgupf

Page 3: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Why?

We've replaced UEFI complexity with Linux Kernel complexity

Little review & visibilityvs

an uncountable number of contributors

(Also, reproducible builds)

@hugelgupf

Page 4: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Not on UEFI?

@hugelgupf

Page 5: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

u-root: pointlessly rewriting things in Go

● We have the full toolset of Linux applications at our fingertips in firmware now.

○ Let’s use them!

○ Let’s use a memory-safe language.

○ Let’s use a language that makes concurrency easy.

● Enter u-root: 3MB - 5MB (compressed) initramfs in Go○ busybox-like tools (cat, dd, ls, cp, cpio, …)

○ kexec-based bootloaders (PXE- and GRUB-compatible boot tools, ...)

○ github.com/u-root/u-root

@hugelgupf

Page 6: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Progress: Project Health● New: merging duplicate projects

○ systemboot + u-root: Facebook + Google

○ systemboot had TPM + certificate support

○ u-root the “cleaner” bootloaders

○ deduplicate + improve code health

@hugelgupf

Page 7: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

CI presubmit:VM-based integration tests

(still needs work!)

Launch VM with unit tests in pkg/gpio

unit test in pkg/gpio

@hugelgupf

Page 8: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Command to run inside VM

Commands to build into VM initramfs

Expect script

File to include in VM initramfs at /kernel

@hugelgupf

Page 9: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Progress

● New: kexec multiboot kernels (Xen, ESXi, tboot, …)

○ tboot support essential to some of our users

○ Imagine writing a trampoline in Go assembly :)

@hugelgupf

Page 11: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Why not be UEFI compliant

Boot Device Selector (BDS)

Linux + initramfs

Most DXEs are removed

kexec

● UEFI apps are Portable Executables (PEs)● Let’s kexec them!● Specifically, kexec Windows boot-manager

@hugelgupf

Page 12: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

What do you need to boot EFI apps?

PE32 loader into ring 0

&

pointers to pass to the entrypoint

&

PE32 app expects physical addressing

SystemTable

BootServices

RuntimeService

ConOut

ConfigurationTable

...

BootServices

LocateHandle

AllocatePages

OpenProtocol

ExitBootServices

...

Page 13: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Let’s collect some info

● Take EDKII, add a bunch of prints○ What Boot Services are called?○ What Protocols are invoked?

● Use that to boot Windows in a VM under EDKII/OVMF

@hugelgupf

Page 14: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Minimum Required EFI Boot Services

Services Used (out of 44)● StartImage● LocateHandle● Open/CloseProtocol● Allocate/FreePages● Allocate/FreePool● GetMemoryMap● SetWatchdogTimer● ExitBootServices

@hugelgupf

Page 15: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Minimum Required EFI Protocols

Services Used (out of 44)● StartImage● LocateHandle● Open/CloseProtocol● Allocate/FreePages● Allocate/FreePool● GetMemoryMap● SetWatchdogTimer● ExitBootServices

Protocols Used (Out of ~441)● LoadedImageProtocol● BlockIoProtocol● DevicePathProtocol● SimpleTextInputExProtocol● StorageSecurityCommandProtocol● GraphicsOutputProtocol

Happy conclusion:UEFI spec is huge, but only a small

subset is actually used

@hugelgupf

Page 16: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

● 3 stage loading process○ bootmgfw.efi

■ Loads winload.efi ● which loads ntoskernel.exe

● kexec code for PE32 loader -- not that hard○ validation for this is easy -- launch

■ Linux with PE32-shim■ An EFI hello world

Launching Windows via kexec

@hugelgupf

Page 17: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Debug cycle2.Crash

1.Launch

Page 18: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Debug cycle2.Crash

1.Launch

3. Analyze4. Learn something about

5. Fix

Page 19: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Debugging Example

● Illegal memory access● Stack trace is useless

Page 20: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

IPython:

Debugging Example

Page 21: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

● <show IDA + reversing.py+reactOS source>

Debugging Example

Page 22: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Physicalmemory

Virtualmemory

Challenge: Physical Addressing

0xffff0c00000...

0xffff0a010000xffff0a00000

0xa010000xa00000

1. AllocatePage

...

0xffff0a00000

2. kmalloc

Page 23: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Challenge: Physical Addressing

1. AllocatePage

0xffff0a00000

3. Change CR34. Access “physical” page 0xffff0a00000

2. kmalloc

Physicalmemory

0xa010000xa00000

...

Page 24: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Virtualmemory

Solution: 1:1 Virtual-to-Physical Mapping

0x00000a010000x00000a00000

Physicalmemory

0xffff0c00000...

0xffff0a010000xffff0a00000

0xa010000xa00000

...

Page 25: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Solution: 1:1 Virtual-to-Physical Mapping

1. AllocatePage

0xa00000

2. kmalloc 3. map 1:1

Virtualmemory

0x00000a010000x00000a00000

Physicalmemory

0xffff0c00000...

0xffff0a010000xffff0a00000

0xa010000xa00000

...

Page 26: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Solution: 1:1 Virtual-to-Physical Mapping

1. AllocatePage

0xa00000

4. Change CR35. Access “physical” page 0xa00000

2. kmalloc 3. map 1:1

Physicalmemory

0xa010000xa00000

...

Page 27: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 1

● ExitBootServices is called

● Most cores seems to be in KiIdleLoop

● 1 core in KiSystemCall64

Page 28: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 2

● Enabling kernel debug+EMS

Page 29: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 2

● Enabling kernel debug+EMS

Page 30: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 2

● Enabling kernel debug+EMS

Page 31: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 3

● Enabling graphics● Using Linux /dev/fb0● Give the

framebuffer to Windows● And... we crash!

Page 32: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 3

● Enabling graphics● Using Linux /dev/fb0● Step 1: Using it ourselves● Step 2: Giving the

framebuffer to Windows● And... we crash!● Fix..

Page 33: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Whoa moment 3● Enabling graphics● Using Linux /dev/fb0● Step 1: Using it ourselves● Step 2: Giving the

framebuffer to Windows● And... we crash!● Fix..● Login!

Page 34: LinuxBoot progress: boot anything from Linux …...3 stage loading process bootmgfw.efi Loads winload.efi which loads ntoskernel.exe kexec code for PE32 loader -- not that hard validation

Sign up for the Open Source Firmware Slackhttp://slack.u-root.com

Codehttps://github.com/oweisse/u-root/tree/kexec_test/booting_windowshttps://github.com/oweisse/linux

Thanks toOfir Weisse for being a productive PhD intern :)

[email protected]://twitter.com/hugelgupf