From: Wietse Venema Date: Sun, 9 Jan 2011 05:00:00 +0000 (-0500) Subject: postfix-2.8-20110109 X-Git-Tag: v2.8.0-RC1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=17d7812e9b808f05c6e22daa51768364d12ee925;p=thirdparty%2Fpostfix.git postfix-2.8-20110109 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 29ce6f50f..cad0567ef 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -16149,6 +16149,12 @@ Apologies for any names omitted. reading an entire command, instead of a time limit for reading individual characters. File: postscreen/postscreen_smtpd.c. +20101023 + + Cleanup: don't apply reject_rhsbl_helo to non-domain forms + such as network addresses. This would cause false positives + with dbl.spamhaus.org. File: smtpd/smtpd_check.c. + 20101117 Bugfix: the "421" reply after Milter error was overruled @@ -16157,12 +16163,6 @@ Apologies for any names omitted. as permitted by RFC. Solution by Victor Duchovni. File: smtpd/smtpd.c. -20101023 - - Cleanup: don't apply reject_rhsbl_helo to non-domain forms - such as network addresses. This would cause false positives - with dbl.spamhaus.org. File: smtpd/smtpd_check.c. - 20101124-6 Feature: pattern matching for DNSWL/DNSBL responses. For @@ -16357,11 +16357,11 @@ Apologies for any names omitted. 20110104 Feature: add contact information to each SMTP server reject - message. For example, "smtpd_reject_footer = - call 800-555-0101 for assistance", with macro expansion and - with multi-line support. Files: global/mail_params.h, - mantools/postlink, proto/postconf.proto, smtpd/smtpd.c, - smtpd/smtpd_chat.c, smtpd/smtpd_expand.[hc], util/mac_expand.[hc]. + message. For example, "smtpd_reject_footer = call 800-555-0101 + for assistance", with macro expansion and with multi-line + support. Files: global/mail_params.h, mantools/postlink, + proto/postconf.proto, smtpd/smtpd.c, smtpd/smtpd_chat.c, + smtpd/smtpd_expand.[hc], util/mac_expand.[hc]. 20110105 @@ -16381,7 +16381,7 @@ Apologies for any names omitted. verify server certificates. Files: smtpd/smtpd.c, smtp/smtp_proto.c. -20110106: +20110106 Non-production: cleaned up the tlsproxy support in the Postfix SMTP server for stress testing of the tlsproxy @@ -16403,6 +16403,26 @@ Apologies for any names omitted. compatibility with smtpd_command_filter. Files: postscreen/postscreen_dict.c, postscreen/postscreen_smtpd.c +20110108 + Cleanup: postscreen(8) now displays control characters in PREGREET responses as C-style \letter escapes, instead of "?". File: postscreen/postscreen_early.c. + +20110109 + + Cleanup: Solaris support for "pass" (file descriptor passing + based) services in master.cf. This was needed by postscreen(8). + Also, renamed upass_xxx.c to unix_pass_xxx.c. One-character + prefixes are too short. Removed upass_connect.c because it + was useless code. Files: util/stream_pass_connect.c, + util/unix_pass_listen.c, util/unix_pass_trigger.c. + + Cleanup: on Solaris the Postfix event engine was deaf for + SIGHUP and SIGALRM (and probably more) signals after the + switch to /dev/poll. Symptoms were delayed "postfix reload" + response, and killed processes when the watchdog timeout + was less than max_idle. The fix is to set up SIGHUP and + SIGALRM handlers that write to a pipe, and to monitor that + pipe for read events via the Postfix event engine. Files: + master/master_sig.c, util/watchdog.c. diff --git a/postfix/README_FILES/POSTSCREEN_README b/postfix/README_FILES/POSTSCREEN_README index aa7943119..428d5d6a0 100644 --- a/postfix/README_FILES/POSTSCREEN_README +++ b/postfix/README_FILES/POSTSCREEN_README @@ -5,9 +5,13 @@ PPoossttffiixx PPoossttssccrreeeenn HHoowwttoo IInnttrroodduuccttiioonn The Postfix postscreen(8) server performs triage on multiple inbound SMTP -connections in parallel. While a single postscreen(8) process keeps zombies -away from Postfix SMTP server processes, more Postfix SMTP server processes -remain available for legitimate clients. +connections at the same time. While a single postscreen(8) process keeps +zombies away from Postfix SMTP server processes, more Postfix SMTP server +processes remain available for legitimate clients. + +postscreen(8) should not be used on SMTP ports that receive mail from end-user +clients (MUAs). In a typical deployment, postscreen(8) is used on the "port 25" +service, while MUA clients submit mail via the submission service. postscreen(8) is the first layer in a multi-layer defense. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index bb8ba6de5..79f4421c6 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -52,9 +52,8 @@ Server response: This feature supports macro expansion ($client_address, $localtime, etc.), as documented in the postconf(5) manpage. -This feature is also supported as postscreen_reject_footer -using the same setting as smtpd_reject_footer by -default. +This feature is also supported as postscreen_reject_footer using +the same setting as smtpd_reject_footer by default. Incompatibility with snapshot 20110102 ====================================== @@ -119,7 +118,7 @@ for almost 10 years now. For backwards compatibility, specify: /etc/postfix/main.cf - To: undisclosed-recipients:; + undisclosed_recipients_header = To: undisclosed-recipients:; Note: both the ":" and ";" are required. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 510ae4ba8..39f17a30e 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -1,23 +1,34 @@ Wish list: - Remove this file from the stable release. - - Re-run "make depend" with all plugins enabled. + Things to do before the stable release: - Make very clear in postscreen manpage and readme that this - program is not to be used against your own mail clients. - - Test postscreen on Solaris. + Remove this file from the stable release. - match_list support that does not recompile CIDR patterns - on every call. + To speed up postscreen_whitelist/blacklist_networks lookups + invent match_list support that does not recompile CIDR + patterns on every call. Otherwise, large CIDR files will + make postscreen unacceptably slow. + + Better, replace the postscreen_whitelist/blacklist_networks + mechanisms with one single postscreen_client_restrictions + mechanism that understands "permit_mynetworks" and (cidr) + access maps with entries of "pattern permit", "pattern + reject", or "pattern dunno". Tables that require locking + should not be used for performance reasons. The new mechanism + can reduce the number of table lookups when sites have both + whitelists and blacklists. We then use "permit_mynetworks" + to whitelist local networks by default. Unlike match_lists, + PCRE maps in access tables are compiled once, and even + Stan's very large tables resolve in a millisecond or so on + modern hardware. + + Things to do after the stable release: tlsproxy(8) should receive TLS preferences from postscreen(8) and smtpd(8), instead of reading them from main.cf. This means that many tlsproxy_ parameters become postscreen_ - parameters. This also means that tls_server_init() must not - "validate" preferences that are supplied later at - tls_server_start() time, which was dubious design anyway. + parameters, and that tls_server_init() parameters move to + to tls_server_start(). That is a significant API change. anvil rate limit for sasl_username. diff --git a/postfix/conf/post-install b/postfix/conf/post-install index 32624c68b..743c69db3 100644 --- a/postfix/conf/post-install +++ b/postfix/conf/post-install @@ -743,7 +743,7 @@ EOF grep '^#*smtp.*postscreen' $config_directory/master.cf >/dev/null || { echo Editing $config_directory/master.cf, adding missing entry for postscreen TCP service cat >>$config_directory/master.cf </dev/null || { echo Editing $config_directory/master.cf, adding missing entry for dnsblog unix-domain service cat >>$config_directory/master.cf </dev/null || { echo Editing $config_directory/master.cf, adding missing entry for tlsproxy unix-domain service cat >>$config_directory/master.cf < Introduction

The Postfix postscreen(8) server performs triage on multiple -inbound SMTP connections in parallel. While a single postscreen(8) -process keeps zombies away from Postfix SMTP server processes, -more Postfix SMTP server processes remain available for legitimate +inbound SMTP connections at the same time. While a single postscreen(8) +process keeps zombies away from Postfix SMTP server processes, more +Postfix SMTP server processes remain available for legitimate clients.

+

postscreen(8) should not be used on SMTP ports that receive +mail from end-user clients (MUAs). In a typical deployment, +postscreen(8) is used on the "port 25" service, while MUA clients +submit mail via the submission service.

+

postscreen(8) is the first layer in a multi-layer defense.

    diff --git a/postfix/html/postscreen.8.html b/postfix/html/postscreen.8.html index 41499a6cc..89411a593 100644 --- a/postfix/html/postscreen.8.html +++ b/postfix/html/postscreen.8.html @@ -14,10 +14,15 @@ POSTSCREEN(8) POSTSCREEN(8) DESCRIPTION The Postfix postscreen(8) server performs triage on multi- - ple inbound SMTP connections in parallel. While a single - postscreen(8) process keeps spambots away from Postfix - SMTP server processes, more Postfix SMTP server processes - remain available for legitimate clients. + ple inbound SMTP connections at the same time. While a + single postscreen(8) process keeps spambots away from + Postfix SMTP server processes, more Postfix SMTP server + processes remain available for legitimate clients. + + This program should not be used on SMTP ports that receive + mail from end-user clients (MUAs). In a typical deploy- + ment, postscreen(8) is used on the "port 25" service, + while MUA clients submit mail via the submission service. postscreen(8) maintains a temporary whitelist for clients that have passed a number of tests. When an SMTP client diff --git a/postfix/man/man8/postscreen.8 b/postfix/man/man8/postscreen.8 index e6822c0bc..fbb0b7f8e 100644 --- a/postfix/man/man8/postscreen.8 +++ b/postfix/man/man8/postscreen.8 @@ -13,11 +13,16 @@ Postfix zombie blocker .ad .fi The Postfix \fBpostscreen\fR(8) server performs triage on -multiple inbound SMTP connections in parallel. While a -single \fBpostscreen\fR(8) process keeps spambots away from -Postfix SMTP server processes, more Postfix SMTP server +multiple inbound SMTP connections at the same time. While +a single \fBpostscreen\fR(8) process keeps spambots away +from Postfix SMTP server processes, more Postfix SMTP server processes remain available for legitimate clients. +This program should not be used on SMTP ports that receive +mail from end-user clients (MUAs). In a typical deployment, +\fBpostscreen\fR(8) is used on the "port 25" service, while +MUA clients submit mail via the \fBsubmission\fR service. + \fBpostscreen\fR(8) maintains a temporary whitelist for clients that have passed a number of tests. When an SMTP client IP address is whitelisted, \fBpostscreen\fR(8) hands diff --git a/postfix/proto/POSTSCREEN_README.html b/postfix/proto/POSTSCREEN_README.html index 5adef7580..503aec71a 100644 --- a/postfix/proto/POSTSCREEN_README.html +++ b/postfix/proto/POSTSCREEN_README.html @@ -18,11 +18,16 @@

    Introduction

    The Postfix postscreen(8) server performs triage on multiple -inbound SMTP connections in parallel. While a single postscreen(8) -process keeps zombies away from Postfix SMTP server processes, -more Postfix SMTP server processes remain available for legitimate +inbound SMTP connections at the same time. While a single postscreen(8) +process keeps zombies away from Postfix SMTP server processes, more +Postfix SMTP server processes remain available for legitimate clients.

    +

    postscreen(8) should not be used on SMTP ports that receive +mail from end-user clients (MUAs). In a typical deployment, +postscreen(8) is used on the "port 25" service, while MUA clients +submit mail via the submission service.

    +

    postscreen(8) is the first layer in a multi-layer defense.

      diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 4ee8d8677..b430a0916 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -797,12 +797,65 @@ delivered_hdr.o: quote_822_local.h delivered_hdr.o: quote_flags.h delivered_hdr.o: rec_type.h delivered_hdr.o: record.h +dict_ldap.o: ../../include/argv.h +dict_ldap.o: ../../include/binhash.h +dict_ldap.o: ../../include/dict.h +dict_ldap.o: ../../include/match_list.h +dict_ldap.o: ../../include/match_ops.h +dict_ldap.o: ../../include/msg.h +dict_ldap.o: ../../include/mymalloc.h +dict_ldap.o: ../../include/name_code.h +dict_ldap.o: ../../include/stringops.h dict_ldap.o: ../../include/sys_defs.h +dict_ldap.o: ../../include/vbuf.h +dict_ldap.o: ../../include/vstream.h +dict_ldap.o: ../../include/vstring.h +dict_ldap.o: cfg_parser.h +dict_ldap.o: db_common.h dict_ldap.o: dict_ldap.c +dict_ldap.o: dict_ldap.h +dict_ldap.o: mail_conf.h +dict_ldap.o: string_list.h +dict_mysql.o: ../../include/argv.h +dict_mysql.o: ../../include/dict.h +dict_mysql.o: ../../include/events.h +dict_mysql.o: ../../include/find_inet.h +dict_mysql.o: ../../include/match_list.h +dict_mysql.o: ../../include/match_ops.h +dict_mysql.o: ../../include/msg.h +dict_mysql.o: ../../include/mymalloc.h +dict_mysql.o: ../../include/myrand.h +dict_mysql.o: ../../include/split_at.h +dict_mysql.o: ../../include/stringops.h dict_mysql.o: ../../include/sys_defs.h +dict_mysql.o: ../../include/vbuf.h +dict_mysql.o: ../../include/vstream.h +dict_mysql.o: ../../include/vstring.h +dict_mysql.o: cfg_parser.h +dict_mysql.o: db_common.h dict_mysql.o: dict_mysql.c +dict_mysql.o: dict_mysql.h +dict_mysql.o: string_list.h +dict_pgsql.o: ../../include/argv.h +dict_pgsql.o: ../../include/dict.h +dict_pgsql.o: ../../include/events.h +dict_pgsql.o: ../../include/find_inet.h +dict_pgsql.o: ../../include/match_list.h +dict_pgsql.o: ../../include/match_ops.h +dict_pgsql.o: ../../include/msg.h +dict_pgsql.o: ../../include/mymalloc.h +dict_pgsql.o: ../../include/myrand.h +dict_pgsql.o: ../../include/split_at.h +dict_pgsql.o: ../../include/stringops.h dict_pgsql.o: ../../include/sys_defs.h +dict_pgsql.o: ../../include/vbuf.h +dict_pgsql.o: ../../include/vstream.h +dict_pgsql.o: ../../include/vstring.h +dict_pgsql.o: cfg_parser.h +dict_pgsql.o: db_common.h dict_pgsql.o: dict_pgsql.c +dict_pgsql.o: dict_pgsql.h +dict_pgsql.o: string_list.h dict_proxy.o: ../../include/argv.h dict_proxy.o: ../../include/attr.h dict_proxy.o: ../../include/dict.h diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index e92f57391..989e78697 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 "20110108" +#define MAIL_RELEASE_DATE "20110109" #define MAIL_VERSION_NUMBER "2.8" #ifdef SNAPSHOT diff --git a/postfix/src/master/master_sig.c b/postfix/src/master/master_sig.c index 0f7d2e6e1..925144725 100644 --- a/postfix/src/master/master_sig.c +++ b/postfix/src/master/master_sig.c @@ -53,9 +53,8 @@ #ifdef USE_SIG_RETURN #include -#endif - -#ifndef USE_SIG_RETURN +#undef USE_SIG_PIPE +#else #define USE_SIG_PIPE #endif @@ -76,6 +75,8 @@ int master_sig_pipe[2]; int master_gotsigchld; int master_gotsighup; +#ifdef USE_SIG_RETURN + /* master_sighup - register arrival of hangup signal */ static void master_sighup(int sig) @@ -92,8 +93,6 @@ static void master_sighup(int sig) /* master_sigchld - register arrival of child death signal */ -#ifdef USE_SIG_RETURN - static void master_sigchld(int sig, int code, struct sigcontext * scp) { @@ -116,7 +115,25 @@ static void master_sigchld(int sig, int code, struct sigcontext * scp) #else -#ifdef USE_SIG_PIPE +/* master_sighup - register arrival of hangup signal */ + +static void master_sighup(int sig) +{ + int saved_errno = errno; + + /* + * WARNING WARNING WARNING. + * + * This code runs at unpredictable moments, as a signal handler. Don't put + * any code here other than for setting a global flag, or code that is + * intended to be run within a signal handler. Restore errno in case we + * are interrupting the epilog of a failed system call. + */ + master_gotsighup = sig; + if (write(SIG_PIPE_WRITE_FD, "", 1) != 1) + msg_warn("write to SIG_PIPE_WRITE_FD failed: %m"); + errno = saved_errno; +} /* master_sigchld - force wakeup from select() */ @@ -132,6 +149,7 @@ static void master_sigchld(int unused_sig) * intended to be run within a signal handler. Restore errno in case we * are interrupting the epilog of a failed system call. */ + master_gotsigchld = 1; if (write(SIG_PIPE_WRITE_FD, "", 1) != 1) msg_warn("write to SIG_PIPE_WRITE_FD failed: %m"); errno = saved_errno; @@ -145,24 +163,8 @@ static void master_sig_event(int unused_event, char *unused_context) while (read(SIG_PIPE_READ_FD, c, 1) > 0) /* void */ ; - master_gotsigchld = 1; } -#else - -static void master_sigchld(int sig) -{ - - /* - * WARNING WARNING WARNING. - * - * This code runs at unpredictable moments, as a signal handler. Don't put - * any code here other than for setting a global flag. - */ - master_gotsigchld = sig; -} - -#endif #endif /* master_sigdeath - die, women and children first */ diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c index cc7f3aa41..2ba285c0e 100644 --- a/postfix/src/postscreen/postscreen.c +++ b/postfix/src/postscreen/postscreen.c @@ -7,11 +7,16 @@ /* \fBpostscreen\fR [generic Postfix daemon options] /* DESCRIPTION /* The Postfix \fBpostscreen\fR(8) server performs triage on -/* multiple inbound SMTP connections in parallel. While a -/* single \fBpostscreen\fR(8) process keeps spambots away from -/* Postfix SMTP server processes, more Postfix SMTP server +/* multiple inbound SMTP connections at the same time. While +/* a single \fBpostscreen\fR(8) process keeps spambots away +/* from Postfix SMTP server processes, more Postfix SMTP server /* processes remain available for legitimate clients. /* +/* This program should not be used on SMTP ports that receive +/* mail from end-user clients (MUAs). In a typical deployment, +/* \fBpostscreen\fR(8) is used on the "port 25" service, while +/* MUA clients submit mail via the \fBsubmission\fR service. +/* /* \fBpostscreen\fR(8) maintains a temporary whitelist for /* clients that have passed a number of tests. When an SMTP /* client IP address is whitelisted, \fBpostscreen\fR(8) hands diff --git a/postfix/src/postscreen/postscreen_send.c b/postfix/src/postscreen/postscreen_send.c index 808afa69d..355542707 100644 --- a/postfix/src/postscreen/postscreen_send.c +++ b/postfix/src/postscreen/postscreen_send.c @@ -192,8 +192,8 @@ void psc_send_socket(PSC_STATE *state) * Postfix-specific. */ if ((server_fd = - LOCAL_CONNECT(psc_smtpd_service_name, NON_BLOCKING, - PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) { + PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING, + PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) { msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name); PSC_SEND_REPLY(state, "421 4.3.2 All server ports are busy\r\n"); psc_free_session_state(state); diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 8fefcf181..f72ddaec2 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -30,10 +30,10 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \ vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \ write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \ - allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \ - upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \ + allascii.c load_file.c killme_after.c vstream_tweak.c \ + unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \ unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \ - ip_match.c nbbio.c + ip_match.c nbbio.c stream_pass_connect.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -65,10 +65,10 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \ vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \ write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \ - allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \ - upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \ + allascii.o load_file.o killme_after.o vstream_tweak.o \ + unix_pass_listen.o unix_pass_trigger.o edit_file.o inet_windowsize.o \ unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \ - ip_match.o nbbio.o + ip_match.o nbbio.o stream_pass_connect.o HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \ dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \ @@ -1599,6 +1599,11 @@ stream_listen.o: listen.h stream_listen.o: msg.h stream_listen.o: stream_listen.c stream_listen.o: sys_defs.h +stream_pass_connect.o: connect.h +stream_pass_connect.o: iostuff.h +stream_pass_connect.o: msg.h +stream_pass_connect.o: stream_pass_connect.c +stream_pass_connect.o: sys_defs.h stream_recv_fd.o: iostuff.h stream_recv_fd.o: msg.h stream_recv_fd.o: stream_recv_fd.c @@ -1679,6 +1684,20 @@ unix_pass_fd_fix.o: sys_defs.h unix_pass_fd_fix.o: unix_pass_fd_fix.c unix_pass_fd_fix.o: vbuf.h unix_pass_fd_fix.o: vstring.h +unix_pass_listen.o: iostuff.h +unix_pass_listen.o: listen.h +unix_pass_listen.o: msg.h +unix_pass_listen.o: sane_accept.h +unix_pass_listen.o: sys_defs.h +unix_pass_listen.o: unix_pass_listen.c +unix_pass_trigger.o: connect.h +unix_pass_trigger.o: events.h +unix_pass_trigger.o: iostuff.h +unix_pass_trigger.o: msg.h +unix_pass_trigger.o: mymalloc.h +unix_pass_trigger.o: sys_defs.h +unix_pass_trigger.o: trigger.h +unix_pass_trigger.o: unix_pass_trigger.c unix_recv_fd.o: iostuff.h unix_recv_fd.o: msg.h unix_recv_fd.o: sys_defs.h @@ -1698,30 +1717,6 @@ unix_trigger.o: unix_trigger.c unsafe.o: safe.h unsafe.o: sys_defs.h unsafe.o: unsafe.c -upass_connect.o: connect.h -upass_connect.o: events.h -upass_connect.o: iostuff.h -upass_connect.o: msg.h -upass_connect.o: mymalloc.h -upass_connect.o: sane_connect.h -upass_connect.o: sane_socketpair.h -upass_connect.o: sys_defs.h -upass_connect.o: timed_connect.h -upass_connect.o: upass_connect.c -upass_listen.o: iostuff.h -upass_listen.o: listen.h -upass_listen.o: msg.h -upass_listen.o: sane_accept.h -upass_listen.o: sys_defs.h -upass_listen.o: upass_listen.c -upass_trigger.o: connect.h -upass_trigger.o: events.h -upass_trigger.o: iostuff.h -upass_trigger.o: msg.h -upass_trigger.o: mymalloc.h -upass_trigger.o: sys_defs.h -upass_trigger.o: trigger.h -upass_trigger.o: upass_trigger.c uppercase.o: stringops.h uppercase.o: sys_defs.h uppercase.o: uppercase.c diff --git a/postfix/src/util/connect.h b/postfix/src/util/connect.h index 40987dc72..9ec9c5883 100644 --- a/postfix/src/util/connect.h +++ b/postfix/src/util/connect.h @@ -22,7 +22,9 @@ extern int unix_connect(const char *, int, int); extern int inet_connect(const char *, int, int); extern int stream_connect(const char *, int, int); -extern int upass_connect(const char *, int, int); +extern int stream_pass_connect(const char *, int, int); + +#define unix_pass_connect unix_connect /* LICENSE /* .ad diff --git a/postfix/src/util/listen.h b/postfix/src/util/listen.h index 8a9041547..848543752 100644 --- a/postfix/src/util/listen.h +++ b/postfix/src/util/listen.h @@ -24,12 +24,15 @@ extern int inet_listen(const char *, int, int); extern int fifo_listen(const char *, int, int); extern int stream_listen(const char *, int, int); -#define upass_listen(path, mode, log) unix_listen((path), (mode), (log)) +#define unix_pass_listen unix_listen +#define stream_pass_listen stream_listen extern int inet_accept(int); extern int unix_accept(int); extern int stream_accept(int); -extern int upass_accept(int); +extern int unix_pass_accept(int); + +#define stream_pass_accept stream_accept /* LICENSE /* .ad diff --git a/postfix/src/util/make_dirs.c b/postfix/src/util/make_dirs.c index 79b244cbf..fef1c6fcc 100644 --- a/postfix/src/util/make_dirs.c +++ b/postfix/src/util/make_dirs.c @@ -126,13 +126,13 @@ int make_dirs(const char *path, int perms) * GID. Don't change the effective UID for doing this. */ if ((ret = stat(saved_path, &st)) < 0) { - msg_warn("%s: stat saved_path: %m", myname); + msg_warn("%s: stat %s: %m", myname, saved_path); break; } if (egid == -1) egid = getegid(); if (st.st_gid != egid && (ret = chown(saved_path, -1, egid)) < 0) { - msg_warn("%s: chgrp saved_path: %m", myname); + msg_warn("%s: chgrp %s: %m", myname, saved_path); break; } } diff --git a/postfix/src/util/stream_pass_connect.c b/postfix/src/util/stream_pass_connect.c new file mode 100644 index 000000000..9bacdf4ae --- /dev/null +++ b/postfix/src/util/stream_pass_connect.c @@ -0,0 +1,86 @@ +/*++ +/* NAME +/* stream_pass_connect 3 +/* SUMMARY +/* connect to stream-based descriptor listener +/* SYNOPSIS +/* #include +/* +/* int stream_pass_connect(path, block_mode, timeout) +/* const char *path; +/* int block_mode; +/* int timeout; +/* DESCRIPTION +/* stream_pass_connect() connects to a stream-based descriptor +/* listener for the specified pathname, and returns the resulting +/* file descriptor. The next operation is to stream_send_fd() +/* a file descriptor and then close() the connection once the +/* server has received the file descriptor. +/* +/* Arguments: +/* .IP path +/* Null-terminated string with listener endpoint name. +/* .IP block_mode +/* Either NON_BLOCKING for a non-blocking stream, or BLOCKING for +/* blocking mode. However, a stream connection succeeds or fails +/* immediately. +/* .IP timeout +/* This argument is ignored; it is present for compatibility with +/* other interfaces. Stream connections succeed or fail immediately. +/* DIAGNOSTICS +/* The result is -1 in case the connection could not be made. +/* Fatal errors: other system call failures. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include + +#ifdef STREAM_CONNECTIONS + +#include +#include +#include +#include + +#endif + +/* Utility library. */ + +#include +#include + +/* stream_pass_connect - connect to stream-based descriptor listener */ + +int stream_pass_connect(const char *path, int block_mode, int unused_timeout) +{ +#ifdef STREAM_CONNECTIONS + const char *myname = "stream_pass_connect"; + int fifo; + + /* + * The requested file system object must exist, otherwise we can't reach + * the server. + */ + if ((fifo = open(path, O_WRONLY | O_NONBLOCK, 0)) < 0) + return (-1); + + /* + * This is for {unix,inet}_connect() compatibility. + */ + non_blocking(fifo, block_mode); + + return (fifo); +#else + msg_fatal("stream connections are not implemented"); +#endif +} diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index f000c2d7b..93dc2a054 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -415,6 +415,10 @@ extern int opterr; #define LOCAL_TRIGGER stream_trigger #define LOCAL_SEND_FD stream_send_fd #define LOCAL_RECV_FD stream_recv_fd +#define PASS_CONNECT stream_pass_connect +#define PASS_LISTEN stream_pass_listen +#define PASS_ACCEPT stream_pass_accept +#define PASS_TRIGGER stream_pass_trigger #define HAS_VOLATILE_LOCKS #define BROKEN_READ_SELECT_ON_TCP_SOCKET #define CANT_WRITE_BEFORE_SENDING_FD @@ -437,6 +441,7 @@ extern int opterr; #define USE_SYSV_POLL #ifndef NO_DEVPOLL # define EVENTS_STYLE EVENTS_STYLE_DEVPOLL +# define USE_WATCHDOG_PIPE #endif /* @@ -1324,9 +1329,10 @@ extern int inet_pton(int, const char *, void *); #endif #ifndef PASS_LISTEN -#define PASS_LISTEN upass_listen -#define PASS_ACCEPT upass_accept -#define PASS_TRIGGER upass_trigger +#define PASS_CONNECT unix_pass_connect +#define PASS_LISTEN unix_pass_listen +#define PASS_ACCEPT unix_pass_accept +#define PASS_TRIGGER unix_pass_trigger #endif #if !defined (HAVE_SYS_NDIR_H) && !defined (HAVE_SYS_DIR_H) \ diff --git a/postfix/src/util/trigger.h b/postfix/src/util/trigger.h index bd3e45d4f..5e578d2b4 100644 --- a/postfix/src/util/trigger.h +++ b/postfix/src/util/trigger.h @@ -18,7 +18,9 @@ extern int unix_trigger(const char *, const char *, ssize_t, int); extern int inet_trigger(const char *, const char *, ssize_t, int); extern int fifo_trigger(const char *, const char *, ssize_t, int); extern int stream_trigger(const char *, const char *, ssize_t, int); -extern int upass_trigger(const char *, const char *, ssize_t, int); +extern int unix_pass_trigger(const char *, const char *, ssize_t, int); + +#define stream_pass_trigger stream_trigger /* LICENSE /* .ad diff --git a/postfix/src/util/unix_pass_listen.c b/postfix/src/util/unix_pass_listen.c new file mode 100644 index 000000000..822615977 --- /dev/null +++ b/postfix/src/util/unix_pass_listen.c @@ -0,0 +1,85 @@ +/*++ +/* NAME +/* unix_pass_listen 3 +/* SUMMARY +/* start UNIX-domain file descriptor listener +/* SYNOPSIS +/* #include +/* +/* int unix_pass_listen(path, backlog, block_mode) +/* const char *path; +/* int backlog; +/* int block_mode; +/* +/* int unix_pass_accept(fd) +/* int fd; +/* DESCRIPTION +/* This module implements a listener that receives one file descriptor +/* across each UNIX-domain connection that is made to it. +/* +/* unix_pass_listen() creates a listener endpoint with the specified +/* permissions, and returns a file descriptor to be used for accepting +/* descriptors. +/* +/* unix_pass_accept() accepts a descriptor. +/* +/* Arguments: +/* .IP path +/* Null-terminated string with connection destination. +/* .IP backlog +/* This argument exists for compatibility and is ignored. +/* .IP block_mode +/* Either NON_BLOCKING or BLOCKING. This does not affect the +/* mode of accepted connections. +/* .IP fd +/* File descriptor returned by unix_pass_listen(). +/* DIAGNOSTICS +/* Fatal errors: unix_pass_listen() aborts upon any system call failure. +/* unix_pass_accept() leaves all error handling up to the caller. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include + +/* unix_pass_accept - accept descriptor */ + +int unix_pass_accept(int listen_fd) +{ + const char *myname = "unix_pass_accept"; + int accept_fd; + int recv_fd = -1; + + accept_fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0); + if (accept_fd < 0) { + if (errno != EAGAIN) + msg_warn("%s: accept connection: %m", myname); + return (-1); + } else { + if (read_wait(accept_fd, 100) < 0) + msg_warn("%s: timeout receiving file descriptor: %m", myname); + else if ((recv_fd = unix_recv_fd(accept_fd)) < 0) + msg_warn("%s: cannot receive file descriptor: %m", myname); + if (close(accept_fd) < 0) + msg_warn("%s: close: %m", myname); + return (recv_fd); + } +} diff --git a/postfix/src/util/upass_trigger.c b/postfix/src/util/unix_pass_trigger.c similarity index 57% rename from postfix/src/util/upass_trigger.c rename to postfix/src/util/unix_pass_trigger.c index 2532f2bf3..5c0a9c8e3 100644 --- a/postfix/src/util/upass_trigger.c +++ b/postfix/src/util/unix_pass_trigger.c @@ -1,18 +1,18 @@ /*++ /* NAME -/* upass_trigger 3 +/* unix_pass_trigger 3 /* SUMMARY /* wakeup UNIX-domain file descriptor listener /* SYNOPSIS /* #include /* -/* int upass_trigger(service, buf, len, timeout) +/* int unix_pass_trigger(service, buf, len, timeout) /* const char *service; /* const char *buf; /* ssize_t len; /* int timeout; /* DESCRIPTION -/* upass_trigger() wakes up the named UNIX-domain server by sending +/* unix_pass_trigger() wakes up the named UNIX-domain server by sending /* a brief connection to it and writing the named buffer. /* /* The connection is closed by a background thread. Some kernels @@ -32,7 +32,7 @@ /* DIAGNOSTICS /* The result is zero in case of success, -1 in case of problems. /* SEE ALSO -/* upass_connect(3), UNIX-domain client +/* unix_pass_connect(3), UNIX-domain client /* LICENSE /* .ad /* .fi @@ -60,17 +60,18 @@ #include #include -struct upass_trigger { +struct unix_pass_trigger { int fd; char *service; + int *pair; }; -/* upass_trigger_event - disconnect from peer */ +/* unix_pass_trigger_event - disconnect from peer */ -static void upass_trigger_event(int event, char *context) +static void unix_pass_trigger_event(int event, char *context) { - struct upass_trigger *up = (struct upass_trigger *) context; - static const char *myname = "upass_trigger_event"; + struct unix_pass_trigger *up = (struct unix_pass_trigger *) context; + static const char *myname = "unix_pass_trigger_event"; /* * Disconnect. @@ -78,19 +79,25 @@ static void upass_trigger_event(int event, char *context) if (event == EVENT_TIME) msg_warn("%s: read timeout for service %s", myname, up->service); event_disable_readwrite(up->fd); - event_cancel_timer(upass_trigger_event, context); + event_cancel_timer(unix_pass_trigger_event, context); + /* Don't combine multiple close() calls into one boolean expression. */ if (close(up->fd) < 0) msg_warn("%s: close %s: %m", myname, up->service); + if (close(up->pair[0]) < 0) + msg_warn("%s: close pipe: %m", myname); + if (close(up->pair[1]) < 0) + msg_warn("%s: close pipe: %m", myname); myfree(up->service); myfree((char *) up); } -/* upass_trigger - wakeup UNIX-domain server */ +/* unix_pass_trigger - wakeup UNIX-domain server */ -int upass_trigger(const char *service, const char *buf, ssize_t len, int timeout) +int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int timeout) { - const char *myname = "upass_trigger"; - struct upass_trigger *up; + const char *myname = "unix_pass_trigger"; + int pair[2]; + struct unix_pass_trigger *up; int fd; if (msg_verbose > 1) @@ -99,25 +106,34 @@ int upass_trigger(const char *service, const char *buf, ssize_t len, int tim /* * Connect... */ - if ((fd = upass_connect(service, BLOCKING, timeout)) < 0) { + if ((fd = unix_pass_connect(service, BLOCKING, timeout)) < 0) { if (msg_verbose) msg_warn("%s: connect to %s: %m", myname, service); return (-1); } close_on_exec(fd, CLOSE_ON_EXEC); + /* + * Create a pipe, and send one pipe end to the server. + */ + if (pipe(pair) < 0) + msg_fatal("%s: pipe: %m", myname); + if (unix_send_fd(fd, pair[0]) < 0) + msg_fatal("%s: send file descriptor: %m", myname); + /* * Stash away context. */ - up = (struct upass_trigger *) mymalloc(sizeof(*up)); + up = (struct unix_pass_trigger *) mymalloc(sizeof(*up)); up->fd = fd; up->service = mystrdup(service); + up->pair = pair; /* * Write the request... */ - if (write_buf(fd, buf, len, timeout) < 0 - || write_buf(fd, "", 1, timeout) < 0) + if (write_buf(pair[1], buf, len, timeout) < 0 + || write_buf(pair[1], "", 1, timeout) < 0) if (msg_verbose) msg_warn("%s: write to %s: %m", myname, service); @@ -125,7 +141,7 @@ int upass_trigger(const char *service, const char *buf, ssize_t len, int tim * Wakeup when the peer disconnects, or when we lose patience. */ if (timeout > 0) - event_request_timer(upass_trigger_event, (char *) up, timeout + 100); - event_enable_read(fd, upass_trigger_event, (char *) up); + event_request_timer(unix_pass_trigger_event, (char *) up, timeout + 100); + event_enable_read(fd, unix_pass_trigger_event, (char *) up); return (0); } diff --git a/postfix/src/util/upass_connect.c b/postfix/src/util/upass_connect.c deleted file mode 100644 index 4efd837a9..000000000 --- a/postfix/src/util/upass_connect.c +++ /dev/null @@ -1,141 +0,0 @@ -/*++ -/* NAME -/* upass_connect 3 -/* SUMMARY -/* connect to UNIX-domain file descriptor listener -/* SYNOPSIS -/* #include -/* -/* int upass_connect(addr, block_mode, timeout) -/* const char *addr; -/* int block_mode; -/* int timeout; -/* DESCRIPTION -/* upass_connect() connects to a file descriptor listener in -/* the UNIX domain at the specified address, sends one half -/* of a socketpair to the listener, and returns the other half -/* to the caller. -/* -/* The file descriptor transporting connection is closed by -/* a background thread. Some kernels might otherwise discard -/* the descriptor before the server has received it. -/* -/* Arguments: -/* .IP addr -/* Null-terminated string with connection destination. -/* .IP block_mode -/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for -/* blocking mode. This setting has no effect on the connection -/* establishment process. -/* .IP timeout -/* Bounds the number of seconds that the operation may take. Specify -/* a value <= 0 to disable the time limit. -/* DIAGNOSTICS -/* The result is -1 in case the connection could not be made. -/* Fatal errors: other system call failures. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System interfaces. */ - -#include -#include -#include -#include -#include -#include - -/* Utility library. */ - -#include -#include -#include -#include -#include -#include -#include -#include - - /* - * Workaround for hostile kernels that don't support graceful shutdown. - */ -struct upass_connect { - int fd; - char *service; -}; - -/* upass_connect_event - disconnect from peer */ - -static void upass_connect_event(int event, char *context) -{ - struct upass_connect *up = (struct upass_connect *) context; - static const char *myname = "upass_connect_event"; - - /* - * Disconnect. - */ - if (event == EVENT_TIME) - msg_warn("%s: read timeout for service %s", myname, up->service); - event_disable_readwrite(up->fd); - event_cancel_timer(upass_connect_event, context); - if (close(up->fd) < 0) - msg_warn("%s: close %s: %m", myname, up->service); - myfree(up->service); - myfree((char *) up); -} - -/* upass_connect - connect to UNIX-domain file descriptor listener */ - -int upass_connect(const char *addr, int block_mode, int timeout) -{ - struct upass_connect *up; - int pair[2]; - int sock; - - /* - * Connect. - */ - if ((sock = unix_connect(addr, BLOCKING, timeout)) < 0) - return (-1); - - /* - * Send one socket pair half to the server. - */ -#define OUR_HALF 0 -#define THEIR_HALF 1 - - if (sane_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) { - close(sock); - return (-1); - } - if (unix_send_fd(sock, pair[THEIR_HALF]) < 0) { - close(pair[THEIR_HALF]); - close(pair[OUR_HALF]); - close(sock); - return (-1); - } - close(pair[THEIR_HALF]); - - /* - * Return the other socket pair half to the caller. Don't close the - * control socket just yet, but wait until the receiver closes it first. - * Otherwise, some hostile kernel might discard the socket that we just - * sent. - */ - up = (struct upass_connect *) mymalloc(sizeof(*up)); - up->fd = sock; - up->service = mystrdup(addr); - if (timeout > 0) - event_request_timer(upass_connect_event, (char *) up, timeout + 100); - event_enable_read(sock, upass_connect_event, (char *) up); - non_blocking(pair[OUR_HALF], block_mode); - return (pair[OUR_HALF]); -} diff --git a/postfix/src/util/upass_listen.c b/postfix/src/util/upass_listen.c deleted file mode 100644 index 3696409ba..000000000 --- a/postfix/src/util/upass_listen.c +++ /dev/null @@ -1,194 +0,0 @@ -/*++ -/* NAME -/* upass_listen 3 -/* SUMMARY -/* start UNIX-domain file descriptor listener -/* SYNOPSIS -/* #include -/* -/* int upass_listen(path, backlog, block_mode) -/* const char *path; -/* int backlog; -/* int block_mode; -/* -/* int upass_accept(fd) -/* int fd; -/* DESCRIPTION -/* This module implements a listener that receives one file descriptor -/* across each UNIX-domain connection that is made to it. -/* -/* upass_listen() creates a listener endpoint with the specified -/* permissions, and returns a file descriptor to be used for accepting -/* descriptors. -/* -/* upass_accept() accepts a descriptor. -/* -/* Arguments: -/* .IP path -/* Null-terminated string with connection destination. -/* .IP backlog -/* This argument exists for compatibility and is ignored. -/* .IP block_mode -/* Either NON_BLOCKING or BLOCKING. This does not affect the -/* mode of accepted connections. -/* .IP fd -/* File descriptor returned by upass_listen(). -/* DIAGNOSTICS -/* Fatal errors: upass_listen() aborts upon any system call failure. -/* upass_accept() leaves all error handling up to the caller. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System library. */ - -#include -#include -#include -#include - -/* Utility library. */ - -#include -#include -#include - -/* upass_accept - accept descriptor */ - -int upass_accept(int listen_fd) -{ - const char *myname = "upass_accept"; - int accept_fd; - int recv_fd = -1; - - accept_fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0); - if (accept_fd < 0) { - if (errno != EAGAIN) - msg_warn("%s: accept connection: %m", myname); - return (-1); - } else { - if (read_wait(accept_fd, 100) < 0) - msg_warn("%s: timeout receiving file descriptor: %m", myname); - else if ((recv_fd = unix_recv_fd(accept_fd)) < 0) - msg_warn("%s: cannot receive file descriptor: %m", myname); - if (close(accept_fd) < 0) - msg_warn("%s: close: %m", myname); - return (recv_fd); - } -} - -#if 0 - -/* System library. */ - -#include - -/* Utility library. */ - -#include -#include -#include -#include -#include - - /* - * It would be nice if a client could make one UNIX-domain connection to a - * Postfix master service, send multiple descriptors, and have each - * descriptor handled by the first available child process. - * - * Possible solutions: - * - * - Either the master process accepts the UNIX-domain connection and forwards - * each descriptor sent by the client to the first available child process. - * That's what the code below does. Unfortunately, this approach is - * inconsistent with the Postfix architecture which tries to eliminate the - * master from connection management as much as possible. - * - * - Or one child processes accepts the UNIX-domain connection and sends a - * shared socketpair half to the client. The other socketpair half is shared - * with the master and all the child's siblings. The client then sends its - * descriptors over the socketpair, and each descriptor is available to any - * child process that is waiting for work. - * - * If the second solution did not use a shared socketpair, then all the - * client's descriptors would be available only to the child process that - * accepted the UNIX-domain connection. That results in poor performance. - * - * Unfortunately, having to receive a descriptor before being able to send one - * or more descriptors is ugly from the client's point of view. - */ - -#define upass_accept(fd) unix_recv_fd(fd) - -/* upass_plumbing - operate the hidden descriptor passing machinery */ - -static void upass_plumbing(int unused_event, char *context) -{ - const char *myname = "upass_plumbing"; - UPASS_INFO *info = (UNIX_UPASS_INFO *) context; - int fd; - - /* - * Each time a client connects to the hidden UNIX-domain socket, call - * unix_send_fd() to send one half of the hidden socketpair across a - * short-lived UNIX-domain connection. Wait until the client closes the - * UNIX-domain connection before closing the connection. This wait needs - * to be time limited. - */ - fd = sane_accept(info->unixsock, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0); - if (fd < 0) { - if (errno != EAGAIN) - msg_fatal("%s: accept connection: %m", myname); - } else { - if (unix_send_fd(fd, info->halfpair) < 0) - msg_warn("%s: cannot send file descriptor: %m", myname); - if (read_wait(fd, 5) < 0) - msg_warn("%s: read timeout", myname); - if (close(fd) < 0) - msg_warn("%s: close: %m", myname); - } -} - -/* upass_listen - set up hidden descriptor passing machinery */ - -int upass_listen(const char *path, int backlog, int blocking, UPASS_INFO **ip) -{ - int pair[2]; - UPASS_INFO *info; - - /* - * Create a UNIX-domain socket with unix_listen() and create a - * socketpair. One socketpair half is returned to the caller. The other - * half is part of the hidden machinery, together with the UNIX-domain - * socket. - */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) - msg_fatal("socketpair: %m"); - info = (UPASS_INFO *) mymalloc(sizeof(*info)); - info->halfpair = pair[0]; - info->unixsock = unix_listen(path, backlog, blocking); - event_request_read(info->unixsock, upass_plumbing, (char *) info); - *ip = info; - return (pair[1]); -} - -/* upass_shutdown - tear down hidden descriptor passing machinery */ - -void upass_shutdown(UPASS_INFO *info) -{ - event_disable_readwrite(upass_info->unixsock) - if (close(info->unixsock) < 0) - msg_warn("%s: close unixsock: %m", myname); - if (close(info->halfpair) < 0) - msg_warn("%s: close halfpair: %m", myname); - myfree((char *) info); -} - -#endif diff --git a/postfix/src/util/watchdog.c b/postfix/src/util/watchdog.c index a1ab0cf1e..7481c8887 100644 --- a/postfix/src/util/watchdog.c +++ b/postfix/src/util/watchdog.c @@ -119,6 +119,30 @@ struct WATCHDOG { */ static WATCHDOG *watchdog_curr; + /* + * Workaround for systems where the alarm signal does not wakeup the event + * machinery, and therefore does not restart the watchdog timer in the + * single_server etc. skeletons. The symptom is that programs abort when the + * watchdog timeout is less than the max_idle time. + */ +#ifdef USE_WATCHDOG_PIPE +#include +#include + +static int watchdog_pipe[2]; + +/* watchdog_read - read event pipe */ + +static void watchdog_read(int unused_event, char *unused_context) +{ + char ch; + + while (read(watchdog_pipe[0], &ch, 1) > 0) + /* void */ ; +} + +#endif /* USE_WATCHDOG_PIPE */ + /* watchdog_event - handle timeout event */ static void watchdog_event(int unused_sig) @@ -137,6 +161,14 @@ static void watchdog_event(int unused_sig) if (msg_verbose > 1) msg_info("%s: %p %d", myname, (void *) wp, wp->trip_run); if (++(wp->trip_run) < WATCHDOG_STEPS) { +#ifdef USE_WATCHDOG_PIPE + int saved_errno = errno; + + /* Wake up the events(3) engine. */ + if (write(watchdog_pipe[1], "", 1) != 1) + msg_warn("%s: write watchdog_pipe: %m", myname); + errno = saved_errno; +#endif alarm(wp->timeout); } else { if (wp->action) @@ -177,6 +209,15 @@ WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context) msg_fatal("%s: sigaction(SIGALRM): %m", myname); if (msg_verbose > 1) msg_info("%s: %p %d", myname, (void *) wp, timeout); +#ifdef USE_WATCHDOG_PIPE + if (watchdog_curr == 0) { + if (pipe(watchdog_pipe) < 0) + msg_fatal("%s: pipe: %m", myname); + non_blocking(watchdog_pipe[0], NON_BLOCKING); + non_blocking(watchdog_pipe[1], NON_BLOCKING); + event_enable_read(watchdog_pipe[0], watchdog_read, (char *) 0); + } +#endif return (watchdog_curr = wp); } @@ -193,6 +234,13 @@ void watchdog_destroy(WATCHDOG *wp) if (wp->saved_time) alarm(wp->saved_time); myfree((char *) wp); +#ifdef USE_WATCHDOG_PIPE + if (watchdog_curr == 0) { + event_disable_readwrite(watchdog_pipe[0]); + (void) close(watchdog_pipe[0]); + (void) close(watchdog_pipe[1]); + } +#endif if (msg_verbose > 1) msg_info("%s: %p", myname, (void *) wp); }