Dear maintainers,


We have found an issue in u-boot that can lead to an Out-of-Bounds error when 
compiled with ASAN.

The details of the issue are as follows:


Issue Description:

Crash reproduced by `poc.sh` feeds a crafted IPv6 packet with a incorrect 
payload length into the `net_process_received_packet @ net/net.c`.



Vulnerable path:

     - `net_process_received_packet` -> `net_ip6_handler` -> `csum_partial` -> 
`csum_do_csum`



Root cause:
`net_ip6_handler()` trusts the IPv6 `payload_len` and computes checksums over 
`hlen = ntohs(ip6->payload_len)` without verifying that the incoming frame 
contains that many bytes.

With a truncated frame and a large `payload_len`, `csum_partial()` reads past 
the end of the RX buffer, causing a buffer overflow that is caught by ASAN.



Modifications to u-boot

In order to reproduce this issue, we have implemented a `sb netrx` hook in 
`cmd/sb.c` that allows injecting arbitrary raw Ethernet RX frames into the 
networking stack.

The existing sandbox net driver only auto-generates limited packets (e.g. 
ARP/ping) and cannot deliver a crafted IPv6 frame with a bogus `payload_len`. 

The `sb netrx` hook is a minimal injection path that calls 
`net_process_received_packet()` directly on a buffer loaded into RAM, which is 
required to hit `net_ip6_handler()`.




```

diff --git a/cmd/sb.c b/cmd/sb.c

index 79f3fb0aacd..8e7604a13c4 100644

--- a/cmd/sb.c

+++ b/cmd/sb.c

@@ -6,6 +6,10 @@



#include <command.h>

#include <dm.h>

+#include <malloc.h>

+#include <mapmem.h>

+#include <net.h>

+#include <string.h>

#include <spl.h>

#include <asm/cpu.h>

#include <asm/global_data.h>

@@ -47,12 +51,52 @@ static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int 
argc,

return 0;

}



+static int do_sb_netrx(struct cmd_tbl *cmdtp, int flag, int argc,

+                      char *const argv[])

+{

+       ulong addr;

+       unsigned int len;

+       uchar *buf;

+       uchar stack_buf[256];

+       bool heap = false;

+       void *src;

+

+       if (argc != 3)

+               return CMD_RET_USAGE;

+

+       addr = hextoul(argv[1], NULL);

+       len = dectoul(argv[2], NULL);

+

+       if (len > sizeof(stack_buf)) {

+               buf = malloc(len);

+               if (!buf)

+                       return CMD_RET_FAILURE;

+               heap = true;

+       } else {

+               buf = stack_buf;

+       }

+       src = map_sysmem(addr, len);

+       if (!src) {

+               free(buf);

+               return CMD_RET_FAILURE;

+       }

+       memcpy(buf, src, len);

+       unmap_sysmem(src);

+       net_process_received_packet(buf, len);

+       if (heap)

+               free(buf);

+

+       return 0;

+}

+

U_BOOT_LONGHELP(sb,

"handoff     - Show handoff data received from SPL\n"

"sb map         - Show mapped memory\n"

-       "sb state       - Show sandbox state");

+       "sb state       - Show sandbox state\n"

+       "sb netrx <addr> <len> - inject a raw RX packet into net stack");



U_BOOT_CMD_WITH_SUBCMDS(sb, "Sandbox status commands", sb_help_text,

U_BOOT_SUBCMD_MKENT(handoff, 1, 1, do_sb_handoff),

U_BOOT_SUBCMD_MKENT(map, 1, 1, do_sb_map),

-       U_BOOT_SUBCMD_MKENT(state, 1, 1, do_sb_state));

+       U_BOOT_SUBCMD_MKENT(state, 1, 1, do_sb_state),

+       U_BOOT_SUBCMD_MKENT(netrx, 3, 1, do_sb_netrx));

```




Proposed Patch:

The patch proposed by our system verifies that the payload length is within 
bounds of the packet data before computing the checksum thus avoiding the 
Out-of-Bounds access.



```

diff --git a/net/net6.c b/net/net6.c

index 4cff98df15c..8453c1ca754 100644

--- a/net/net6.c

+++ b/net/net6.c

@@ -397,6 +397,9 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr 
*ip6, int len)

                icmp = (struct icmp6hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);

                csum = icmp->icmp6_cksum;

                hlen = ntohs(ip6->payload_len);

+               /* Validate payload length doesn't exceed available data */

+               if (hlen > len - IP6_HDR_SIZE)

+                       hlen = len - IP6_HDR_SIZE;

                icmp->icmp6_cksum = 0;

                /* checksum */

                csum_p = csum_partial((u8 *)icmp, hlen, 0);

@@ -424,6 +427,9 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr 
*ip6, int len)

                udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);

                csum = udp->udp_xsum;

                hlen = ntohs(ip6->payload_len);

+               /* Validate payload length doesn't exceed available data */

+               if (hlen > len - IP6_HDR_SIZE)

+                       hlen = len - IP6_HDR_SIZE;

                udp->udp_xsum = 0;

                /* checksum */

                csum_p = csum_partial((u8 *)udp, hlen, 0);



```


Crash backtrace:

```

=================================================================

==39394==ERROR: AddressSanitizer: stack-buffer-overflow on address 
0xffffd7aea450 at pc 0xaaaacf7407fc bp 0xffffd7aea100 sp 0xffffd7aea0f0

READ of size 4 at 0xffffd7aea450 thread T0

    #0 0xaaaacf7407f8 in csum_do_csum net/net6.c:215

    #1 0xaaaacf7407f8 in csum_partial.constprop.0 net/net6.c:245

    #2 0xaaaacf5d0510 in net_ip6_handler net/net6.c:429

    #3 0xaaaacf5d0510 in net_process_received_packet net/net.c:1282

    #4 0xaaaacf345788 in do_sb_netrx cmd/sb.c:85

    #5 0xaaaacf3847a8 in cmd_call common/command.c:582

    #6 0xaaaacf3847a8 in cmd_process common/command.c:637

    #7 0xaaaacf37b5d4 in run_pipe_real common/cli_hush.c:1674

    #8 0xaaaacf37b5d4 in run_list_real common/cli_hush.c:1870

    #9 0xaaaacf37c2e0 in run_list common/cli_hush.c:2019

    #10 0xaaaacf37c2e0 in parse_stream_outer common/cli_hush.c:3209

    #11 0xaaaacf37c868 in parse_string_outer common/cli_hush.c:3275

    #12 0xaaaacf754940 in run_command_list.constprop.0 common/cli.c:149

    #13 0xaaaacf2bc980 in sandbox_main_loop_init arch/sandbox/cpu/start.c:145

    #14 0xaaaacf2bc980 in run_main_loop common/board_r.c:583

    #15 0xaaaacf2bc980 in initcall_run_r common/board_r.c:783

    #16 0xaaaacf2bc980 in board_init_r common/board_r.c:813

    #17 0xaaaacf2bc980 in sandbox_main arch/sandbox/cpu/start.c:584

    #18 0xffffba7d73fc  (/lib/aarch64-linux-gnu/libc.so.6+0x273fc)

    #19 0xffffba7d74d4 in __libc_start_main 
(/lib/aarch64-linux-gnu/libc.so.6+0x274d4)

    #20 0xaaaacf2ac9ec in _start 
(/src/simulation_environments/xxx_uboot_issue_1/sources/xxx_uboot_issue_1/u-boot+0x27c9ec)



Address 0xffffd7aea450 is located in stack of thread T0 at offset 288 in frame

    #0 0xaaaacf345634 in do_sb_netrx cmd/sb.c:56



  This frame has 1 object(s):

    [32, 288) 'stack_buf' (line 60) <== Memory access at offset 288 overflows 
this variable

HINT: this may be a false positive if your program uses some custom stack 
unwind mechanism, swapcontext or vfork

      (longjmp and C++ exceptions *are* supported)

SUMMARY: AddressSanitizer: stack-buffer-overflow net/net6.c:215 in csum_do_csum

Shadow bytes around the buggy address:

  0x200ffaf5d430: f1 f1 04 f2 04 f2 04 f2 04 f2 04 f2 04 f2 04 f2

  0x200ffaf5d440: 04 f2 04 f2 04 f2 00 00 f2 f2 00 00 04 f2 f2 f2

  0x200ffaf5d450: f2 f2 06 f3 f3 f3 00 00 00 00 00 00 00 00 00 00

  0x200ffaf5d460: 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00

  0x200ffaf5d470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

=>0x200ffaf5d480: 00 00 00 00 00 00 00 00 00 00[f3]f3 f3 f3 f3 f3

  0x200ffaf5d490: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  0x200ffaf5d4a0: 00 00 00 00 f1 f1 f1 f1 04 f3 f3 f3 00 00 00 00

  0x200ffaf5d4b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  0x200ffaf5d4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

  0x200ffaf5d4d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Shadow byte legend (one shadow byte represents 8 application bytes):

  Addressable:           00

  Partially addressable: 01 02 03 04 05 06 07

  Heap left redzone:       fa

  Freed heap region:       fd

  Stack left redzone:      f1

  Stack mid redzone:       f2

  Stack right redzone:     f3

  Stack after return:      f5

  Stack use after scope:   f8

  Global redzone:          f9

  Global init order:       f6

  Poisoned by user:        f7

  Container overflow:      fc

  Array cookie:            ac

  Intra object redzone:    bb

  ASan internal:           fe

  Left alloca redzone:     ca

  Right alloca redzone:    cb

  Shadow gap:              cc

==39394==ABORTING

```



Reproduction Steps:

```

chmod +x build.sh poc.sh



# This clones the latest source code of u-boot from  
https://source.denx.de/u-boot/u-boot.git 

# applies the patch for `sb netrx`
# and compiles the sandbox it with ASAN

./build.sh



# This crafts an IPv6 packet with an arbitrary payload length

# and invokes the `sb netrx` command with the crafted packet
./poc.sh

```


build.sh

```

#!/usr/bin/env bash

set -euo pipefail



ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

UBOOT_DIR="$ROOT_DIR/u-boot"



if [ ! -d "$UBOOT_DIR" ]; then

    git clone https://source.denx.de/u-boot/u-boot.git  "$UBOOT_DIR"

    patch -d "$UBOOT_DIR" -p1 < ../u-boot.patch

fi



cd "$UBOOT_DIR"



make sandbox_defconfig

./scripts/config --file .config -e ASAN

make olddefconfig

make -j"$(nproc)"



printf 'Built ASAN sandbox U-Boot at %s\n' "$UBOOT_DIR/u-boot"

```



poc.sh

```

#!/usr/bin/env bash

set -euo pipefail



ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

UBOOT="$ROOT_DIR/u-boot/u-boot"

POC_BIN="$ROOT_DIR/ipv6_trunc.bin"



POC_BIN="$POC_BIN" python3 - <<'PY'

import struct

import os

pkt = bytearray()

pkt += b'\xff' * 6 + b'\x00' * 6 + struct.pack('!H', 0x86dd)

pkt += bytes([0x60, 0, 0, 0])          # v6 header

pkt += struct.pack('!H', 0xffff)       # payload_len (bogus)

pkt += bytes([17, 64])                 # next header=UDP, hop limit

pkt += b'\x00' * 32                    # src/dst

open(os.environ["POC_BIN"], "wb").write(pkt)

print(len(pkt))

PY



ASAN_OPTIONS=detect_leaks=0 \

"$UBOOT" -c "load hostfs - 0x100000 ipv6_trunc.bin && sb netrx 0x100000 54"

```



All the necessary files are also attached with this email.

Please investigate this issue.



Thank you for your time.
54
Bloblist at 100 not found (err=-2)


U-Boot 2026.04-rc1 (Jan 29 2026 - 07:29:07 +0000)

DRAM:  256 MiB
Core:  29 devices, 15 uclasses, devicetree: board, universal payload active
NAND:  0 MiB
MMC:   
Loading Environment from nowhere... OK
Warning: device tree node '/config/environment' not found
In:    serial
Out:   serial,vidconsole
Err:   serial,vidconsole
Net:         eth_initialize() No ethernet found.

54 bytes read in 0 ms
=================================================================
==39394==ERROR: AddressSanitizer: stack-buffer-overflow on address 
0xffffd7aea450 at pc 0xaaaacf7407fc bp 0xffffd7aea100 sp 0xffffd7aea0f0
READ of size 4 at 0xffffd7aea450 thread T0
    #0 0xaaaacf7407f8 in csum_do_csum net/net6.c:215
    #1 0xaaaacf7407f8 in csum_partial.constprop.0 net/net6.c:245
    #2 0xaaaacf5d0510 in net_ip6_handler net/net6.c:429
    #3 0xaaaacf5d0510 in net_process_received_packet net/net.c:1282
    #4 0xaaaacf345788 in do_sb_netrx cmd/sb.c:85
    #5 0xaaaacf3847a8 in cmd_call common/command.c:582
    #6 0xaaaacf3847a8 in cmd_process common/command.c:637
    #7 0xaaaacf37b5d4 in run_pipe_real common/cli_hush.c:1674
    #8 0xaaaacf37b5d4 in run_list_real common/cli_hush.c:1870
    #9 0xaaaacf37c2e0 in run_list common/cli_hush.c:2019
    #10 0xaaaacf37c2e0 in parse_stream_outer common/cli_hush.c:3209
    #11 0xaaaacf37c868 in parse_string_outer common/cli_hush.c:3275
    #12 0xaaaacf754940 in run_command_list.constprop.0 common/cli.c:149
    #13 0xaaaacf2bc980 in sandbox_main_loop_init arch/sandbox/cpu/start.c:145
    #14 0xaaaacf2bc980 in run_main_loop common/board_r.c:583
    #15 0xaaaacf2bc980 in initcall_run_r common/board_r.c:783
    #16 0xaaaacf2bc980 in board_init_r common/board_r.c:813
    #17 0xaaaacf2bc980 in sandbox_main arch/sandbox/cpu/start.c:584
    #18 0xffffba7d73fc  (/lib/aarch64-linux-gnu/libc.so.6+0x273fc)
    #19 0xffffba7d74d4 in __libc_start_main 
(/lib/aarch64-linux-gnu/libc.so.6+0x274d4)
    #20 0xaaaacf2ac9ec in _start 
(/src/simulation_environments/xxx_uboot_issue_1/sources/xxx_uboot_issue_1/u-boot+0x27c9ec)

Address 0xffffd7aea450 is located in stack of thread T0 at offset 288 in frame
    #0 0xaaaacf345634 in do_sb_netrx cmd/sb.c:56

  This frame has 1 object(s):
    [32, 288) 'stack_buf' (line 60) <== Memory access at offset 288 overflows 
this variable
HINT: this may be a false positive if your program uses some custom stack 
unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow net/net6.c:215 in csum_do_csum
Shadow bytes around the buggy address:
  0x200ffaf5d430: f1 f1 04 f2 04 f2 04 f2 04 f2 04 f2 04 f2 04 f2
  0x200ffaf5d440: 04 f2 04 f2 04 f2 00 00 f2 f2 00 00 04 f2 f2 f2
  0x200ffaf5d450: f2 f2 06 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
  0x200ffaf5d460: 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00
  0x200ffaf5d470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x200ffaf5d480: 00 00 00 00 00 00 00 00 00 00[f3]f3 f3 f3 f3 f3
  0x200ffaf5d490: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x200ffaf5d4a0: 00 00 00 00 f1 f1 f1 f1 04 f3 f3 f3 00 00 00 00
  0x200ffaf5d4b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x200ffaf5d4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x200ffaf5d4d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==39394==ABORTING

Attachment: build.sh
Description: Binary data

Attachment: poc.sh
Description: Binary data

Attachment: proposed_patch.diff
Description: Binary data

Attachment: u-boot.patch
Description: Binary data

Reply via email to