Prereq: "3.3.0" diff -ur --new-file /var/tmp/postfix-3.3.0/src/global/mail_version.h ./src/global/mail_version.h --- /var/tmp/postfix-3.3.0/src/global/mail_version.h 2018-02-21 19:17:21.000000000 -0500 +++ ./src/global/mail_version.h 2018-05-19 16:14:35.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 "20180221" -#define MAIL_VERSION_NUMBER "3.3.0" +#define MAIL_RELEASE_DATE "20180519" +#define MAIL_VERSION_NUMBER "3.3.1" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -ur --new-file /var/tmp/postfix-3.3.0/HISTORY ./HISTORY --- /var/tmp/postfix-3.3.0/HISTORY 2018-02-19 11:29:00.000000000 -0500 +++ ./HISTORY 2018-05-19 16:13:44.000000000 -0400 @@ -23334,3 +23334,33 @@ built-in or service-defined parameters for ldap, *sql, etc. database names. Problem reported by Christian Rößner. Files: postconf/postconf_user.c. + +20180306 + + Bugfix (introduced: 19990302): when luser_relay specifies + a non-existent local address, the luser_relay feature becomes + a black hole. Reported by Jørgen Thomsen. File: local/unknown.c. + +20180422 + + Bugfix (introduced: Postfix 2.8): missing tls_server_start() + error propagation in tlsproxy(8) resulting in segfault after + TLS handshake error. Found during code maintenance. File: + tlsproxy/tlsproxy.c. + +20180509 + + Bugfix (introduced: 20170617): postconf(1) command segfault + if unable to open a Postfix database configuration file due + to a file permission error. Report by Andreas Hasenack, fix + by Viktor Dukhovni. File: postconf/postconf_dbms.c. + +20180519 + + Cleanup: Postfix did not support running as a PID=1 process, + which complicated Postfix management in containers. The + "postfix start-fg" command will now run the Postfix master + daemon as a PID=1 process if possible. Thanks to inputs + from Andreas Schulze, Eray Aslan, and Viktor Dukhovni. + Files: postfix/postfix.c, master/master.c, master/master.h, + master/master_sig.c, conf/postfix-script. diff -ur --new-file /var/tmp/postfix-3.3.0/conf/postfix-script ./conf/postfix-script --- /var/tmp/postfix-3.3.0/conf/postfix-script 2017-12-27 17:30:27.000000000 -0500 +++ ./conf/postfix-script 2018-05-19 10:17:23.000000000 -0400 @@ -150,11 +150,16 @@ ;; start-fg) # Foreground start-up is incompatible with multi-instance mode. - # We can't use "exec $daemon_directory/master" here: that would - # break process group management, and "postfix stop" would kill - # too many processes. + # Use "exec $daemon_directory/master" only if PID == 1. + # Otherwise, doing so would break process group management, + # and "postfix stop" would kill too many processes. case $instances in - "") $daemon_directory/master + "") case $$ in + 1) exec $daemon_directory/master -i + $FATAL "cannot start-fg the master daemon" + exit 1;; + *) $daemon_directory/master;; + esac ;; *) $FATAL "start-fg does not support multi_instance_directories" exit 1 diff -ur --new-file /var/tmp/postfix-3.3.0/html/master.8.html ./html/master.8.html --- /var/tmp/postfix-3.3.0/html/master.8.html 2018-01-14 11:48:37.000000000 -0500 +++ ./html/master.8.html 2018-05-19 15:48:33.000000000 -0400 @@ -10,7 +10,7 @@ master - Postfix master process SYNOPSIS - master [-Ddtvw] [-c config_dir] [-e exit_time] + master [-Dditvw] [-c config_dir] [-e exit_time] DESCRIPTION The master(8) daemon is the resident process that runs Postfix daemons @@ -47,6 +47,11 @@ Terminate the master process after exit_time seconds. Child pro- cesses terminate at their convenience. + -i Enable init mode: do not attempt to become a session or process + group leader; and to force termination, set an explicit signal + handler instead of relying on the default signal action. This + mode is allowed only if the process ID equals 1. + -t Test mode. Return a zero exit status when the master.pid lock file does not exist or when that file is not locked. This is evidence that the master(8) daemon is not running. diff -ur --new-file /var/tmp/postfix-3.3.0/html/postfix.1.html ./html/postfix.1.html --- /var/tmp/postfix-3.3.0/html/postfix.1.html 2018-02-11 10:17:59.000000000 -0500 +++ ./html/postfix.1.html 2018-05-19 15:47:30.000000000 -0400 @@ -37,13 +37,14 @@ check described above. start-fg - Like start, but keep the master daemon running in the fore- - ground. This requires that multi-instance support is disabled - (i.e. the multi_instance_directories parameter value must be - empty). When running Postfix inside a container, mount the con- - tainer host's /dev/log socket inside the container (example: - "docker run -v /dev/log:/dev/log ...") and specify a distinct - Postfix "syslog_name" prefix that identifies logging from the + Like start, but keep the master(8) daemon running in the fore- + ground, and enable master(8) "init" mode when running as PID 1. + This command requires that multi-instance support is disabled + (i.e. the multi_instance_directories parameter value must be + empty). When running Postfix inside a container, mount the con- + tainer host's /dev/log socket inside the container (example: + "docker run -v /dev/log:/dev/log ...") and specify a distinct + Postfix "syslog_name" prefix that identifies logging from the Postfix instance. stop Stop the Postfix mail system in an orderly fashion. If possible, diff -ur --new-file /var/tmp/postfix-3.3.0/man/man1/postfix.1 ./man/man1/postfix.1 --- /var/tmp/postfix-3.3.0/man/man1/postfix.1 2018-02-11 10:17:59.000000000 -0500 +++ ./man/man1/postfix.1 2018-05-19 15:45:33.000000000 -0400 @@ -38,8 +38,10 @@ Start the Postfix mail system. This also runs the configuration check described above. .IP \fBstart\-fg\fR -Like \fBstart\fR, but keep the master daemon running in the -foreground. This requires that multi\-instance support is +Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running +in the foreground, and enable \fBmaster\fR(8) "init" mode +when running as PID 1. +This command requires that multi\-instance support is disabled (i.e. the multi_instance_directories parameter value must be empty). When running Postfix inside a container, mount the container host's /dev/log socket inside the diff -ur --new-file /var/tmp/postfix-3.3.0/man/man8/master.8 ./man/man8/master.8 --- /var/tmp/postfix-3.3.0/man/man8/master.8 2018-01-14 11:48:35.000000000 -0500 +++ ./man/man8/master.8 2018-05-19 15:45:33.000000000 -0400 @@ -8,7 +8,7 @@ .SH "SYNOPSIS" .na .nf -\fBmaster\fR [\fB\-Ddtvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR] +\fBmaster\fR [\fB\-Dditvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR] .SH DESCRIPTION .ad .fi @@ -43,6 +43,12 @@ .IP "\fB\-e \fIexit_time\fR" Terminate the master process after \fIexit_time\fR seconds. Child processes terminate at their convenience. +.IP \fB\-i\fR +Enable \fBinit\fR mode: do not attempt to become a session +or process group leader; and to force termination, set an +explicit signal handler instead of relying on the default +signal action. This mode is allowed only if the process ID +equals 1. .IP \fB\-t\fR Test mode. Return a zero exit status when the \fBmaster.pid\fR lock file does not exist or when that file is not locked. This is evidence diff -ur --new-file /var/tmp/postfix-3.3.0/src/local/unknown.c ./src/local/unknown.c --- /var/tmp/postfix-3.3.0/src/local/unknown.c 2015-01-11 15:30:20.000000000 -0500 +++ ./src/local/unknown.c 2018-03-06 19:29:36.000000000 -0500 @@ -73,11 +73,14 @@ #include #include #include +#include /* Application-specific. */ #include "local.h" +#define STREQ(x,y) (strcasecmp((x),(y)) == 0) + /* deliver_unknown - delivery for unknown recipients */ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) @@ -85,6 +88,7 @@ const char *myname = "deliver_unknown"; int status; VSTRING *expand_luser; + VSTRING *canon_luser; static MAPS *transp_maps; const char *map_transport; @@ -139,8 +143,20 @@ if (*var_luser_relay) { state.msg_attr.unmatched = 0; expand_luser = vstring_alloc(100); + canon_luser = vstring_alloc(100); local_expand(expand_luser, var_luser_relay, &state, &usr_attr, (void *) 0); - status = deliver_resolve_addr(state, usr_attr, STR(expand_luser)); + /* In case luser_relay specifies a domain-less address. */ + canon_addr_external(canon_luser, vstring_str(expand_luser)); + /* Assumes that the address resolver won't change the address. */ + if (STREQ(vstring_str(canon_luser), state.msg_attr.rcpt.address)) { + dsb_simple(state.msg_attr.why, "5.1.1", + "unknown user: \"%s\"", state.msg_attr.user); + status = bounce_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } else { + status = deliver_resolve_addr(state, usr_attr, STR(expand_luser)); + } + vstring_free(canon_luser); vstring_free(expand_luser); return (status); } @@ -149,8 +165,6 @@ * If no alias was found for a required reserved name, toss the message * into the bit bucket, and issue a warning instead. */ -#define STREQ(x,y) (strcasecmp(x,y) == 0) - if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON) || STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) { msg_warn("required alias not found: %s", state.msg_attr.user); diff -ur --new-file /var/tmp/postfix-3.3.0/src/master/master.c ./src/master/master.c --- /var/tmp/postfix-3.3.0/src/master/master.c 2018-01-14 11:48:25.000000000 -0500 +++ ./src/master/master.c 2018-05-19 15:16:11.000000000 -0400 @@ -4,7 +4,7 @@ /* SUMMARY /* Postfix master process /* SYNOPSIS -/* \fBmaster\fR [\fB-Ddtvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR] +/* \fBmaster\fR [\fB-Dditvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR] /* DESCRIPTION /* The \fBmaster\fR(8) daemon is the resident process that runs Postfix /* daemons on demand: daemons to send or receive messages via the @@ -37,6 +37,12 @@ /* .IP "\fB-e \fIexit_time\fR" /* Terminate the master process after \fIexit_time\fR seconds. Child /* processes terminate at their convenience. +/* .IP \fB-i\fR +/* Enable \fBinit\fR mode: do not attempt to become a session +/* or process group leader; and to force termination, set an +/* explicit signal handler instead of relying on the default +/* signal action. This mode is allowed only if the process ID +/* equals 1. /* .IP \fB-t\fR /* Test mode. Return a zero exit status when the \fBmaster.pid\fR lock /* file does not exist or when that file is not locked. This is evidence @@ -229,6 +235,7 @@ #include "master.h" int master_detach = 1; +int init_mode = 0; /* master_exit_event - exit for memory leak testing purposes */ @@ -334,7 +341,7 @@ /* * Process JCL. */ - while ((ch = GETOPT(argc, argv, "c:Dde:tvw")) > 0) { + while ((ch = GETOPT(argc, argv, "c:Dde:itvw")) > 0) { switch (ch) { case 'c': if (setenv(CONF_ENV_PATH, optarg, 1) < 0) @@ -346,6 +353,11 @@ case 'e': event_request_timer(master_exit_event, (void *) 0, atoi(optarg)); break; + case 'i': + if (getpid() != 1) + msg_fatal("-i is allowed only for PID 1 process"); + init_mode = 1; + break; case 'D': debug_me = 1; break; @@ -375,6 +387,8 @@ */ if (test_lock && wait_flag) msg_fatal("the -t and -w options cannot be used together"); + if (init_mode && (debug_me || !master_detach || wait_flag)) + msg_fatal("the -i option cannot be used with -D, -d, or -w"); /* * Run a foreground monitor process that returns an exit status of 0 when @@ -403,7 +417,8 @@ * all MTA processes cleanly. Give up if we can't separate from our * parent process. We're not supposed to blow away the parent. */ - if (debug_me == 0 && master_detach != 0 && setsid() == -1 && getsid(0) != getpid()) + if (init_mode == 0 && debug_me == 0 && master_detach != 0 + && setsid() == -1 && getsid(0) != getpid()) msg_fatal("unable to set session and process group ID: %m"); /* diff -ur --new-file /var/tmp/postfix-3.3.0/src/master/master.h ./src/master/master.h --- /var/tmp/postfix-3.3.0/src/master/master.h 2012-03-06 17:06:35.000000000 -0500 +++ ./src/master/master.h 2018-04-04 18:59:07.000000000 -0400 @@ -109,6 +109,7 @@ * master.c */ extern int master_detach; +extern int init_mode; /* * master_ent.c diff -ur --new-file /var/tmp/postfix-3.3.0/src/master/master_sig.c ./src/master/master_sig.c --- /var/tmp/postfix-3.3.0/src/master/master_sig.c 2014-12-06 20:35:33.000000000 -0500 +++ ./src/master/master_sig.c 2018-05-19 10:47:08.000000000 -0400 @@ -200,6 +200,15 @@ msg_info("terminating on signal %d", sig); /* + * Undocumented: when a process runs with PID 1, Linux won't deliver a + * signal unless the process specifies a handler (i.e. SIG_DFL is treated + * as SIG_IGN). + */ + if (init_mode) + /* Don't call exit() from a signal handler. */ + _exit(0); + + /* * Deliver the signal to ourselves and clean up. XXX We're running as a * signal handler and really should not be doing complicated things... */ diff -ur --new-file /var/tmp/postfix-3.3.0/src/postconf/postconf_dbms.c ./src/postconf/postconf_dbms.c --- /var/tmp/postfix-3.3.0/src/postconf/postconf_dbms.c 2018-02-18 20:48:47.000000000 -0500 +++ ./src/postconf/postconf_dbms.c 2018-05-09 01:17:49.000000000 -0400 @@ -174,10 +174,10 @@ */ dict = dict_ht_open(dict_spec, O_CREAT | O_RDWR, 0); dict_register(dict_spec, dict); - if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0 - && errno != EACCES) { - msg_warn("open \"%s\" configuration \"%s\": %m", - dp->db_type, cf_file); + if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0) { + if (errno != EACCES) + msg_warn("open \"%s\" configuration \"%s\": %m", + dp->db_type, cf_file); myfree(dict_spec); return; } diff -ur --new-file /var/tmp/postfix-3.3.0/src/postfix/postfix.c ./src/postfix/postfix.c --- /var/tmp/postfix-3.3.0/src/postfix/postfix.c 2018-02-11 10:17:58.000000000 -0500 +++ ./src/postfix/postfix.c 2018-05-19 11:13:16.000000000 -0400 @@ -32,8 +32,10 @@ /* Start the Postfix mail system. This also runs the configuration /* check described above. /* .IP \fBstart-fg\fR -/* Like \fBstart\fR, but keep the master daemon running in the -/* foreground. This requires that multi-instance support is +/* Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running +/* in the foreground, and enable \fBmaster\fR(8) "init" mode +/* when running as PID 1. +/* This command requires that multi-instance support is /* disabled (i.e. the multi_instance_directories parameter /* value must be empty). When running Postfix inside a container, /* mount the container host's /dev/log socket inside the diff -ur --new-file /var/tmp/postfix-3.3.0/src/tlsproxy/tlsproxy.c ./src/tlsproxy/tlsproxy.c --- /var/tmp/postfix-3.3.0/src/tlsproxy/tlsproxy.c 2018-01-14 11:48:25.000000000 -0500 +++ ./src/tlsproxy/tlsproxy.c 2018-05-19 08:02:00.000000000 -0400 @@ -663,7 +663,7 @@ /* tlsp_start_tls - turn on TLS or force disconnect */ -static void tlsp_start_tls(TLSP_STATE *state) +static int tlsp_start_tls(TLSP_STATE *state) { TLS_SERVER_START_PROPS props; static char *cipher_grade; @@ -716,7 +716,7 @@ if (state->tls_context == 0) { tlsp_state_free(state); - return; + return (-1); } /* @@ -729,6 +729,7 @@ * XXX Do we care about certificate verification results? Not as long as * postscreen(8) doesn't actually receive email. */ + return (0); } /* tlsp_get_fd_event - receive final postscreen(8) hand-off information */ @@ -776,7 +777,8 @@ * Perform the TLS layer before-handshake initialization. We perform the * remainder after the TLS handshake completes. */ - tlsp_start_tls(state); + if (tlsp_start_tls(state) < 0) + return; /* * Trigger the initial proxy server I/Os. diff -ur --new-file /var/tmp/postfix-3.3.0/src/util/killme_after.c ./src/util/killme_after.c --- /var/tmp/postfix-3.3.0/src/util/killme_after.c 2006-12-05 09:35:35.000000000 -0500 +++ ./src/util/killme_after.c 2018-05-19 14:59:59.000000000 -0400 @@ -46,11 +46,17 @@ * Schedule an ALARM signal, and make sure the signal will be delivered * even if we are being called from a signal handler and SIGALRM delivery * is blocked. + * + * Undocumented: when a process runs with PID 1, Linux won't deliver a + * signal unless the process specifies a handler (i.e. SIG_DFL is treated + * as SIG_IGN). Conveniently, _exit() can be used directly as a signal + * handler. This changes the wait status that a parent would see, but in + * the case of "init" mode on Linux, no-one would care. */ alarm(0); sigemptyset(&sig_action.sa_mask); sig_action.sa_flags = 0; - sig_action.sa_handler = SIG_DFL; + sig_action.sa_handler = (getpid() == 1 ? _exit : SIG_DFL); sigaction(SIGALRM, &sig_action, (struct sigaction *) 0); alarm(seconds); sigaddset(&sig_action.sa_mask, SIGALRM);