Skip to content

[Bug] Out-of-bounds read in tcpprep #931

@momo-trip

Description

@momo-trip

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions