From e92a4e5458ff35083ea7263c68316b47243a1222 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 12 Feb 2022 23:13:47 +0100 Subject: [PATCH] tcpdump: Fix CVE-2018-16301 This fixes the following security problem: The command-line argument parser in tcpdump before 4.99.0 has a buffer overflow in tcpdump.c:read_infile(). To trigger this vulnerability the attacker needs to create a 4GB file on the local filesystem and to specify the file name as the value of the -F command-line argument of tcpdump. Signed-off-by: Hauke Mehrtens (cherry picked from commit 8f5875c4e221453932f217a82f8c3092cacba3e5) (cherry picked from commit 59e7ae8d65ab9a9315608a69565f6a4247d3b1ac) --- package/network/utils/tcpdump/Makefile | 2 +- .../tcpdump/patches/102-CVE-2018-16301.patch | 101 ++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 package/network/utils/tcpdump/patches/102-CVE-2018-16301.patch diff --git a/package/network/utils/tcpdump/Makefile b/package/network/utils/tcpdump/Makefile index 3e4d9d2d73..7fff2f5a8a 100644 --- a/package/network/utils/tcpdump/Makefile +++ b/package/network/utils/tcpdump/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tcpdump PKG_VERSION:=4.9.3 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.us.tcpdump.org/release/ \ diff --git a/package/network/utils/tcpdump/patches/102-CVE-2018-16301.patch b/package/network/utils/tcpdump/patches/102-CVE-2018-16301.patch new file mode 100644 index 0000000000..39cd368915 --- /dev/null +++ b/package/network/utils/tcpdump/patches/102-CVE-2018-16301.patch @@ -0,0 +1,101 @@ +From 8ab211a7ec728bb0ad8c766c8eeb12deb0a13b86 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Wed, 30 Sep 2020 11:37:30 -0700 +Subject: [PATCH] Handle very large -f files by rejecting them. + +_read(), on Windows, has a 32-bit size argument and a 32-bit return +value, so reject -f files that have more than 2^31-1 characters. + +Add some #defines so that, on Windows, we use _fstati64 to get the size +of that file, to handle large files. + +Don't assume that our definition for ssize_t is the same size as size_t; +by the time we want to print the return value of the read, we know it'll +fit into an int, so just cast it to int and print it with %d. + +(cherry picked from commit faf8fb70af3a013e5d662b8283dec742fd6b1a77) +--- + netdissect-stdinc.h | 16 +++++++++++++++- + tcpdump.c | 15 ++++++++++++--- + 2 files changed, 27 insertions(+), 4 deletions(-) + +--- a/netdissect-stdinc.h ++++ b/netdissect-stdinc.h +@@ -149,10 +149,17 @@ + #ifdef _MSC_VER + #define stat _stat + #define open _open +-#define fstat _fstat + #define read _read + #define close _close + #define O_RDONLY _O_RDONLY ++ ++/* ++ * We define our_fstat64 as _fstati64, and define our_statb as ++ * struct _stati64, so we get 64-bit file sizes. ++ */ ++#define our_fstat _fstati64 ++#define our_statb struct _stati64 ++ + #endif /* _MSC_VER */ + + /* +@@ -211,6 +218,13 @@ typedef char* caddr_t; + + #include + ++/* ++ * We should have large file support enabled, if it's available, ++ * so just use fstat as our_fstat and struct stat as our_statb. ++ */ ++#define our_fstat fstat ++#define our_statb struct stat ++ + #endif /* _WIN32 */ + + #ifndef HAVE___ATTRIBUTE__ +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -108,6 +108,7 @@ The Regents of the University of Califor + #endif /* HAVE_CAP_NG_H */ + #endif /* HAVE_LIBCAP_NG */ + ++#include "netdissect-stdinc.h" + #include "netdissect.h" + #include "interface.h" + #include "addrtoname.h" +@@ -861,15 +862,22 @@ read_infile(char *fname) + { + register int i, fd, cc; + register char *cp; +- struct stat buf; ++ our_statb buf; + + fd = open(fname, O_RDONLY|O_BINARY); + if (fd < 0) + error("can't open %s: %s", fname, pcap_strerror(errno)); + +- if (fstat(fd, &buf) < 0) ++ if (our_fstat(fd, &buf) < 0) + error("can't stat %s: %s", fname, pcap_strerror(errno)); + ++ /* ++ * Reject files whose size doesn't fit into an int; a filter ++ * *that* large will probably be too big. ++ */ ++ if (buf.st_size > INT_MAX) ++ error("%s is too large", fname); ++ + cp = malloc((u_int)buf.st_size + 1); + if (cp == NULL) + error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, +@@ -878,7 +886,8 @@ read_infile(char *fname) + if (cc < 0) + error("read %s: %s", fname, pcap_strerror(errno)); + if (cc != buf.st_size) +- error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); ++ error("short read %s (%d != %d)", fname, (int) cc, ++ (int)buf.st_size); + + close(fd); + /* replace "# comment" with spaces */