Prereq: "3.9.11" diff -ur --new-file /var/tmp/postfix-3.9.11/src/global/mail_version.h ./src/global/mail_version.h --- /var/tmp/postfix-3.9.11/src/global/mail_version.h 2026-05-15 15:53:10.000000000 -0400 +++ ./src/global/mail_version.h 2026-06-17 13:18:11.000000000 -0400 @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20260515" -#define MAIL_VERSION_NUMBER "3.9.11" +#define MAIL_RELEASE_DATE "20260617" +#define MAIL_VERSION_NUMBER "3.9.12" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -ur --new-file /var/tmp/postfix-3.9.11/HISTORY ./HISTORY --- /var/tmp/postfix-3.9.11/HISTORY 2026-05-15 15:55:27.000000000 -0400 +++ ./HISTORY 2026-06-17 13:17:15.000000000 -0400 @@ -28354,3 +28354,173 @@ implementation-defined behavior (shift one bit into the sign position). This works today but may break later. Reported by Kamil Frankowicz. File: util/sys_defs.h. + +20260524 + + Bugfix (defect introduced: Postfix 3.1, date 20150607): + null pointer read and heap data overread in the Postfix + SMTP client's smtp_dns_reply_filter. 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. + + This is a different problem than the one that was introduced + later in Postfix 3.6. + + The root cause is a missing 'break' statement after the + code that converts a TLSA record to string. + + Reproduction: + ============= + + The problem happens when smtp_dns_reply_filter is configured + (this is disabled by default); the Postfix SMTP client is + configured to use opportunistic or mandatory DANE authentication + (this is disabled by default); 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, as long as these resolvers are used without + systemd-resolved. + + Impact statement: + ================= + + SMTP client termination with a null pointer read crash when + the TLSA record length is zero; or an SMTP client data + overread (or rarely, SMTP client termination with a read + segfault crash) when 0 < record length < 20 bytes. The + overread content is not disclosed. + + The impact of SMTP client crashes is easily overstated. + That said, crashes must be eliminated regardless of their + impact. + + On systems that deliver fewer than one message per minute, + an SMTP client 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). + +20260529 + + Robustness: the 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 (Ibonok). Under + high load conditions, the amount of text was already limited + by a 10-second deadline to receive an SMTP command. File: + global/smtp_stream.c. + + 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. + + Impact statement: + ================= + + Postfix should not receive and discard unlimited amounts + of input in SMTP commands, but fixing that will not + fundamentally change the situation. + + By design, any SMTP client can force a server to receive + (and discard) an unlimited amount of text. For example, + an attacker can repeatedly send messages that are a little + under the server's message size limit and abort each + transaction a before reaching the message end. When sending + a message with the "DATA" command, an attacker would + disconnect instead of sending .; and when + sending a message with the "BDAT" command, an attacker would + send "RSET" instead of "BDAT LAST". + + To mitigate such abuse, Postfix can rate-limit the number + of message transactions from the same IP address or address + range (see smtpd_client_message_rate_limit and *prefix_length + parameters). Such a defense is ineffective when faced with + a distributed attack (botnet); for that, postscreen combined + with an IP reputation service (DNSBL) may be more effective. + +20260531 + + Bugfix: (defect introduced: Postfix 3.6, date: 20200710): + panic (assertion failure and voluntary crash) while parsing + a TLSA reply with length 3. Found during code maintenance. + See below for root cause, reproduction, and impact. + + Root cause: + =========== + + An incorrect test 'length < 3' instead of 'length <= 3' + causes a safety check to fail when a TLSA parser attempts + to create zero-length storage for a non-existent TLSA + certificate association data field. + + Reproduction: + ============= + + The problem happens when the Postfix SMTP client is configured + to use opportunistic or mandatory DANE authentication (this + is disabled by default); a destination domain publishes a + TLSA record with a length of three bytes; and the OS is + configured to use a resolver that passes such a TLSA record. + For example, a length-three TLSA record is blocked by BIND, + and by configurations that use systemd-resolved (the default + on many LINUX systems). It is passed by many other resolvers. + + This bug enables an attack that is more potent than the + TLSA parsing bug introduced with Postfix 3.1. + + - An attack with a length-three TLSA reply does not depend + on smtp_dns_reply_filter configuration. + + - An attack with a length-three TLSA reply propagates through + more resolvers than an attack with a length-zero TLSA reply. + + Impact statement: + ================= + + SMTP client voluntary termination (crash) after an assertion + failure. This is a fail-safe mechanism. + + The impact of SMTP client crashes (voluntary or not) is + easily overstated. That said, crashes must be eliminated + regardless of their impact. + + On systems that deliver fewer than one message per minute, + an SMTP client 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 an + SMTP client 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). + +20260608 + + Bugfix (defect introduced: Postfix 3.0, date: 20140708): + the SMTP client did not xtext_quote a '+' character in a + DSN ORCPT parameter value. A strict receiver implementation + could reject or discard the parameter value, but this has + never been reported to happen. Found during code maintenance. + File: smtp_proto.c. diff -ur --new-file /var/tmp/postfix-3.9.11/html/smtpd.8.html ./html/smtpd.8.html --- /var/tmp/postfix-3.9.11/html/smtpd.8.html 2025-11-25 12:29:01.000000000 -0500 +++ ./html/smtpd.8.html 2026-06-17 13:21:00.000000000 -0400 @@ -264,7 +264,7 @@ sions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. - milter_default_action (tempfail) + milter_default_action (see 'postconf -d milter_default_action' output) The default action when a Milter (mail filter) response is unavailable (for example, bad Postfix configuration or Milter failure). diff -ur --new-file /var/tmp/postfix-3.9.11/man/man8/smtpd.8 ./man/man8/smtpd.8 --- /var/tmp/postfix-3.9.11/man/man8/smtpd.8 2025-11-25 12:29:01.000000000 -0500 +++ ./man/man8/smtpd.8 2026-06-17 13:21:00.000000000 -0400 @@ -259,7 +259,7 @@ The mail filter protocol version and optional protocol extensions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. -.IP "\fBmilter_default_action (tempfail)\fR" +.IP "\fBmilter_default_action (see 'postconf -d milter_default_action' output)\fR" The default action when a Milter (mail filter) response is unavailable (for example, bad Postfix configuration or Milter failure). diff -ur --new-file /var/tmp/postfix-3.9.11/src/dns/dns_strrecord.c ./src/dns/dns_strrecord.c --- /var/tmp/postfix-3.9.11/src/dns/dns_strrecord.c 2023-02-13 15:58:00.000000000 -0500 +++ ./src/dns/dns_strrecord.c 2026-06-17 13:17:15.000000000 -0400 @@ -99,6 +99,8 @@ } 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 -ur --new-file /var/tmp/postfix-3.9.11/src/global/smtp_stream.c ./src/global/smtp_stream.c --- /var/tmp/postfix-3.9.11/src/global/smtp_stream.c 2024-01-12 13:39:59.000000000 -0500 +++ ./src/global/smtp_stream.c 2026-06-17 13:17:15.000000000 -0400 @@ -457,8 +457,12 @@ && 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 -ur --new-file /var/tmp/postfix-3.9.11/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c --- /var/tmp/postfix-3.9.11/src/smtp/smtp_proto.c 2025-10-23 19:46:29.000000000 -0400 +++ ./src/smtp/smtp_proto.c 2026-06-17 13:17:15.000000000 -0400 @@ -1787,7 +1787,7 @@ vstring_sprintf_append(next_command, " ORCPT=%s", vstring_str(session->scratch)); } else { - xtext_quote(session->scratch, orcpt_type_addr, "="); + xtext_quote(session->scratch, orcpt_type_addr, "+="); vstring_sprintf_append(next_command, " ORCPT=%s", vstring_str(session->scratch)); } diff -ur --new-file /var/tmp/postfix-3.9.11/src/smtpd/smtpd.c ./src/smtpd/smtpd.c --- /var/tmp/postfix-3.9.11/src/smtpd/smtpd.c 2025-10-23 19:46:29.000000000 -0400 +++ ./src/smtpd/smtpd.c 2026-06-17 13:21:00.000000000 -0400 @@ -233,7 +233,7 @@ /* The mail filter protocol version and optional protocol extensions /* for communication with a Milter application; prior to Postfix 2.6 /* the default protocol is 2. -/* .IP "\fBmilter_default_action (tempfail)\fR" +/* .IP "\fBmilter_default_action (see 'postconf -d milter_default_action' output)\fR" /* The default action when a Milter (mail filter) response is /* unavailable (for example, bad Postfix configuration or Milter /* failure). @@ -3936,6 +3936,21 @@ 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. */ @@ -3953,6 +3968,16 @@ 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. */ if (final_chunk) diff -ur --new-file /var/tmp/postfix-3.9.11/src/tls/tls_dane.c ./src/tls/tls_dane.c --- /var/tmp/postfix-3.9.11/src/tls/tls_dane.c 2023-08-07 09:42:24.000000000 -0400 +++ ./src/tls/tls_dane.c 2026-06-17 13:17:15.000000000 -0400 @@ -520,7 +520,7 @@ 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);