32-bit Integer Overflow in dlt_logstorage_prepare_msg_cache Leads to Heap Buffer Overflow
- Dominant language
- C
- Stars
- 459
- Forks
- 340
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 2
Description
## Summary
Unchecked integer arithmetic in FileSize handling can cause an integer overflow on 32-bit targets, leading to a heap under-allocation followed by a heap buffer overflow when log data is copied into the cache. An attacker controlling the configuration can cause memory corruption and potentially crash the daemon.
## Vulnerable Code
File: `src/offlinelogstorage/dlt_offline_logstorage_behavior.c`
```c
1361: /* check total logstorage cache size */
1362: if ((g_logstorage_cache_size + cache_size +
1363: sizeof(DltLogStorageCacheFooter)) >
1364: g_logstorage_cache_max) /* <-- unsigned-int add wraps mod 2^32 -> passes */
1365: {
1366: dlt_vlog(LOG_ERR, "%s: Max size of Logstorage Cache already used. ...");
1369: return -1;
1370: } else {
....
1378: config->cache = calloc(1, cache_size + sizeof(DltLogStorageCacheFooter)); /* <-- wraps -> tiny */
....
1522: /* write data to cache */
1523: memcpy(curr_write_addr, data1, (size_t)size1); /* <-- overruns the tiny buffer */
1524: curr_write_addr += size1;
1525: memcpy(curr_write_addr, data2, (size_t)size2);
1526: curr_write_addr += size2;
1527: memcpy(curr_write_addr, data3, (size_t)size3);
```
`cache_size` is derived from the attacker-controlled `FileSize=` value in `dlt_logstorage.conf`. On 32-bit targets, both `unsigned int` and `size_t` are 32-bit, causing the cache size calculations and the `calloc` allocation size to wrap on overflow.
`DltLogStorageCacheFooter` consists of four `unsigned int` fields, resulting in a size of **16 bytes** (`dlt_offline_logstorage.h:139-145`). The variables `g_logstorage_cache_size`, `cache_size`, and `config->file_size` are all stored as `unsigned int`.
```
typedef struct
{
unsigned int offset; /* current write offset */
unsigned int wrap_around_cnt; /* wrap around counter */
unsigned int last_sync_offset; /* last sync position */
unsigned int end_sync_offset; /* end position of previous round */
} DltLogStorageCacheFooter;
```
## Reproduction
The exploitable under-allocation is 32-specific, so build the daemon as a 32-bit process. On a 64-bit host, install the multilib toolchain (`gcc-multilib g++-multilib libc6-dev-i386`) and configure with `-m32` (AddressSanitizer pinpoints the overflow):
```sh
cmake -S . -B build32 \
-DCMAKE_C_FLAGS="-m32 -fsanitize=address -g -O0" \
-DCMAKE_CXX_FLAGS="-m32 -fsanitize=address -g -O0" \
-DCMAKE_EXE_LINKER_FLAGS="-m32 -fsanitize=address" \
-DWITH_DLT_EXAMPLES=ON
cmake --build build32 --target dlt-daemon
```
```ini
[FILTER1]
....
....
....
FileSize=4294967295 ; 0xFFFFFFFF
```
## Log
```
=================================================================
==4472==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xef8001ef at pc 0x656bd963 bp 0xffbb0ea8 sp 0xffbb0e98
READ of size 4 at 0xef8001ef thread T0
#0 0x656bd962 in dlt_logstorage_write_msg_cache /opt/dlt-daemon/src/offlinelogstorage/dlt_offline_logstorage_behavior.c:1447
#1 0x656b5bb6 in dlt_logstorage_write /opt/dlt-daemon/src/offlinelogstorage/dlt_offline_logstorage.c:2637
#2 0x65650757 in dlt_daemon_logstorage_write /opt/dlt-daemon/src/daemon/dlt_daemon_offline_logstorage.c:1427
#3 0x65613074 in dlt_daemon_client_send /opt/dlt-daemon/src/daemon/dlt_daemon_client.c:244
#4 0x6561437b in dlt_daemon_client_send_message_to_all_client /opt/dlt-daemon/src/daemon/dlt_daemon_client.c:551
#5 0x65610afe in dlt_daemon_process_user_message_log /opt/dlt-daemon/src/daemon/dlt-daemon.c:5251
#6 0x65606883 in dlt_daemon_process_user_messages /opt/dlt-daemon/src/daemon/dlt-daemon.c:3838
#7 0x6564a6ff in dlt_daemon_handle_event /opt/dlt-daemon/src/daemon/dlt_daemon_event_handler.c:264
#8 0x655f9b91 in main /opt/dlt-daemon/src/daemon/dlt-daemon.c:1684
#9 0xf1a5ac74 (/lib32/libc.so.6+0x24c74) (BuildId: 5f19d57443bdf59ae677824a50f4b8c12d7e8654)
#10 0xf1a5ad37 in __libc_start_main (/lib32/libc.so.6+0x24d37) (BuildId: 5f19d57443bdf59ae677824a50f4b8c12d7e8654)
#11 0x655f4a76 in _start (/opt/dlt-build32/src/daemon/dlt-daemon+0xca76) (BuildId: 91662d75b13a576d77a9f7a7ac8a3f0793d3130d)
0xef8001ef is located 1 bytes before 15-byte region [0xef8001f0,0xef8001ff)
allocated by thread T0 here:
#0 0xf1d5752b in calloc ../../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x656bd6d8 in dlt_logstorage_prepare_msg_cache /opt/dlt-daemon/src/offlinelogstorage/dlt_offline_logstorage_behavior.c:1378
#2 0x656b55c3 in dlt_logstorage_write /opt/dlt-daemon/src/offlinelogstorage/dlt_offline_logstorage.c:2603
#3 0x65650757 in dlt_daemon_logstorage_write /opt/dlt-daemon/src/daemon/dlt_daemon_offline_logstorage.c:1427
#4 0x65613074 in dlt_daemon_client_send /opt/dlt-daemon/src/daemon/dlt_daemon_client.c:244
#5 0x6561437b in dlt_daemon_client_send_message_to_all_client /opt/dlt-daemon/src/daemon/dlt_daemon_client.c:551
#6 0x65610afe in dlt_daemon_process_user_message_log /opt/dlt-daemon/src/daemon/dlt-daemon.c:5251
#7 0x65606883 in dlt_daemon_process_user_messages /opt/dlt-daemon/src/daemon/dlt-daemon.c:3838
#8 0x6564a6ff in dlt_daemon_handle_event /opt/dlt-daemon/src/daemon/dlt_daemon_event_handler.c:264
#9 0x655f9b91 in main /opt/dlt-daemon/src/daemon/dlt-daemon.c:1684
#10 0xf1a5ac74 (/lib32/libc.so.6+0x24c74) (BuildId: 5f19d57443bdf59ae677824a50f4b8c12d7e8654)
SUMMARY: AddressSanitizer: heap-buffer-overflow /opt/dlt-daemon/src/offlinelogstorage/dlt_offline_logstorage_behavior.c:1447 in dlt_logstorage_write_msg_cache
Shadow bytes around the buggy address:
0xef7fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xef7fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xef800000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xef800080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xef800100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0xef800180: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]00 07
0xef800200: fa fa fd fd fa fa fd fa fa fa 04 fa fa fa 00 00
0xef800280: fa fa 05 fa fa fa 04 fa fa fa 05 fa fa fa 05 fa
0xef800300: fa fa 00 07 fa fa 00 00 fa fa fd fd fa fa fd fa
0xef800380: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0xef800400: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd 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
==4472==ABORTING
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in src/offlinelogstorage/dlt_offline_logstorage_behavior.c at dlt_logstorage_prepare_msg_cache and dlt_logstorage_write_msg_cache, then inspect DltLogStorageCacheFooter in dlt_offline_logstorage.h. Reproduce with the provided 32-bit CMake and AddressSanitizer build of dlt-daemon using FileSize=4294967295. Done means oversized configuration values no longer produce wrapped allocation or an AddressSanitizer heap-buffer-overflow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 62/100