返回资讯中心
外部精选
软件工程
#开发者实时流

Tinfoil – Less Is More: From 1M Lines of Firmware to 300 of Assembly

Less Is More: From 1M Lines of Firmware to 300 of Assembly

Hacker News 最新ibobev2026/10/26 · 今天30 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

Back to postsCopy markdown

Less Is More: From 1M Lines of Firmware to 300 of Assembly

Oct 25, 2026•16 min read

Joe Lothan, Jules Drean, Mia Korennykh

Patching bugs does not scale anymore. New vulnerabilities are getting disclosed at an exponential rate, and it can feel like all software is getting hacked at once. At Tinfoil, we’ve been thinking hard about what we can do to create a more principled approach to hardening software systems, especially when it comes to the most important parts of our stack. In our case, one critical piece of software is the firmware for our virtual machines, which plays a central role in the verifiability and security of all of our infrastructure.

The firmware sets up our secure enclave environments using configurations provided by the host. Since the host is controlled by Tinfoil, it is untrusted under our threat model, which means that the firmware code needs to be firmly hardened to prevent host-side exploits.

Previously, we relied on the widely used open-source OVMF firmware. However, we found that most of OVMF’s functionality was not necessary for our purposes. We could move almost all of the essential functionality to our build system, where it becomes easier to audit and verify. This removed almost all responsibility from the very security-critical part of the stack and allowed us to fully replace OVMF. We deleted 1M lines of C in favor of ~300 lines of open-source assembly and zero dependencies.

We think this is what designing secure systems will increasingly look like.

In the days of yore, using a large, trusted open-source codebase was the way to go, because only popularity could bring enough eyeballs to a project to make it legitimate from a security standpoint. That led to a concentration of open-source projects (e.g., OVMF for virtual firmware) that had to work for everyone. There was both a tension and a symbiotic relationship between security and feature completeness. It used to be that feature completeness equated to greater popularity, which equated to more eyeballs, which equated to better security. But the larger surface area also introduced more bugs.

In this new age, LLMs provide us with more “artificial eyeballs” than ever to scrutinize software. This makes it easier to write small, purpose-built software that doesn’t have to support every platform, and to test and fuzz it for security continuously. Security is no longer correlated with popularity. The same force that makes large codebases exploitable en masse also makes shrinking code into minimal, scrutinized components tractable.

That’s why we’re betting that maintaining our own minimal, purpose-built firmware1 is now a better security posture than adopting a legacy open-source one with 20 years of accumulated features. It also moves us closer to our end goal of formally verifying every part of the confidential VM image on which all of Tinfoil’s security and verifiability rest.

We view this reductionist approach as more pragmatic compared to unleashing swarms of agents to find vulnerabilities and patch them (e.g., OpenAI’s “Patch the Planet”). It costs millions of dollars to red-team large code bases. For example, OpenAI revealed how they’ve burned nearly 400B tokens red-teaming their infrastructure (Figure 1).2 That’s somewhere between $8 and $20M in tokens at current prices, using a frontier cyber model that nobody but them has access to. Patching-with-swarms is unfortunately a strategy that will only be viable for big companies with deep pockets.

Figure 1: Cumulative candidate findings from OpenAI’s red-teaming campaign. Source: OpenAI.

Tinfoil guarantees that we cannot access our customers’ workloads or data, even if an attacker compromises us and steals all our keys. Every workload runs in a secure enclave: a confidential virtual machine whose memory is encrypted by hardware from Intel, AMD and NVIDIA, and which can publicly prove exactly what code it is running.

Traditionally, cloud security meant guarding against a tenant breaking out of their virtual machine, known as the guest-to-host attack surface. At Tinfoil, we’re equally concerned with the opposite, the host-to-guest attack surface: everything we (or whoever has compromised us) could do to break into our tenants’ enclaves. The most critical and exposed moment that attackers can take advantage of is boot, since that’s when the security attestation is generated.

When a secure enclave boots, its initial state is measured by the secure hardware. Then, when the virtual machine has finished booting, it asks the hardware to attest to what was measured. This is how Tinfoil proves what code is running in the enclave for anyone to verify.3

Firmware is software that directly interfaces with hardware; computers need firmware to run at boot time to initialize their hardware. Virtual machines in secure enclaves are no different, and the guest firmware in enclaves has a particularly critical job. In the traditional boot flow, the initial launch of the enclave measures the firmware, which is then responsible for loading and verifying the code that the guest runs after it. In our case, the firmware needed to measure the kernel, the initramfs, and the Linux command line. Because of this critical role, an exploitable bug in the firmware code could allow a malicious host to load arbitrary software, voiding security and verifiability. Figure 2 shows this traditional boot flow.

Figure 2: How a secure enclave traditionally boots. Hardware measures the firmware, which must then interpret host input and measure what runs next.

