From 29eed1aa022082af23ac9cb3954d438e6268c653 Mon Sep 17 00:00:00 2001 From: eaglegai Date: Sat, 8 Apr 2023 10:55:47 +0000 Subject: [PATCH] fix CVE-2023-1801 --- ...place-obsolete-function-call-asctime.patch | 48 +++ backport-CVE-2023-1801.patch | 334 ++++++++++++++++++ tcpdump.spec | 10 +- 3 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2023-1801-pre-smbutil-Replace-obsolete-function-call-asctime.patch create mode 100644 backport-CVE-2023-1801.patch diff --git a/backport-CVE-2023-1801-pre-smbutil-Replace-obsolete-function-call-asctime.patch b/backport-CVE-2023-1801-pre-smbutil-Replace-obsolete-function-call-asctime.patch new file mode 100644 index 0000000..9e56e5f --- /dev/null +++ b/backport-CVE-2023-1801-pre-smbutil-Replace-obsolete-function-call-asctime.patch @@ -0,0 +1,48 @@ +From 8b68416428742aa440d27dd4337636ed89d8ecc2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ege=20=C3=87etin?= +Date: Sun, 1 Jan 2023 12:29:03 +0000 +Subject: [PATCH] smbutil.c: Replace obsolete function call (asctime) + +(cherry picked from commit ab17cb47648b8a60d9897f598b7fd0df1dd354fa) +--- + CREDITS | 1 + + smbutil.c | 7 +++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/CREDITS b/CREDITS +index 25a860ea7..b6862ccba 100644 +--- a/CREDITS ++++ b/CREDITS +@@ -84,6 +84,7 @@ Additional people who have contributed patches (in alphabetical order): + Duane Wessels + Eamon Doyle + Eddie Kohler ++ Ege Cetin + Eliot Lear + Elmar Kirchner + Eric S. Raymond +diff --git a/smbutil.c b/smbutil.c +index ff32ecce2..7f609f7f3 100644 +--- a/smbutil.c ++++ b/smbutil.c +@@ -770,6 +770,7 @@ smb_fdata1(netdissect_options *ndo, + time_t t; + struct tm *lt; + const char *tstring; ++ char buffer[sizeof("Www Mmm dd hh:mm:ss yyyy\n")]; + uint32_t x; + + switch (atoi(fmt + 1)) { +@@ -800,8 +801,10 @@ smb_fdata1(netdissect_options *ndo, + } + if (t != 0) { + lt = localtime(&t); +- if (lt != NULL) +- tstring = asctime(lt); ++ if (lt != NULL) { ++ strftime(buffer, sizeof(buffer), "%a %b %e %T %Y%n", lt); ++ tstring = buffer; ++ } + else + tstring = "(Can't convert time)\n"; + } else diff --git a/backport-CVE-2023-1801.patch b/backport-CVE-2023-1801.patch new file mode 100644 index 0000000..ee945fd --- /dev/null +++ b/backport-CVE-2023-1801.patch @@ -0,0 +1,334 @@ +From 03c037bbd75588beba3ee09f26d17783d21e30bc Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Mon, 30 Jan 2023 23:03:16 -0800 +Subject: [PATCH] Have a common routine for converting dates and times to + strings. + +Have a routine that takes a buffer, a strftime format, and a struct tm * +as arguments, and: + +* checks whether the struct tm * is null and, if so, returns a string +indicating that the date and time couldn't be converted; + +* otherwise, passes it to strftime(), along with the buffer and the +format argument and, if strftime() returns 0, meaning the string didn't +fit into the buffer and thus that the buffer's contents are undefined, +returns a string indicating that the date and time didn't fit into the +buffer; + +* otherwise, returns a pointer to the buffer. + +Call that routine instead of directly calling strftime() in printers; +that prevents printing a buffer with undefined data if the buffer isn't +big enough for the string. + +Also, when generating file names using an strftime format, check the +return value of strftime() to make sure the buffer didn't overflow. +--- + netdissect.h | 3 +++ + ntp.c | 21 ++++++--------------- + print-ahcp.c | 12 ++++-------- + print-arista.c | 13 ++++--------- + print-rx.c | 8 ++++---- + print-zep.c | 7 +++---- + smbutil.c | 16 +++++----------- + tcpdump.c | 22 ++++++++++++++++++++-- + util-print.c | 36 ++++++++++++++++++++++++++++-------- + 9 files changed, 77 insertions(+), 61 deletions(-) + +diff --git a/netdissect.h b/netdissect.h +index 5c16be660..b1074ef72 100644 +--- a/netdissect.h ++++ b/netdissect.h +@@ -389,6 +389,9 @@ extern void ts_print(netdissect_options *, const struct timeval *); + extern void signed_relts_print(netdissect_options *, int32_t); + extern void unsigned_relts_print(netdissect_options *, uint32_t); + ++extern const char *nd_format_time(char *buf, size_t bufsize, ++ const char *format, const struct tm *timeptr); ++ + extern void fn_print_char(netdissect_options *, u_char); + extern void fn_print_str(netdissect_options *, const u_char *); + extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *); +diff --git a/ntp.c b/ntp.c +index 10fabe4b6..ec8f659a4 100644 +--- a/ntp.c ++++ b/ntp.c +@@ -55,8 +55,8 @@ p_ntp_time(netdissect_options *ndo, + if (i) { + int64_t seconds_64bit = (int64_t)i - JAN_1970; + time_t seconds; +- struct tm *tm; + char time_buf[128]; ++ const char *time_string; + + seconds = (time_t)seconds_64bit; + if (seconds != seconds_64bit) { +@@ -64,22 +64,13 @@ p_ntp_time(netdissect_options *ndo, + * It doesn't fit into a time_t, so we can't hand it + * to gmtime. + */ +- ND_PRINT(" (unrepresentable)"); ++ time_string = "[Time is too large to fit into a time_t]"; + } else { +- tm = gmtime(&seconds); +- if (tm == NULL) { +- /* +- * gmtime() can't handle it. +- * (Yes, that might happen with some version of +- * Microsoft's C library.) +- */ +- ND_PRINT(" (unrepresentable)"); +- } else { +- /* use ISO 8601 (RFC3339) format */ +- strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm); +- ND_PRINT(" (%s)", time_buf); +- } ++ /* use ISO 8601 (RFC3339) format */ ++ time_string = nd_format_time(time_buf, sizeof (time_buf), ++ "%Y-%m-%dT%H:%M:%SZ", gmtime(&seconds)); + } ++ ND_PRINT(" (%s)", time_string); + } + #endif + } +diff --git a/print-ahcp.c b/print-ahcp.c +index 9859f7600..d57edda9e 100644 +--- a/print-ahcp.c ++++ b/print-ahcp.c +@@ -102,18 +102,14 @@ ahcp_time_print(netdissect_options *ndo, + const u_char *cp, uint8_t len) + { + time_t t; +- struct tm *tm; +- char buf[BUFSIZE]; ++ char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")]; + + if (len != 4) + goto invalid; + t = GET_BE_U_4(cp); +- if (NULL == (tm = gmtime(&t))) +- ND_PRINT(": gmtime() error"); +- else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) +- ND_PRINT(": strftime() error"); +- else +- ND_PRINT(": %s UTC", buf); ++ ND_PRINT(": %s", ++ nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", ++ gmtime(&t))); + return; + + invalid: +diff --git a/print-arista.c b/print-arista.c +index 039a1ffd1..079ad684b 100644 +--- a/print-arista.c ++++ b/print-arista.c +@@ -10,7 +10,6 @@ + + #include "netdissect.h" + #include "extract.h" +-#include "addrtoname.h" + + #define ARISTA_SUBTYPE_TIMESTAMP 0x01 + +@@ -32,16 +31,12 @@ arista_print_date_hms_time(netdissect_options *ndo, uint32_t seconds, + uint32_t nanoseconds) + { + time_t ts; +- struct tm *tm; +- char buf[BUFSIZE]; ++ char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")]; + + ts = seconds + (nanoseconds / 1000000000); +- if (NULL == (tm = gmtime(&ts))) +- ND_PRINT(": gmtime() error"); +- else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) +- ND_PRINT(": strftime() error"); +- else +- ND_PRINT(": %s, %09u ns, ", buf, nanoseconds); ++ ND_PRINT(": %s, %09u ns, ", ++ nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ++ gmtime(&ts)), nanoseconds); + } + + int +diff --git a/print-rx.c b/print-rx.c +index 26b51c19d..0a1a8d12d 100644 +--- a/print-rx.c ++++ b/print-rx.c +@@ -794,12 +794,12 @@ rx_cache_find(netdissect_options *ndo, const struct rx_header *rxh, + ND_PRINT(" %" PRIu64, _i); \ + } + +-#define DATEOUT() { time_t _t; struct tm *tm; char str[256]; \ ++#define DATEOUT() { time_t _t; char str[256]; \ + _t = (time_t) GET_BE_S_4(bp); \ + bp += sizeof(int32_t); \ +- tm = localtime(&_t); \ +- strftime(str, 256, "%Y/%m/%d %H:%M:%S", tm); \ +- ND_PRINT(" %s", str); \ ++ ND_PRINT(" %s", \ ++ nd_format_time(str, sizeof(str), \ ++ "%Y/%m/%d %H:%M:%S", localtime(&_t))); \ + } + + #define STOREATTROUT() { uint32_t mask, _i; \ +diff --git a/print-zep.c b/print-zep.c +index 8119a19e9..52901e789 100644 +--- a/print-zep.c ++++ b/print-zep.c +@@ -83,12 +83,11 @@ static void zep_print_ts(netdissect_options *ndo, const u_char *p) + */ + if (i) { + time_t seconds = i - JAN_1970; +- struct tm *tm; + char time_buf[128]; + +- tm = localtime(&seconds); +- strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm); +- ND_PRINT(" (%s)", time_buf); ++ ND_PRINT(" (%s)", ++ nd_format_time(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", ++ localtime(&seconds))); + } + #endif + } +diff --git a/smbutil.c b/smbutil.c +index 9e19909a2..97217a8d9 100644 +--- a/smbutil.c ++++ b/smbutil.c +@@ -768,9 +768,8 @@ smb_fdata1(netdissect_options *ndo, + case 'T': + { + time_t t; +- struct tm *lt; + const char *tstring; +- char buffer[sizeof("Www Mmm dd hh:mm:ss yyyy\n")]; ++ char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy")]; + uint32_t x; + + switch (atoi(fmt + 1)) { +@@ -800,16 +799,11 @@ smb_fdata1(netdissect_options *ndo, + break; + } + if (t != 0) { +- lt = localtime(&t); +- if (lt != NULL) { +- strftime(buffer, sizeof(buffer), "%a %b %e %T %Y%n", lt); +- tstring = buffer; +- } +- else +- tstring = "(Can't convert time)\n"; ++ tstring = nd_format_time(buffer, sizeof(buffer), "%a %b %e %T %Y", ++ localtime(&t)); + } else +- tstring = "NULL\n"; +- ND_PRINT("%s", tstring); ++ tstring = "NULL"; ++ ND_PRINT("%s\n", tstring); + fmt++; + while (ND_ASCII_ISDIGIT(*fmt)) + fmt++; +diff --git a/tcpdump.c b/tcpdump.c +index 78d0871a5..0b6541589 100644 +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -843,6 +843,8 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) + char *filename = malloc(PATH_MAX + 1); + if (filename == NULL) + error("%s: malloc", __func__); ++ if (strlen(orig_name) == 0) ++ error("an empty string is not a valid file name"); + + /* Process with strftime if Gflag is set. */ + if (Gflag != 0) { +@@ -854,9 +856,25 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) + } + + /* There's no good way to detect an error in strftime since a return +- * value of 0 isn't necessarily failure. ++ * value of 0 isn't necessarily failure; if orig_name is an empty ++ * string, the formatted string will be empty. ++ * ++ * However, the C90 standard says that, if there *is* a ++ * buffer overflow, the content of the buffer is undefined, ++ * so we must check for a buffer overflow. ++ * ++ * So we check above for an empty orig_name, and only call ++ * strftime() if it's non-empty, in which case the return ++ * value will only be 0 if the formatted date doesn't fit ++ * in the buffer. ++ * ++ * (We check above because, even if we don't use -G, we ++ * want a better error message than "tcpdump: : No such ++ * file or directory" for this case.) + */ +- strftime(filename, PATH_MAX, orig_name, local_tm); ++ if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) { ++ error("%s: strftime", __func__); ++ } + } else { + strncpy(filename, orig_name, PATH_MAX); + } +diff --git a/util-print.c b/util-print.c +index 8b2064972..054833786 100644 +--- a/util-print.c ++++ b/util-print.c +@@ -230,7 +230,8 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec, + { + time_t Time = sec; + struct tm *tm; +- char timestr[32]; ++ char timebuf[32]; ++ const char *timestr; + + if ((unsigned)sec & 0x80000000) { + ND_PRINT("[Error converting time]"); +@@ -242,14 +243,13 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec, + else + tm = gmtime(&Time); + +- if (!tm) { +- ND_PRINT("[Error converting time]"); +- return; ++ if (date_flag == WITH_DATE) { ++ timestr = nd_format_time(timebuf, sizeof(timebuf), ++ "%Y-%m-%d %H:%M:%S", tm); ++ } else { ++ timestr = nd_format_time(timebuf, sizeof(timebuf), ++ "%H:%M:%S", tm); + } +- if (date_flag == WITH_DATE) +- strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm); +- else +- strftime(timestr, sizeof(timestr), "%H:%M:%S", tm); + ND_PRINT("%s", timestr); + + ts_frac_print(ndo, usec); +@@ -405,6 +405,26 @@ signed_relts_print(netdissect_options *ndo, + unsigned_relts_print(ndo, secs); + } + ++/* ++ * Format a struct tm with strftime(). ++ * If the pointer to the struct tm is null, that means that the ++ * routine to convert a time_t to a struct tm failed; the localtime() ++ * and gmtime() in the Microsoft Visual Studio C library will fail, ++ * returning null, if the value is before the UNIX Epoch. ++ */ ++const char * ++nd_format_time(char *buf, size_t bufsize, const char *format, ++ const struct tm *timeptr) ++{ ++ if (timeptr != NULL) { ++ if (strftime(buf, bufsize, format, timeptr) != 0) ++ return (buf); ++ else ++ return ("[nd_format_time() buffer is too small]"); ++ } else ++ return ("[localtime() or gmtime() couldn't convert the date and time]"); ++} ++ + /* Print the truncated string */ + void nd_print_trunc(netdissect_options *ndo) + { diff --git a/tcpdump.spec b/tcpdump.spec index 8696568..98b54ba 100644 --- a/tcpdump.spec +++ b/tcpdump.spec @@ -1,7 +1,7 @@ Name: tcpdump Epoch: 14 Version: 4.99.1 -Release: 5 +Release: 6 Summary: A network traffic monitoring tool License: BSD with advertising URL: http://www.tcpdump.org @@ -16,6 +16,8 @@ Patch2: backport-0007-Introduce-nn-option.patch Patch3: backport-0009-Change-n-flag-to-nn-in-TESTonce.patch Patch4: backport-Set-SA_RESTART-non-lethal-signals-avoid-corrupting-binary-pcap-output.patch Patch5: tcpdump-Add-sw64-architecture.patch +Patch6: backport-CVE-2023-1801-pre-smbutil-Replace-obsolete-function-call-asctime.patch +Patch7: backport-CVE-2023-1801.patch Requires(pre): shadow-utils BuildRequires: automake openssl-devel libpcap-devel git-core gcc @@ -89,6 +91,12 @@ make check %{_mandir}/man8/tcpdump.8* %changelog +* Sat Apr 08 2023 gaihuiying - 14:4.99.1-6 +- Type:CVE +- CVE:CVE-2023-1801 +- SUG:NA +- DESC:fix CVE-2023-1801 + * Tue Oct 25 2022 wuzx - 14:4.99.1-5 - Type:feature - CVE:NA -- Gitee