← ALL ADVISORIES

HIGH BYTERAY-2026-0213Disclosed

U-Boot — Out-of-Bounds Write in the BMP RLE8 Decoder

U-Boot's RLE8 bitmap decoder does not bound its writes to the framebuffer, so a crafted RLE8-compressed BMP decoded during boot writes past the end of the framebuffer and corrupts adjacent memory inside the bootloader.

Advisory
BYTERAY-2026-0213
CVE
CVE-2026-71972
CWE
CWE-787
CVSS
6.0 (CVSS:4.0/AV:A/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N); 5.9 (CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:H)
Vendor
U-Boot
Product
U-Boot
Reported
2026-07-29
Disclosure
2026-09-29
Affected
U-Boot through 2026.10-rc5
Fixed in
Commit 5201e83342d64c2f438ea35158575f28225e752e (in u-boot/next; not yet in a tagged release)

Executive Summary

U-Boot decodes a boot logo or splash image during the boot flow. The decoder for RLE8-compressed BMP images does not bound its writes to the framebuffer, so a crafted image writes past the end of it. The logo is commonly loaded from unsigned, attacker-writable storage and decoded before the next boot stage is authenticated, which places an attacker-controlled memory-corruption primitive inside the component that enforces verified boot.

Affected Products and Versions

  • Product: U-Boot, BMP RLE8 decode path in drivers/video/video_bmp.c (video_display_rle8_bitmap()).
  • Affected: U-Boot through 2026.10-rc5.
  • Fixed: commit 5201e83342d64c2f438ea35158575f28225e752e, present in the u-boot/next branch; at the time of writing it is not yet in a tagged release.

Technical Details

video_display_rle8_bitmap() decodes an RLE8-compressed 8-bit BMP straight into the framebuffer. RLE8 is a sequence of opcodes: a run of one color, a run of literal bytes, an end-of-line marker, an end-of-bitmap marker, and a delta that jumps the write cursor. BMP scanlines are stored bottom to top, so the decoder starts at the bottom row of the framebuffer and walks upward, moving to the next row on each end-of-line marker.

The write cursor is the pointer fb. The end-of-line handler moves it toward lower addresses by one row on every marker, and checks no lower bound:

case BMP_RLE8_EOL:            /* end of line */
    bmap += 2;
    x = 0;
    y--;
    fb -= width * bytes_per_pixel + priv->line_length;
    break;

The only bounds check near the writes is on the logical row counter y, not on fb:

default:                      /* unencoded run */
    runlen = bmap[1];
    bmap += 2;
    if (y < height) {                       /* checks the row, never fb */
        if (x < width) {
            ...
            draw_unencoded_bitmap(&fb, bpix, eformat, bmap, palette, cnt);
        }
        x += runlen;
    }

y and fb are advanced by different opcodes: the end-of-line marker moves fb, while the run opcodes advance the image, so the two drift apart. An attacker sends N end-of-line markers with N smaller than the image height. y counts down from height - 1 and stays a small positive value that keeps passing the y < height guard, while fb slides N * (width * bytes_per_pixel + line_length) bytes below the start of the framebuffer. A single unencoded run after that copies attacker-controlled bytes through the drifted fb, writing out of bounds below the framebuffer (an underwrite) at an attacker-chosen distance. The delta opcode has the same defect: it recomputes fb from the unchecked y, so it can place the cursor at an arbitrary offset.

When the framebuffer is 8 bits per pixel the decoder stores each palette index directly (*fb++ = *bmap), so every byte written is a raw attacker byte at the target address, which gives byte-exact control over the out-of-bounds write. Deeper framebuffers map the index through the palette before storing it, which still corrupts memory but removes that byte-exact control.

On the SoCs whose display controller scans out from DRAM (for example NXP i.MX6, Amlogic Meson, STMicro STM32), U-Boot places the framebuffer at the top of RAM directly above its own relocated image, so walking fb below the framebuffer walks it into U-Boot's own code and function-pointer tables. The vulnerable path is built when CONFIG_VIDEO_BMP_RLE8 is enabled.

Reachability and Preconditions

  • The device decodes a boot logo or splash BMP during boot.
  • The attacker can place a crafted BMP in the storage U-Boot reads the logo from. This storage is commonly unsigned and attacker-writable, and the decode runs before the next stage is authenticated.

Impact

An out-of-bounds write corrupting memory adjacent to the framebuffer and crashing the bootloader. Because the decode runs inside U-Boot, the verified-boot enforcer, before the next stage is authenticated, the primitive can corrupt the verification logic and bypass secure boot.

Remediation and Mitigation

Update U-Boot to a build containing commit 5201e83342d64c2f438ea35158575f28225e752e (currently in u-boot/next). Where the boot logo is loaded from untrusted storage, restrict write access to that storage until the fix is deployed.

Timeline

  • 2026-07-29 — Vulnerability public and fix available upstream.
  • 2026-07-29 — Fix committed to u-boot/next (commit 5201e83342d64c2f438ea35158575f28225e752e); not yet in a tagged release.
  • 2026-09-29 — CVE-2026-71972 record published by VulnCheck.

Credits

Discovered and reported by Shahriyar Jalayeri and Mehrun P. Hunter of ByteRay Ltd.

References