Linux on Surface RT - Make the Kernel boot

⚠️
This post does not reflect the current state of the art of Linux on Surface RT. For more information, go to OpenRT's gitbook: https://openrt.gitbook.io/open-surfacert/ 
Linux on Surface RT - (nearly) full featured OS
A lot of progress has been made by the Open Surface RT team since my last post on this subject. It’s time for an update.

I have been following the Surface RT jailbreak community since the discovery of CVE-2016-3287 and CVE-2016-3320 (aka Secure Boot Golden Key vulnerability). Until now, nearly no one got to boot Linux on the Surface RT using it. At the best, the community (including me) was able to boot into an EFI version of Grub.

But for the past weeks a major breakthrough is reviving the hope in me to at last use the Surface RT. Let's dive a bit into the current state of the art.

This article will be (maybe) followed by a conclusion to this story that I followed for 5 years. Stay tuned!

The problem with the Surface RT

I've got a Surface RT since late 2013 and never got to use anything else than the crippled Windows RT 8.0 on it. You'll see that getting something else to work on it is quite a challenge.

The Microsoft Surface RT is an ARM version of Microsoft's Windows tablets released in 2012. Yes! Something that Microsoft made is still resisting hacking after 8 years of life! (but you'll see that this is not for the good reasons)

Relying on a Tegra 3 T30 SoC, it runs natively Windows RT 8.0 (and 8.1). But here is the catch: the Surface RT is an alien in the Surface landscape (along with the Surface 2) and the support for Windows RT has been quickly dropped as the next generations of Surface go back to x86.

Also, for these models, Microsoft decided to lock the device: Secure Boot that cannot be disabled by the user, very specific hardware, user software digital signature required, lack of Windows applications supporting ARM, etc...

When the support of Windows RT has been dropped, an obvious choice would have been to install Linux on it and to enjoy the vast amount of Linux software supporting ARM. But the path to this goal is quite tricky.

The first hope of a jailbreak

I got interested in Surface RT jailbreak when 2 guys (my123 and slipstream) from Ring of Lightning released the details of 2 vulnerabilities allowing to disable Secure Boot: https://forum.xda-developers.com/windows-10-mobile/leaked-leaked-secure-boot-golden-keys-t3437885

These vulnerabilities are known collectively as the Golden Key vulnerability.

Unfortunatly the original website is down but some archives and instructions can still be found on the XDA developers forums.

My Surface RT under Windows showing a Secure Boot warning (in French) in the right bottom corner

The idea of these vulnerabilities is simple if we sum it up with some shortcuts.

Development devices cannot have the same security constrains because that would mean that Microsoft has to sign every binary developers compile to test their software. That is why Microsoft implemented little files (that are signed and verified by the firmware) that describe the Secure Boot policy to be applied by the UEFI firmware (which is in charge of enforcing Secure Boot among many other things).

These files cannot be circumvented or modified because of the UEFI cryptographic checks. Also, it should be noted that such a policy file cannot be used on any other device as they are tied to each device (via a unique device ID). So a development and a customer device would have different policies tied to the hardware.

But during the development of Windows 10, Microsoft added a new type of Secure Boot policy called "supplemental" policies. At this time, Windows' EFI bootloader did first load the Secure Boot policy it had by default and then load additional parameters from the "supplemental" policy if present.

And the catch here is that the bootmanager did check the validity of the "supplemental" policy that it loaded into a valid Secure Boot policy but these policies did not include any device ID. So any "supplemental" policy would work on any device!

This way, it was possible to load any valid Secure Boot policy, including ones that enabled testsigning, a special mode allowing to run auto-signed firmware and driver files. In fact, that means practically any software.

Microsoft patched the vulnerability by blacklisting some (but not all) policies. And it was later discovered that a downgrade was possible to get back the vulnerable version of the bootloader.

At the moment, I was convinced that this was the end of the Windows lock. But not quite.

The authors released a PoC with "supplemental" policies allowing to alter Secure Boot and software signing requirements. They also provided a Grub EFI binary that could run from an USB stick. It tried it and it worked like a charm, until the moment to boot Linux came...

The Grub prompt on my Surface RT after Jailbreak

Why booting Linux failed during several years

Any unsigned (well self-signed...) EFI binary compiled for ARM32 would work at this stage but Linux is not an EFI binary (excluding Linux EFI shim but this is only a tool to boot Linux on EFI systems).

Several problems came into the path.

When the Golden Key exploit was released, I tried to create a Linux image based on the image provided by Nvidia for development boards using Tegra 3 cores (aka Cardhu). When jumping from Grub it immediately crashed with no output.

I expected that and I suspected that was mainly due to the fact that the Device Tree and the drivers were designed for Nvidia's development boards. The Surface RT, even if it uses a very similar SoC, is not the same hardware.

Note: I know retrospectively that this approach could have disastrous consequences as incorrect power management description in the Device Tree can lead to a pure and simple fry of the electronics. Don't try this at home!

So the Device Tree, a blob describing the hardware to Linux (and mandatory to run Linux ARM) did not cover the hardware of the Surface RT and I didn't have enough knowledge to write a brand new one.

