1
0
Quellcode durchsuchen

Import upstream version 4.5.4

Fred Klassen vor 3 Tagen
Ursprung
Commit
493282a6ac

+ 10 - 10
configure

@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for tcpreplay 4.5.3.
+# Generated by GNU Autoconf 2.72 for tcpreplay 4.5.4.
 #
 # Report bugs to <https://github.com/appneta/tcpreplay/issues>.
 #
@@ -614,8 +614,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='tcpreplay'
 PACKAGE_TARNAME='tcpreplay'
-PACKAGE_VERSION='4.5.3'
-PACKAGE_STRING='tcpreplay 4.5.3'
+PACKAGE_VERSION='4.5.4'
+PACKAGE_STRING='tcpreplay 4.5.4'
 PACKAGE_BUGREPORT='https://github.com/appneta/tcpreplay/issues'
 PACKAGE_URL='http://tcpreplay.sourceforge.net/'
 
@@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures tcpreplay 4.5.3 to adapt to many kinds of systems.
+'configure' configures tcpreplay 4.5.4 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1549,7 +1549,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of tcpreplay 4.5.3:";;
+     short | recursive ) echo "Configuration of tcpreplay 4.5.4:";;
    esac
   cat <<\_ACEOF
 
@@ -1726,7 +1726,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-tcpreplay configure 4.5.3
+tcpreplay configure 4.5.4
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2673,7 +2673,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by tcpreplay $as_me 4.5.3, which was
+It was created by tcpreplay $as_me 4.5.4, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4684,7 +4684,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='tcpreplay'
- VERSION='4.5.3'
+ VERSION='4.5.4'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -30125,7 +30125,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by tcpreplay $as_me 4.5.3, which was
+This file was extended by tcpreplay $as_me 4.5.4, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -30194,7 +30194,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-tcpreplay config.status 4.5.3
+tcpreplay config.status 4.5.4
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 

+ 1 - 1
configure.ac

@@ -4,7 +4,7 @@ dnl $Id$
 AC_PREREQ([2.69])
 
 dnl Set version info here!
-AC_INIT([tcpreplay],[4.5.3],[https://github.com/appneta/tcpreplay/issues],[tcpreplay],[http://tcpreplay.sourceforge.net/])
+AC_INIT([tcpreplay],[4.5.4],[https://github.com/appneta/tcpreplay/issues],[tcpreplay],[http://tcpreplay.sourceforge.net/])
 AC_CONFIG_SRCDIR([src/tcpreplay.c])
 AC_CONFIG_HEADERS([src/config.h])
 AC_CONFIG_AUX_DIR(config)

+ 42 - 0
docs/CHANGELOG

@@ -1,3 +1,45 @@
+07/22/2026 Version 4.5.4
+    - SECURITY: fix heap buffer overflow in the tcprewrite fragroute tcp_opt module
+      (GHSA-pfqg-243f-8q25, CWE-787, CVSS 8.4). tcp_opt_apply() (src/fragroute/mod_tcp_opt.c)
+      passed sizeof(pkt->pkt_data) - ETH_HDR_LEN as the buffer-capacity bound to
+      inet_add_option(); pkt_data is a pointer, so sizeof() was 8 on 64-bit builds and the
+      subtraction underflowed size_t to near SIZE_MAX, disabling the bounds check and letting
+      libdnet's option-insertion memmove() write past the packet's heap allocation. The bound is
+      now computed from the real buffer extent (pkt->pkt_buf + pkt->pkt_buf_size - pkt->pkt_ip).
+      Reported by tinyb0y.
+    - SECURITY: fix heap buffer overflow in the tcprewrite fragroute ip6_opt module
+      (GHSA-2wmf-4p77-784q, CWE-787). ip6_opt_apply() (src/fragroute/mod_ip6_opt.c) inserted IPv6
+      routing/extension headers with memmove()/memcpy() without checking that the inserted bytes
+      fit the packet's remaining buffer headroom. Both the route and raw paths now verify
+      pkt_end + offset stays within the allocation and skip the packet otherwise. Reported by
+      tinyb0y.
+    - SECURITY: fix the same class of unchecked option-insertion overflow in the fragroute ip_opt
+      module (src/fragroute/mod_ip_opt.c), which used a fixed PKT_BUF_LEN - ETH_HDR_LEN bound that
+      overcounts capacity by the buffer's lead-alignment pad on small packets; it now uses the same
+      real buffer-extent bound as tcp_opt.
+    - SECURITY: fix SEGV in the tcpedit DLT_JUNIPER_ETHER plugin when used as a decoder
+      (GHSA-ww62-mxv7-pg55, CWE-704, CWE-843). dlt_jnpr_ether_post_init()/_cleanup()/_decode()/
+      _proto()/_get_mac()/_l2len() (src/tcpedit/plugins/dlt_jnpr_ether/jnpr_ether.c) read
+      ctx->encoder->config to get the plugin's own config, but this plugin only ever operates as a
+      decoder (packet encoding is unsupported) - ctx->encoder pointed at an unrelated plugin's
+      config struct, a type confusion that crashed tcpedit_dlt_getplugin() when processing
+      DLT_JUNIPER_ETHER input, e.g. via tcprewrite --dlt=enet. Fixed by reading ctx->decoder->config
+      in all six sites. Reported and originally patched by jiezhuzzz.
+    - SECURITY: fix crash in remove_settings() on failed text_mmap (GHSA-5cjx-62pj-pmgq, CWE-476).
+      remove_settings() (libopts/save.c), reachable from the AutoOpts option-file save/rewrite path
+      (e.g. via --load-opts), dereferenced the pointer returned by text_mmap() without checking for
+      MAP_FAILED, unlike the other two callers in configfile.c. A missing/inaccessible/wrong-type/
+      empty settings file crashed the program. Fixed with the same TEXT_MMAP_FAILED_ADDR() guard
+      already used elsewhere in the codebase. Reported by jiezhuzzz.
+    - SECURITY: fix buffer overflow in the KHIAL sendpacket() path (GHSA-pjh6-6hrw-vcwr, CWE-787,
+      CVSS 6.6). buffer_payload_size (src/common/sendpacket.c) was computed as sizeof(buffer) +
+      sizeof(struct pcap_pkthdr) instead of sizeof(buffer) - sizeof(struct pcap_pkthdr), overstating
+      the KHIAL send buffer's available space by 48 bytes (64-bit) and letting memcpy() overflow the
+      static buffer for packets >= 10024 bytes sent via tcpreplay --intf1=<khial-device>; the
+      following write() had the same problem in reverse, reading past the buffer into the character
+      device. Fixed the calculation and added an explicit length check that rejects oversized
+      packets before either memcpy or write() touch the buffer. Reported by 360AlphaLab.
+
 07/18/2026 Version 4.5.3
     - configure: fix --with-netmap=DIR permanently leaking -I<DIR>/sys onto CFLAGS for the rest of
       the script, with no restore (unlike the equivalent, correctly-scoped CPPFLAGS addition a few

+ 12 - 0
docs/CREDIT

@@ -161,3 +161,15 @@ Gabriel Ganne <GitHub @GabrielGanne>
     - fragroute: fix heap-buffer-overflow on packets with too many MPLS labels (#993)
     - tcprewrite: fix vlan tag add silently truncating output when --enet-vlan-pri/-cfi omitted (#994)
     - tcpprep: fix buffer overflow in check_dst_port() on truncated L4 headers (#995)
+
+tinyb0y <GitHub @tinyb0y>
+    - fragroute: reported heap buffer overflow in tcp_opt module (GHSA-pfqg-243f-8q25)
+    - fragroute: reported heap buffer overflow in ip6_opt module (GHSA-2wmf-4p77-784q)
+
+jiezhuzzz <GitHub @jiezhuzzz>
+    - tcpedit: reported and proposed fix for SEGV in DLT_JUNIPER_ETHER plugin when used as
+      a decoder (GHSA-ww62-mxv7-pg55)
+    - libopts: reported crash in remove_settings() on failed text_mmap (GHSA-5cjx-62pj-pmgq)
+
+360AlphaLab <GitHub @360AlphaLab>
+    - common: reported buffer overflow in the KHIAL sendpacket() path (GHSA-pjh6-6hrw-vcwr)

+ 3 - 0
libopts/save.c

@@ -495,6 +495,9 @@ remove_settings(tOptions * opts, char const * fname)
     char *       text = text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &map_info);
     char *       scan = text;
 
+    if (TEXT_MMAP_FAILED_ADDR(text))
+        return;
+
     for (;;) {
         char * next = scan = strstr(scan, zCfgProg);
         if (scan == NULL)

+ 1 - 1
src/common/git_version.c

@@ -1,4 +1,4 @@
-const char GIT_Version[] = "git:v4.5.3-1-g60888f71";
+const char GIT_Version[] = "git:v4.5.4";
 const char *git_version(void) {
     return GIT_Version;
 }

+ 7 - 2
src/common/sendpacket.c

@@ -257,7 +257,7 @@ sendpacket(sendpacket_t *sp, const u_char *data, size_t len, struct pcap_pkthdr
                                   * larger than page size so made static to
                                   * prevent page misses on stack
                                   */
-    static const size_t buffer_payload_size = sizeof(buffer) + sizeof(struct pcap_pkthdr);
+    static const size_t buffer_payload_size = sizeof(buffer) - sizeof(struct pcap_pkthdr);
     /* Bound the EAGAIN/ENOBUFS retry loop below so sustained buffer pressure (e.g. very
      * large frames) can't spin forever at 100% CPU; a short sleep between retries keeps
      * that spin from hammering the kernel while we wait for buffer space to free up.
@@ -291,8 +291,13 @@ TRY_SEND_AGAIN:
     switch (sp->handle_type) {
     case SP_TYPE_KHIAL:
 
+        if (len > buffer_payload_size) {
+            sendpacket_seterr(sp, "Packet too large for KHIAL buffer: %zu > %zu", len, buffer_payload_size);
+            return -1;
+        }
+
         memcpy(buffer, pkthdr, sizeof(struct pcap_pkthdr));
-        memcpy(buffer + sizeof(struct pcap_pkthdr), data, min(len, buffer_payload_size));
+        memcpy(buffer + sizeof(struct pcap_pkthdr), data, len);
 
         /* tell the kernel module which direction the traffic is going */
         if (sp->cache_dir == TCPR_DIR_C2S) { /* aka PRIMARY */

+ 8 - 0
src/fragroute/mod_ip6_opt.c

@@ -122,6 +122,10 @@ ip6_opt_apply(void *d, struct pktq *pktq)
 
         if (opt->type == OPT6_TYPE_ROUTE) {
             offset = 8 + IP6_ADDR_LEN * opt->u.route.segments;
+            if ((u_char *)pkt->pkt_end + offset > pkt->pkt_buf + pkt->pkt_buf_size) {
+                warnx("ip6_opt: not enough buffer headroom to insert routing header, skipping packet");
+                continue;
+            }
             memmove(((u_char *)ext) + offset, ext, pkt->pkt_end - (u_char *)ext);
 
             pkt->pkt_end += offset;
@@ -143,6 +147,10 @@ ip6_opt_apply(void *d, struct pktq *pktq)
 
         } else if (opt->type == OPT6_TYPE_RAW) {
             offset = opt->u.raw.len;
+            if ((u_char *)pkt->pkt_end + offset > pkt->pkt_buf + pkt->pkt_buf_size) {
+                warnx("ip6_opt: not enough buffer headroom to insert extension header, skipping packet");
+                continue;
+            }
             memmove(((u_char *)ext) + offset, ext, pkt->pkt_end - (u_char *)ext);
 
             pkt->pkt_end += offset;

+ 5 - 1
src/fragroute/mod_ip_opt.c

@@ -82,7 +82,11 @@ ip_opt_apply(void *d, struct pktq *pktq)
         uint16_t eth_type = htons(pkt->pkt_eth->eth_type);
 
         if (eth_type == ETH_TYPE_IP) {
-            len = ip_add_option(pkt->pkt_ip, PKT_BUF_LEN - ETH_HDR_LEN, IP_PROTO_IP, opt, opt->opt_len);
+            len = ip_add_option(pkt->pkt_ip,
+                                pkt->pkt_buf + pkt->pkt_buf_size - (u_char *)pkt->pkt_ip,
+                                IP_PROTO_IP,
+                                opt,
+                                opt->opt_len);
 
             if (len > 0) {
                 pkt->pkt_end += len;

+ 1 - 1
src/fragroute/mod_tcp_opt.c

@@ -81,7 +81,7 @@ tcp_opt_apply(void *d, struct pktq *pktq)
 
         len = inet_add_option(eth_type,
                               pkt->pkt_ip,
-                              sizeof(pkt->pkt_data) - ETH_HDR_LEN,
+                              pkt->pkt_buf + pkt->pkt_buf_size - (u_char *)pkt->pkt_ip,
                               IP_PROTO_TCP,
                               opt,
                               opt->opt_len);

+ 1 - 1
src/tcpbridge.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpbridge 1 "19 Jul 2026" "tcpbridge" "User Commands"
+.TH tcpbridge 1 "22 Jul 2026" "tcpbridge" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpcapinfo.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpcapinfo 1 "19 Jul 2026" "Tcpreplay Suite" "User Commands"
+.TH tcpcapinfo 1 "22 Jul 2026" "Tcpreplay Suite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 6 - 6
src/tcpedit/plugins/dlt_jnpr_ether/jnpr_ether.c

@@ -131,7 +131,7 @@ dlt_jnpr_ether_post_init(tcpeditdlt_t *ctx)
         return TCPEDIT_OK;
 
     /* init our subcontext & decoder of en10mb */
-    config = (jnpr_ether_config_t *)ctx->encoder->config;
+    config = (jnpr_ether_config_t *)ctx->decoder->config;
     if (config->subctx == NULL)
         config->subctx = tcpedit_dlt_init(ctx->tcpedit, DLT_EN10MB);
 
@@ -161,7 +161,7 @@ dlt_jnpr_ether_cleanup(tcpeditdlt_t *ctx)
         /* clean up the en10mb plugin */
         jnpr_ether_config_t *config;
 
-        config = (jnpr_ether_config_t *)ctx->encoder->config;
+        config = (jnpr_ether_config_t *)ctx->decoder->config;
         if (config != NULL && config->subctx != NULL) {
             tcpedit_dlt_cleanup(config->subctx);
         }
@@ -215,7 +215,7 @@ dlt_jnpr_ether_decode(tcpeditdlt_t *ctx, const u_char *packet, int pktlen)
     if (pktlen < JUNIPER_ETHER_HEADER_LEN)
         return TCPEDIT_ERROR;
 
-    config = (jnpr_ether_config_t *)ctx->encoder->config;
+    config = (jnpr_ether_config_t *)ctx->decoder->config;
 
     /* first, verify magic */
     if (memcmp(packet, JUNIPER_ETHER_MAGIC, JUNIPER_ETHER_MAGIC_LEN) != 0) {
@@ -319,7 +319,7 @@ dlt_jnpr_ether_proto(tcpeditdlt_t *ctx, const u_char *packet, int pktlen)
     if (pktlen < JUNIPER_ETHER_HEADER_LEN)
         return TCPEDIT_ERROR;
 
-    config = (jnpr_ether_config_t *)ctx->encoder->config;
+    config = (jnpr_ether_config_t *)ctx->decoder->config;
 
     /* next make sure the L2 header is present */
     if ((packet[JUNIPER_ETHER_OPTIONS_OFFSET] & JUNIPER_ETHER_L2PRESENT) != JUNIPER_ETHER_L2PRESENT) {
@@ -405,7 +405,7 @@ dlt_jnpr_ether_get_mac(tcpeditdlt_t *ctx, tcpeditdlt_mac_type_t mac, const u_cha
     if (pktlen < JUNIPER_ETHER_EXTLEN_OFFSET + 2)
         return NULL;
 
-    config = (jnpr_ether_config_t *)ctx->encoder->config;
+    config = (jnpr_ether_config_t *)ctx->decoder->config;
 
     /* first get the Juniper header length */
     memcpy(&jnpr_hdr_len, &packet[JUNIPER_ETHER_EXTLEN_OFFSET], 2);
@@ -431,7 +431,7 @@ dlt_jnpr_ether_l2len(tcpeditdlt_t *ctx, const u_char *packet, int pktlen)
     if (pktlen < JUNIPER_ETHER_EXTLEN_OFFSET + 2)
         return -1;
 
-    config = (jnpr_ether_config_t *)ctx->encoder->config;
+    config = (jnpr_ether_config_t *)ctx->decoder->config;
 
     /* first get the Juniper header length */
     memcpy(&len, &packet[JUNIPER_ETHER_EXTLEN_OFFSET], 2);

+ 1 - 1
src/tcpliveplay.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpliveplay 1 "19 Jul 2026" "tcpliveplay" "User Commands"
+.TH tcpliveplay 1 "22 Jul 2026" "tcpliveplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpprep.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpprep 1 "19 Jul 2026" "tcpprep" "User Commands"
+.TH tcpprep 1 "22 Jul 2026" "tcpprep" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpreplay-edit.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpreplay-edit 1 "19 Jul 2026" "tcpreplay" "User Commands"
+.TH tcpreplay-edit 1 "22 Jul 2026" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcpreplay.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcpreplay 1 "19 Jul 2026" "tcpreplay" "User Commands"
+.TH tcpreplay 1 "22 Jul 2026" "tcpreplay" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"

+ 1 - 1
src/tcprewrite.1

@@ -10,7 +10,7 @@
 .ds B-Font B
 .ds I-Font I
 .ds R-Font R
-.TH tcprewrite 1 "19 Jul 2026" "tcprewrite" "User Commands"
+.TH tcprewrite 1 "22 Jul 2026" "tcprewrite" "User Commands"
 .\"
 .\" DO NOT EDIT THIS FILE (in-mem file)
 .\"