-
Notifications
You must be signed in to change notification settings - Fork 279
Description
Out-of-bounds read in tcpprep
Hi, we have found an out-of-bounds read and would like to report this issue.
Could you confirm if this qualifies as a valid bug? I am happy to provide any additional information needed.
Summary
An out-of-bounds read vulnerability has been identified in tcpprep version 4.5.1. The issue is triggered when command-line arguments are passed to the --save-opts option. Internally, the program uses strstr() on a memory buffer obtained via mmap(), which is not null-terminated. This causes strstr() to read beyond the mapped region, leading to a segmentation fault and potential denial of service (DoS).
Reproduction
Test Environment
- Operating System: Ubuntu 22.04 LTS
- Architecture: x86_64
- Compiler: clang with AddressSanitizer (clang version: 14.0.0)
Setup
#!/bin/bash
set -euo pipefail
TARGET_DIR="tcpreplay"
VERSION_OR_COMMIT="v4.5.1"
REPOSITORY=https://github.com/appneta/tcpreplay
CC="clang"
CXX="clang++"
CFLAGS="-fsanitize=address -g"
CXXFLAGS="-fsanitize=address -g"
git clone --recursive ${REPOSITORY} ${TARGET_DIR}
cd ${TARGET_DIR}
git switch --detach ${VERSION_OR_COMMIT}
./autogen.sh
CC=${CC} CXX=${CXX} CFLAGS=${CFLAGS} CXXFLAGS=${CFLAGS} ./configure --enable-debug
make
Execute
# Trigger the crash
gdb --args ./src/tcpprep --sa ">>>>>>>>>>>I>>>>"
AddressSanitizer Output
AddressSanitizer:DEADLYSIGNAL
==1459594==ERROR: AddressSanitizer: SEGV on unknown address 0xffffffffffffffc0
==1459594==The signal is caused by a READ memory access.
#0 __strstr_sse2_unaligned ../sysdeps/x86_64/multiarch/strstr-sse2-unaligned.S:278
#1 remove_settings /root/dataset_fuzz/tcpreplay-4.5.1/libopts/./save.c:499:30
#2 open_sv_file /root/dataset_fuzz/tcpreplay-4.5.1/libopts/./save.c:564:13
#3 optionSaveFile /root/dataset_fuzz/tcpreplay-4.5.1/libopts/./save.c:828:10
Affected Code
libopts/save.c
Root Cause
The vulnerability stems from the use of strstr()
on a memory-mapped buffer that lacks null termination.
Impact Assessment
- Denial of Service: Immediate application crash due to segmentation fault
- Potential Information Disclosure: Out-of-bounds read may access sensitive memory regions
- Reliability: Application becomes unreliable when processing certain input patterns
Proposed Fix
diff --git a/libopts/save.c b/libopts/save.c
index ba342070..8710d306 100644
--- a/libopts/save.c
+++ b/libopts/save.c
@@ -492,9 +492,18 @@ remove_settings(tOptions * opts, char const * fname)
{
size_t const name_len = strlen(opts->pzProgName);
tmap_info_t map_info;
- char * text = text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &map_info);
- char * scan = text;
+ char * _text = text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &map_info);
+ if (_text == NULL)
+ goto leave;
+
+ char * text = ao_malloc(map_info.txt_size + 1);
+ if (text == NULL)
+ goto leave;
+ memcpy(text, _text, map_info.txt_size);
+ text[map_info.txt_size] = '\0';
+
+ char * scan = text;
for (;;) {
char * next = scan = strstr(scan, zCfgProg);
if (scan == NULL)
The vulnerability is fixed by creating a null-terminated copy of the memory-mapped buffer before using strstr()
. We allocate a temporary buffer with malloc(map_info.txt_size + 1)
, copy the mapped data, and append a null terminator. This prevents SIMD-optimized strstr()
from reading beyond buffer boundaries regardless of input patterns.