Another problem consists in the fact that, for ARM, Linux expects to be booted from low addresses in physical memory. Microsoft's bootloader is the first code executed after the first stage bootloader (burnt in the SoC) and is the one in charge of initializing the TrustZone (an isolated environment for security operations). As a matter of fact, Microsoft's bootloader locks pages of the physical memory in the same region.

Thus, Grub and Linux are unable to initialize the corresponding memory for the OS.

At the moment, I was stuck (mostly by what I though was only a Device Tree problem). And I must admit that I though that someone way more clever in the community will figure on something. But things have been staying more or less still until last June.

Fusée Gelée

When the Reswitched team released the Fusée Gelée exploit back in 2018, I remember I immediately though that this could apply to the Surface RT.

Fusée Gelée (CVE-2018-6242) is an exploit targeting Tegra SoCs that was first leveraged to Jailbreak the first generation of Nintendo Switch consoles. It cannot be patched by software and you can bet that, today, 1st generation Nintendo Switch are quite popular (next generations patched the vulnerability with a new revision of their SoCs).

The original paper for Fusée Gelée is here: https://github.com/Qyriad/fusee-launcher/blob/master/report/fusee_gelee.md

So, it happens that Tegra SoCs have a special run mode called RCM (for ReCovery Mode).

This mode can be activated in several conditions after some actions are made by the user, or more likely by the manufacturer. In the case of the Nintendo Switch, a specific connection between 2 pins of the Joy-Con connector would do the trick. On the Surface RT, this mode can be reached by turning the Tegra 3 into the so-called APX mode (by holding volume up and pushing power).

The RCM/APX mode allows to "talk" to the SoC using a USB connection. Unfortunately, by default, messages sent to the SoC must be signed by a key owned by the manufacturer.

And here comes Fusée Gelée.

Katherine Temkin and Mikaela Szekely managed to find an insecure copy operation in the USB connection setup in a firmware extracted from a similar SoC.

Leveraging this copy, they were able to smash the stack in the most early stages of the boot process.

And for many people (or at least the smart ones), smashing the stack often means code execution.

So by executing code in the most early stages of the boot process attackers are able to run any code on the SoC. This is practically allowing to bypass any bootloader included in the device. No wonder I dreamed about the same thing with the Surface RT.

I wasn't the only one to think that this could apply to the Surface RT. And, once again, I didn't feel that I was skilled enough to adapt the Fusée Gelée launcher to the Surface RT.

And in fact, someone did adapt it for the Tegra 3 T30! Jevin Sweval released a fork of the Fusée Gelée launcher to include the support for previous Tegra releases: https://github.com/jevinskie/fusee-launcher

I don't know why, this stayed out of my radar for 2 years. Until really recently.

A new hope

At the time of the writing, this is a Work In Progress. No user-ready Linux distribution is available on the Surface RT for now.

The dedicated forum topic on XDA gained a new activity in June and quickly a new team gathered to boot Linux on the Surface RT: https://forum.xda-developers.com/windows-8-rt/rt-development/wip-secure-boot-linux-surface-rt-t3653848/page14

They launched the Open Surface RT initiative which developed a new approach that is a real breakthrough: https://openrt.gitbook.io/open-surfacert/

Instead of trying to boot Linux from the Windows Boot Manager, they decided to try to recreate the full boot chain by using the Fusée Gelée exploit.

And they managed to recreate all early boot stages to execute a Das U-Boot bootloader that can then load the Linux Kernel.

The main idea consists in bypassing the ROM signature check made by the SoC. Doing that it is possible to load a custom ROM directly into the RAM and then jump into it.

They first wrote program stubs to load with Fusée Gelée directly into the memory in APX mode. These stubs aimed to locate UART pins on the board. These would be useful to debug U-Boot and the Linux Kernel execution in the first stages (before any kind of HDMI or screen driver can be loaded).

By error and trial they finally managed to find these pins, unusually located under the solder mask. By doing this they answered to the 5-year old question of "where the f*ck is the debug port?".

They then used what was known about the Tegra 3 SoC and the board layout to create a Device Tree prototype.

At this stage, the Device Tree is incomplete and only allows to use the SoC (duh!), raw serial interfaces, the SD card reader, the eMMC (onboard storage), the HDMI interface, output stdout (for dmesg log mostly) to the discovered UART and initialize memory.

But this is an impressive work. This is enough to finally boot the Kernel and jump into a Linux console!

The first lines of the exploit output, then u-boot and last Linux first words. This ends into a standard shell prompt

What next?

It is clear that the work is not finished. First of all, the Device Tree must be completed to include all onboard functionalities: WiFi, sound, integrated screen and digitizer, etc... Then drivers and maybe, last, distributions and graphical applications.

But we can dream again and hope that, at the end, a complete Linux image and maybe a Linux distribution or Android will be made available to the Surface RT.

If this happens, I will be glad to write an end to this story.

Sources

I used many sources to write this post. I will only include here the most significant ones: