From: Wietse Z Venema Date: Mon, 1 Jun 2026 05:00:00 +0000 (-0500) Subject: postfix-3.12-20260601 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=68acca813649899be069abedb34cbdada849b68f;p=thirdparty%2Fpostfix.git postfix-3.12-20260601 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 4a30c1525..1906d84fd 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -31172,6 +31172,76 @@ Apologies for any names omitted. Re-indented the source code after deleting 'stat' and adding missing types to .indent.pro. +20260524 + + Bugfix (defect introduced: Postfix 3.1, date 20150607): + null pointer dereference and heap data overread in the + Postfix SMTP client's smtp_dns_reply_filter (this is disabled + by default), when the Postfix SMTP client is configured to + use opportunistic or mandatory DANE authentication (this + is disabled by default); and the destination domain publishes + a TLSA record that is empty or shorter than 20 bytes; and + the OS is configured to use a resolver that passes such a + TLSA record. For example, a zero-length TLSA record is + blocked by BIND, Google DNS, OpenDNS, and by configurations + that use systemd-resolved (the default on many LINUX systems); + it is passed by Cloudflare, Quad9 DNS, and unbound, if these + resolvers are used without systemd-resolved. + + The root cause is a missing 'break' statement after the + code that converts a TLSA record to string, resulting in a + null pointer crash when the record length is zero; or a + data overread (or rarely, a segfault) with 0 < record length + < 20 bytes. The overread content is not disclosed. + + The impact of crashes is easily overstated. That said, + crashes must be eliminated regardless of their impact. + + On systems that deliver fewer than one message per minute, + a null pointer or other segfault crash can result in a delay + of up to one minute for email delivery to other destination + domains. + + On systems with a larger traffic volume, the impact of a + null pointer or other segfault crash on deliveries to other + destination domains is minor because Postfix reuses SMTP + client processes and replaces a failed process within seconds + (self-healing); the practical impact is believed to be no + worse than that of an uncooperative receiver that tarpits + SMTP connections from Postfix to one or more destination + domains under their control (by replying within Postfix + SMTP client read time limits which are several minutes by + default). + + Problem reported by TristanInSec, found with ASAN. Also + reported by other people. Reproduction and real-world impact + researched by Wietse. File: dns/dns_strrecord.c. + +20260529 + + Robustness: Postfix SMTP server will no longer receive (and + discard) an unlimited amount of text while receiving a long + SMTP command line. Problem introduced: Postfix 2.9, date: + 20110205; reported by Michael Wollner. Under high load + conditions, the amount of text was already limited by a + 10-second deadline to receive an SMTP command. Files: + global/smtp_stream.c, smtpd/smtpd.c, smtpd/smtpd_chat.h. + + Robustness: with the above change the Postfix SMTP client + will no longer receive (and discard) an unlimited amount + of text while receiving a long SMTP response line. + + Robustness: do not receive (and discard) unlimited amounts + of data with BDAT commands. Problem introduced: Postfix + 3.4, date: 20180825; found during code maintenance. File: + smtpd/smtpd.c. + +20260531 + + Bugfix: (defect introduced: Postfix 3.6, date: 20200710): + panic() while parsing a TLSA record with length 3. Found + during code maintenance. File: tls/tls_dane.c. + TODO Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc. diff --git a/postfix/proto/stop b/postfix/proto/stop index e7e6efe2f..937f37ec6 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1720,3 +1720,5 @@ substrings Substring tlstrace yyyymmddhhmmss +ASAN +TristanInSec diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index 2a32e3bee..2dde19d54 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -261,3 +261,4 @@ proto proto stop proto stop double cc tlsproxy tlsproxy c tlsproxy tlsproxy_client c postscreen postscreen c postscreen postscreen_tls_conf c anvil anvil c global anvil_clnt hc proto postconf proto + global smtp_stream c smtpd smtpd c smtpd smtpd_chat h diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index f1f938112..816e252d8 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -140,3 +140,9 @@ sunos WebPKI rf musl +Cloudflare +OpenDNS +overread +resolvers +tarpits +Wollner diff --git a/postfix/src/dns/dns_strrecord.c b/postfix/src/dns/dns_strrecord.c index 1e3b74389..b6dbe69bd 100644 --- a/postfix/src/dns/dns_strrecord.c +++ b/postfix/src/dns/dns_strrecord.c @@ -99,6 +99,8 @@ char *dns_strrecord(VSTRING *buf, DNS_RR *rr) } else { vstring_sprintf_append(buf, "[truncated record]"); } + /* 202605 Missing break found by TristanInSec using ASAN. */ + break; /* * We use the SOA record TTL to determine the negative reply TTL. We diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 047d98af7..e619ac82e 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20260516" +#define MAIL_RELEASE_DATE "20260601" #define MAIL_VERSION_NUMBER "3.12" #ifdef SNAPSHOT diff --git a/postfix/src/global/smtp_stream.c b/postfix/src/global/smtp_stream.c index 662950803..7ac6e0181 100644 --- a/postfix/src/global/smtp_stream.c +++ b/postfix/src/global/smtp_stream.c @@ -457,8 +457,12 @@ int smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags && vstream_feof(stream) == 0 && vstream_ferror(stream) == 0) while ((next_char = VSTREAM_GETC(stream)) != VSTREAM_EOF && next_char != '\n') - /* void */ ; - + if (--bound <= 0) { + msg_warn("disabling input from %s", VSTREAM_PATH(stream)); + vstream_fpurge(stream, VSTREAM_PURGE_READ); + shutdown(vstream_fileno(stream), SHUT_RD); + break; + } return (last_char); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 8e0bc714f..cf9da72a4 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -4034,6 +4034,21 @@ static int skip_bdat(SMTPD_STATE *state, off_t chunk_size, off_t done; off_t len; + /* + * Skip inputs below 1.5 times the message size limit, staying in sync + * with the remote SMTP client. Otherwise, force a negative chunk_size + * value to disable reading and discarding input here, and to force a + * "lost connection" condition upon a later read operation. + */ + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && state->act_size / 1.5 > var_message_limit - chunk_size / 1.5) { + chunk_size = -1; + } else if (state->act_size > OFF_T_MAX - chunk_size) { + state->act_size = OFF_T_MAX; + } else { + state->act_size += chunk_size; + } + /* * Read and discard content from the remote SMTP client. TODO: drop the * connection in case of overload. @@ -4051,6 +4066,16 @@ static int skip_bdat(SMTPD_STATE *state, off_t chunk_size, vsmtpd_chat_reply(state, format, ap); va_end(ap); + /* + * Force a "lost connection" condition upon the next read operation. + */ + if (chunk_size < 0) { + msg_warn("%s: too much BDAT content -- disabling further input from %s", + state->queue_id ? state->queue_id : "NOQUEUE", + state->namaddr); + shutdown(vstream_fileno(state->client), SHUT_RD); + } + /* * Reset state, or drop subsequent BDAT payloads until BDAT LAST or RSET. */ @@ -6098,7 +6123,12 @@ static void smtpd_proto(SMTPD_STATE *state) break; } watchdog_pat(); - smtpd_chat_query(state); + if (!smtpd_chat_query(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "500 5.5.2 %s Error: command too long", + var_myhostname); + continue; + } if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) { log_whatsup(state, "reject", "bare received"); state->error_mask |= MAIL_ERROR_PROTOCOL; diff --git a/postfix/src/smtpd/smtpd_chat.h b/postfix/src/smtpd/smtpd_chat.h index 9fbe178ff..b3e1a83ae 100644 --- a/postfix/src/smtpd/smtpd_chat.h +++ b/postfix/src/smtpd/smtpd_chat.h @@ -26,7 +26,7 @@ extern void vsmtpd_chat_reply(SMTPD_STATE *, const char *, va_list); extern void smtpd_chat_notify(SMTPD_STATE *); #define smtpd_chat_query(state) \ - ((void) smtpd_chat_query_limit((state), var_line_limit)) + smtpd_chat_query_limit((state), var_line_limit) /* LICENSE /* .ad diff --git a/postfix/src/tls/tls_dane.c b/postfix/src/tls/tls_dane.c index 5533b7b71..b5d48ba29 100644 --- a/postfix/src/tls/tls_dane.c +++ b/postfix/src/tls/tls_dane.c @@ -57,9 +57,6 @@ /* void tls_dane_log(TLScontext) /* TLS_SESS_STATE *TLScontext; /* -/* int tls_dane_unusable(dane) -/* const TLS_DANE *dane; -/* /* int tls_dane_notfound(dane) /* const TLS_DANE *dane; /* DESCRIPTION @@ -116,11 +113,6 @@ /* tls_dane_log() logs successful verification via DNS-based or /* synthetic DANE TLSA RRs (fingerprint or "tafile"). /* -/* tls_dane_unusable() checks whether a cached TLS_DANE record is -/* the result of a validated RRset, with no usable elements. In -/* this case, TLS is mandatory, but certificate verification is -/* not DANE-based. -/* /* tls_dane_notfound() checks whether a cached TLS_DANE record is /* the result of a validated DNS lookup returning NODATA. In /* this case, TLS is not required by RFC, though users may elect @@ -518,7 +510,7 @@ static int parse_tlsa_rr(TLS_DANE *dane, DNS_RR *rr) q, a, r, rr->type); /* Drop truncated records */ - if ((dlen = rr->data_len - 3) < 0) { + if ((dlen = rr->data_len - 3) <= 0) { msg_warn("%s%s%s: truncated TLSA RR length == %u", q, a, r, (unsigned) rr->data_len); return (0);