Our old firmware was OVMF (Open Virtual Machine Firmware), a widely used and accepted firmware for virtual machines. However, this popularity meant interoperability and richness that came with a major security cost: the specification alone is almost 3,000 pages long. Moreover, OVMF contains over a million lines of C code, and there have been multiple critical vulnerabilities found in the codebase already; one vulnerability was found this week in its network stack.4 Why does firmware even have a network stack, you might ask? For network boot, of course! But at Tinfoil, we don’t boot over the network and only ever use a tiny set of the features that OVMF provides out of the box. We deemed OVMF’s large surface area to be a security risk and set out to do something about it.

Instead of taking OVMF and finding all the bugs and hardening it, our strategy was to step back and consider the purpose of virtual machine firmware in the first place. What does OVMF do for us, really? Concretely, the firmware has two main functions that we use it for: (1) booting Linux and (2) linking the launch measurement to the runtime code in the guest.

The hardware’s guarantee covers only what is in memory at launch, and in our legacy boot process, that consisted of OVMF. It was OVMF’s job to load and measure everything else. So the integrity of the operating system depended on the firmware behaving correctly after the launch measurement had already been taken.

It was clear to us that this was too much for the firmware to do. The firmware was an unnecessary link in the measurement and verification chain. Instead, we decided to simplify both our firmware and our verification chain by placing everything needed to bring up Linux in the enclave’s initial launch memory: our new minimal firmware, kernel, initramfs, page tables, fixed ACPI tables and templates, and Linux command line. These are measured at enclave launch, rather than by the firmware, and recorded as a single hash (MRTD on TDX and the launch digest on SEV-SNP). Figure 3 compares the measurement chains.

Figure 3: Tinfoil’s legacy measurement chain (OVMF on TDX) and new measurement chain (IGVM on TDX and SEV-SNP). CPU and memory parameters remain untrusted inputs checked by the firmware.

To describe the initial memory state of our confidential virtual machines, we use the Independent Guest Virtual Machine (IGVM) file format.5 Our CI builds and attests an IGVM file containing a complete layout of what guest memory should look like when an enclave launches. The firmware no longer needs to load or measure things, which makes verification simple: it’s just a hash of this initial build state. Our firmware now has only one job: to boot up Linux! This would already reduce the security risks of a compromised firmware, but we can go even further.

So what do we need to minimally boot Linux in a secure enclave? It turns out not much. On x86, virtual machines need basic CPU features like paging and 64-bit long mode set up, then they can jmp to Linux. The basic transition could probably be achieved with about 20 lines of x86 assembly instructions. During prototyping, though, we found a couple more requirements, such as handling CPU counts and memory layouts, that our firmware also needed to take care of. This is why our final minimal firmware is about 300 lines of code and not 20.

When using IGVM to build and launch our enclaves, the fixed initial boot state is measured at launch. If we had exactly one workload with only one set of resource requirements, this would not be a problem, but we need the ability to launch enclaves with different amounts of memory without having to build separate images. Figure 4 shows one of the memory layouts we support.

Figure 4: Physical memory of an 8 GiB guest on QEMU’s q35 machine.

For Linux to boot, it needs a layout of its physical address space: a memory map. Tinfoil’s enclaves all run with the physical memory mapping predefined, so this means we pre-bake the machine’s memory map during IGVM build time and do not rely on the firmware to define it at runtime. When the enclave launches, it includes an unmeasured memory map with the actual amount of memory it is provisioned with. Our firmware only needs to check that the shape of the memory map matches the pre-built entries. Thus, only the total memory size is determined by the host; if it lies about the shape of memory, the firmware fails the boot process. Overall, this means that the worst-case scenario is when the host lies and under- or overprovisions memory, which simply causes the boot to fail.

Similarly, we need to handle arbitrary CPU types and configurations, without tying the number of CPUs to our build measurement. Linux brings up multiple CPUs by checking ACPI’s MADT table6, using the number of APIC entries to bring up each CPU it was provisioned. Similarly to how we handle variable memory, we minimize the unmeasured data sent from the host and pre-build the ACPI tables. When our minimal firmware runs in the guest, it just needs to check the CPU count for sanity and patch the MADT entry with the number of CPUs needed. If our host lies and gives more or fewer CPUs than it actually provisions for the enclave, either Linux will not bring the extra CPUs up or the extra CPUs will stay parked in an infinite loop, neither of which poses a threat to the confidentiality of the guest’s enclave.

At this point, things are all set up for Linux. The Linux x86 boot protocol requires a setup header that points to the kernel, the initramfs, and the command line, all of which are already mapped into memory at enclave launch.7 So all our firmware needs to do is jump to Linux! Concretely, the handoff in our firmware looks like:

mov $ZERO_PAGE, %rsi mov $KERNEL_ENTRY, %eax jmp *%rax

And our firmware never runs again. The entire workload continues in Linux with no more after-boot firmware attack surface to speak of.

Here’s where everything OVMF did for us ended up. Roughly speaking, each job either moved earlier, to build time, where the result gets measured; moved later, to Linux; or got deleted. Table 1 shows the breakdown.

Table 1: Firmware jobs grouped by destination. Most move to build time, launch, or Linux, or disappear entirely. Only two bounded host-configuration checks remain in the firmware.

Under OVMF, there were eight different places where guest code parsed bytes the

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →