GNU bug report logs -
#78880
od Heap-buffer overflow
Previous Next
Full log
View this message in rfc822 format
[Message part 1 (text/plain, inline)]
Your message dated Tue, 24 Jun 2025 15:03:41 +0100
with message-id <86c59eab-356b-49ce-bdbd-2b2ce5376afc <at> draigBrady.com>
and subject line Re: bug#78880: od Heap-buffer overflow
has caused the debbugs.gnu.org bug report #78880,
regarding od Heap-buffer overflow
to be marked as done.
(If you believe you have received this mail in error, please contact
help-debbugs <at> gnu.org.)
--
78880: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=78880
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
[Message part 3 (text/plain, inline)]
*###### Build options*```
git clone https://github.com/coreutils/coreutils
export GNULIB_SRCDIR=./gnulib
export FORCE_UNSAFE_CONFIGURE=1
./bootstrap
CC="clang -g -fsanitize=address" CXX="clang -g -fsanitize=address"
./configure $CONFIG_OPTIONS
make -j
```
*###### od version*```
$ src/od --version
od (GNU coreutils) 9.7.52-b7db77
Copyright (C) 2025 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.
```
*###### reproduce script*```c
// gcc -o replay_od replay_od.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_CMDLINE_LEN 100000
#define MAX_CMDLINE_PAR 1000
int main() {
static char in_buf[MAX_CMDLINE_LEN];
static char *argv[MAX_CMDLINE_PAR];
char *ptr = in_buf;
int rc = 0;
int n = read(0, in_buf, MAX_CMDLINE_LEN - 2);
if (n <= 0) {
perror("read");
exit(1);
}
while (*ptr) {
argv[rc] = ptr;
if (argv[rc][0] == 0x02 && !argv[rc][1]) {
argv[rc]++;
}
rc++;
while (*ptr) ptr++;
ptr++;
}
argv[0] = "od";
// exec od with parsed argv
execvp("src/od", argv);
perror("execvp failed");
return 1;
}
```
This is a C wrapper program that automatically sets argv to reproduce the
vulnerability. It is a simple wrapper around the od program and does not
modify the original od binary.
###### ASAN log
```
$ ./replay_od < /root/250623/od-poc
od: 'u'$'\353''d'$'\001''4
'\'''$'\350\003\346\346\346\346\027\027\027\027\027\027\027\027''!'$'\027\027\027\027\027\027\027\027\027\027\027\027\027\027\027\027''{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{'$'\024''{{{{'$'\200\016\377\377''{{{{{{{{{{{s{{'$'\220''{{{{'$'\213\207\213\213\213\213\213\213\213\213\213\213\213\213''}'$'\213\213\213\213\213\213\213\213\213\213''E':
No such file or directory
=================================================================
==1151699==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x6150000004f9 at pc 0x0000004d153f bp 0x7fff937f0410 sp 0x7fff937f0408
WRITE of size 1 at 0x6150000004f9 thread T0
#0 0x4d153e in dump_strings coreutils/src/od.c:1570:14
#1 0x4d153e in main coreutils/src/od.c:2037:30
#2 0x7fc132ca6d8f in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#3 0x7fc132ca6e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#4 0x41f664 in _start (coreutils/src/od+0x41f664)
0x6150000004f9 is located 0 bytes to the right of 505-byte region
[0x615000000300,0x6150000004f9)
allocated by thread T0 here:
#0 0x49c843 in __interceptor_realloc (coreutils/src/od+0x49c843)
#1 0x4ddcea in rpl_realloc coreutils/./lib/stdlib.h:2095:10
#2 0x4ddcea in xrealloc coreutils/lib/xmalloc.c:66:13
#3 0x4ddcea in xpalloc coreutils/lib/xmalloc.c:271:8
#4 0x7fc132ca6d8f in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: heap-buffer-overflow coreutils/src/od.c:1570:14
in dump_strings
Shadow bytes around the buggy address:
0x0c2a7fff8040: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x0c2a7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2a7fff8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[01]
0x0c2a7fff80a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff80b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff80c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff80d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff80e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==1151699==ABORTING
```
*###### Description*
```
1513 static bool
1514 dump_strings (void)
1515 {
1516 idx_t bufsize = MAX (100, string_min);
1517 char *buf = xmalloc (bufsize);
...
1550 while (!limit_bytes_to_format || address < end_offset)
1551 {
1552 if (i == bufsize)
1553 buf = xpalloc (buf, &bufsize, 1, -1, sizeof *buf);
1554 ok &= read_char (&c);
1555 address++;
1556 if (c < 0)
1557 {
1558 free (buf);
1559 return ok;
1560 }
1561 if (c == '\0')
1562 break; /* It is; print this string. */
1563 if (! isprint (c))
1564 goto tryline; /* It isn't; give up on this string.
*/
1565 buf[i++] = c; /* String continues; store it all. */
1566 }
...
1570 buf[i] = 0;
1571 format_address (address - i - 1, ' ');
```
The vulnerability occurs in the dump_strings function. The variable buf is
allocated with a size of bufsize, which is limited to a maximum of 100
bytes.
However, inside the while loop, the variable i is incremented by 1 on each
iteration. When the attached PoC file is passed as arguments to the od
program, the value of i can exceed 100. This leads to a heap buffer
overflow vulnerability.
An attacker could potentially exploit this by manipulating both the i and c
values, resulting in dangerous modifications to the buf chunk on the heap.
Therefore, we recommend adding proper bounds checking for the i variable to
prevent this issue.
[Message part 4 (text/html, inline)]
[od-poc (application/octet-stream, attachment)]
[replay_od.c (application/octet-stream, attachment)]
[Message part 7 (message/rfc822, inline)]
[Message part 8 (text/plain, inline)]
On 24/06/2025 01:16, Pádraig Brady wrote:
> On 23/06/2025 09:24, Jaehoon Jang wrote:
>> =================================================================
>> ==1151699==ERROR: AddressSanitizer: heap-buffer-overflow on address
>> 0x6150000004f9 at pc 0x0000004d153f bp 0x7fff937f0410 sp 0x7fff937f0408
>> WRITE of size 1 at 0x6150000004f9 thread T0
>> #0 0x4d153e in dump_strings coreutils/src/od.c:1570:14
>
> Nice fuzzing.
>
> There looks to be all sorts of off by one errors in the dump_strings() function.
> The issue is most easily demonstrated with:
>
> printf '%100s' | tr ' ' . | valgrind od -N100 -S99
>
> The following should fix this I think.
> I've only analyzed it for a few minutes, so I'll look more tomorrow.
> The following should also fix the printed offset,
> and also support the -N100 -S100 combination.
The previous patch didn't handle the invalid address output in all cases.
Also I didn't see a need for both read() loops in this function,
so I simplified the function in the attached more complete patch.
Marking this as done.
I'll apply this later.
thanks again,
Padraig.
[0001-od-fix-various-off-by-one-issues-with-strings-with-N.patch (text/x-patch, attachment)]
This bug report was last modified 52 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.