Skip to content

pkg/boot/universalpayload: enhance security and robustness of bootloader components#3570

Open
pohaosu wants to merge 7 commits into
u-root:mainfrom
pohaosu:robust-upl
Open

pkg/boot/universalpayload: enhance security and robustness of bootloader components#3570
pohaosu wants to merge 7 commits into
u-root:mainfrom
pohaosu:robust-upl

Conversation

@pohaosu

@pohaosu pohaosu commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR addresses several security vulnerabilities and robustness issues identified in the pkg/boot/universalpayload package. These improvements ensure the bootloader is resilient against malformed or malicious FIT images
and correctly handles dynamic state during the component allocation process.

Key Changes

1. State Accumulation Fix

Moved the global componentsSize reset to loadKexecMemWithHOBs(). This prevents persistent allocation failures that could occur if state accumulated across multiple calls (e.g., failed boot retries).

2. Out-of-Bounds Panic Mitigation

  • PE Relocation: Fixed an insufficient bounds check in relocatePE (DIR64 relocation) that could trigger a panic when reading/writing at the end of the data buffer.
  • FIT Extraction: Added strict slice bounds validation in relocateFdtData for FIT sub-image extraction to prevent panics from malicious data-offset or data-size properties.

3. Secure FDT Generation

Refactored buildDeviceTreeInfo to rely on fdt.Write() for automatic header field population (TotalSize, Offsets, Sizes). This eliminates risky and redundant manual offset patching.

4. Trampoline Underflow Protection

Added safety checks in ARM64 and AMD64 trampoline padding calculations:

  • Technical Detail: In ARM64, gapLen = stackOffset - codeSize. If the trampoline function crosses a memory page boundary, stackOffset can be smaller than codeSize, causing an underflow to a massive value. This fix
    prevents a subsequent OOM panic during memory allocation.

5. Sysfs Robustness

Added string length validation when parsing framebuffer resources from sysfs to prevent panics on malformed or unexpected system file content.

6. Bug Fixes

  • Corrected a typo in the ARM64 TinyGo implementation (trampolineOffse -> trampolineOffset).

Verification

All changes have been verified with existing package tests and new regression tests integrated directly into universalpayload_test.go and utilities_test.go.

  • Package: github.com/u-root/u-root/pkg/boot/universalpayload
  • Total Tests: 42
  • Result: PASS

pohaosu added 6 commits April 9, 2026 17:11
Resets the global componentsSize counter at the start of component allocation
to prevent persistent allocation failures via state accumulation across
multiple calls.

Signed-off-by: Phineas Su <pohaosu@google.com>
…sing

- Fixes an insufficient bounds check in relocatePE (DIR64 relocation).
- Adds slice bounds validation in relocateFdtData for FIT sub-image extraction.

Signed-off-by: Phineas Su <pohaosu@google.com>
Relies on fdt.Write() to correctly calculate and populate FDT header fields
(TotalSize, Offsets, Sizes), removing redundant and risky manual patching.

Signed-off-by: Phineas Su <pohaosu@google.com>
…nstruction

In ARM64, gapLen = stackOffset - codeSize where stackOffset is the relative
position of the stack label within its page. If the trampoline function
crosses a page boundary, stackOffset will be smaller than codeSize, causing
an underflow to a massive value and a subsequent OOM panic during allocation.
Similar protections added to AMD64.

Signed-off-by: Phineas Su <pohaosu@google.com>
Adds length validation when parsing framebuffer sysfs resource strings to
prevent panics on malformed or unexpected system file content.

Signed-off-by: Phineas Su <pohaosu@google.com>
Corrects trampolineOffse to trampolineOffset.

Signed-off-by: Phineas Su <pohaosu@google.com>
@codecov

codecov Bot commented Apr 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.36214% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.13%. Comparing base (3769fe3) to head (dce99d3).
⚠️ Report is 54 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3570      +/-   ##
==========================================
+ Coverage   60.70%   61.13%   +0.43%     
==========================================
  Files         652      659       +7     
  Lines       45516    46558    +1042     
==========================================
+ Hits        27630    28464     +834     
- Misses      17886    18094     +208     
Flag Coverage Δ
.-amd64 90.90% <ø> (ø)
cmds/...-amd64 52.43% <ø> (+0.21%) ⬆️
integration/generic-tests/...-amd64 30.31% <11.26%> (-0.14%) ⬇️
integration/generic-tests/...-arm 33.35% <ø> (+0.37%) ⬆️
integration/generic-tests/...-arm64 28.79% <11.16%> (-0.84%) ⬇️
integration/gotests/...-amd64 60.84% <78.82%> (+0.61%) ⬆️
integration/gotests/...-arm 61.22% <76.05%> (+0.37%) ⬆️
integration/gotests/...-arm64 61.31% <78.57%> (+0.33%) ⬆️
pkg/...-amd64 58.88% <77.92%> (+0.34%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
everything 65.95% <84.36%> (+0.38%) ⬆️
cmds/exp 34.18% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pkg/boot/universalpayload/utilities_test.go Outdated
@pohaosu pohaosu requested a review from rminnich April 22, 2026 13:11
@pohaosu pohaosu force-pushed the robust-upl branch 2 times, most recently from d73b572 to 0d891f2 Compare June 15, 2026 01:52
Moved all mutable state, configuration paths, and mockable function
pointers from package-level variables into a new UPL struct. Refactored
package-level functions into methods of the UPL struct to ensure
internal thread-safety and prevent data races when loading multiple
payloads concurrently.

Implemented a New() constructor with functional options for safe
configuration and isolation. Updated all tests to use UPL instances,
eliminating the need for global state overrides during testing.

Signed-off-by: Phineas Su <pohaosu@google.com>
@pohaosu

pohaosu commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@rminnich, just a gentle ping; would you mind taking a look at dce99d3 when you have a moment? thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants