[Bug 290409] DD integer and Heap Overflow

From: <bugzilla-noreply_at_freebsd.org>
Date: Tue, 21 Oct 2025 19:59:52 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=290409

            Bug ID: 290409
           Summary: DD integer and Heap Overflow
           Product: Base System
           Version: 14.3-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: igor@bsdtrust.com

Where the bug is:
- https://github.com/freebsd/freebsd-src/blob/main/bin/dd/dd.c

The vulnerable point is inside the `setup()` function:

```c
if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
    if ((in.db = malloc((size_t)out.dbsz + in.dbsz - 1)) == NULL)
        err(1, "input buffer");
    out.db = in.db;
}
```

Problem:

The values `in.dbsz` and `out.dbsz` come from command-line arguments (`ibs=`,
`obs=`, or `bs=`).

Both are `size_t`, but they can be assigned from an integer without validation,
coming from argv parsing.

The calculation `(size_t)out.dbsz + in.dbsz - 1` can exceed `SIZE_MAX`, which
causes an arithmetic overflow and the result wraps to a small value —
`malloc()` then allocates less memory than the code expects.

Later the program writes `in.dbsz` bytes into the buffer that, in theory,
should have at least `out.dbsz + in.dbsz` bytes → real heap overflow.

How to reproduce (trigger)

Scenario:

You want `(out.dbsz + in.dbsz - 1) > SIZE_MAX`.

On FreeBSD amd64, `size_t` is 64 bits (`SIZE_MAX = 0xffffffffffffffff`).

So, to overflow:

```
in.dbsz + out.dbsz - 1 > 2^64 - 1
```

But you don't need to reach `2^64` exactly.
If parsing in `jcl()` uses an intermediate `unsigned int` (32 bits), the
overflow happens much earlier.

The `jcl()` parser (in `args.c`) converts arguments like `ibs=1024` using
`strtoumax()`, but there are older builds where it stores the value into
`u_int`. Even on 64-bit builds, the sum can overflow on the cast if `in.dbsz`
and `out.dbsz` come close to `SIZE_MAX`.

Safe execution (VM)

1. Create a small test file:

```
dd if=/dev/zero of=infile bs=1M count=1
```

2. Run `dd` with absurdly large buffers:

```
/usr/bin/dd if=infile of=outfile ibs=9223372036854775800
obs=9223372036854775800
```

(≈ 9.22e18 bytes, or `0x7ffffffffffffff8`)

This makes the calculation overflow and `malloc()` receives a small value, e.g.
`0xFFFFFFFFFFFFFFEF`, depending on the cast.

3. Run inside a VM with Valgrind:

```
valgrind ./dd if=infile of=outfile ibs=9223372036854775800
obs=9223372036854775800
```

You should see something like:

```
root@igor:~ # valgrind dd if=infile of=outfile ibs=9223372036854775800
obs=9223372036854775800
==951== Memcheck, a memory error detector
==951== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==951== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==951== Command: dd if=infile of=outfile ibs=9223372036854775800
obs=9223372036854775800
==951==
==951== Argument 'size' of function malloc has a fishy (possibly negative)
value: -17
==951== at 0x4859304: malloc (vg_replace_malloc.c:450)
==951== by 0x4005C99: ??? (in /bin/dd)
==951== by 0x4907E33: __libc_start1 (in /lib/libc.so.7)
==951== by 0x40045B0: ??? (in /bin/dd)
==951== by 0x482F007: ???
==951==
dd: input buffer: Cannot allocate memory
==951==
==951== HEAP SUMMARY:
==951== in use at exit: 104,220 bytes in 8 blocks
==951== total heap usage: 11 allocs, 3 frees, 104,454 bytes allocated
==951==
==951== LEAK SUMMARY:
==951== definitely lost: 48 bytes in 2 blocks
==951== indirectly lost: 0 bytes in 0 blocks
==951== possibly lost: 21 bytes in 2 blocks
==951== still reachable: 104,151 bytes in 4 blocks
==951== suppressed: 0 bytes in 0 blocks
==951== Rerun with --leak-check=full to see details of leaked memory
==951==
==951== For lists of detected and suppressed errors, rerun with: -s
==951== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```

This confirms heap corruption.

```
dd if=infile of=outfile ibs=9223372036854775800 obs=9223372036854775800
```
Author: Igor Gabriel Sousa e Souza 
Email: igor@bsdtrust.com
LinkedIn: https://www.linkedin.com/in/igo0r

Best Regards!

-- 
You are receiving this mail because:
You are the assignee for the bug.