From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001 From: Martin Sehnoutka Date: Thu, 17 Nov 2016 13:02:27 +0100 Subject: [PATCH] Prevent hanging in SIGCHLD handler. vsftpd can now handle pam_exec.so in pam.d config without hanging in SIGCHLD handler. [Abdelmalek: Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1198259 Fetched from: https://src.fedoraproject.org/cgit/rpms/vsftpd.git/plain/0026-Prevent-hanging-in-SIGCHLD-handler.patch] Signed-off-by: Abdelmalek Benelouezzane --- sysutil.c | 4 ++-- sysutil.h | 2 +- twoprocess.c | 13 +++++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sysutil.c b/sysutil.c index 6d7cb3f..099748f 100644 --- a/sysutil.c +++ b/sysutil.c @@ -592,13 +592,13 @@ vsf_sysutil_exit(int exit_code) } struct vsf_sysutil_wait_retval -vsf_sysutil_wait(void) +vsf_sysutil_wait(int hang) { struct vsf_sysutil_wait_retval retval; vsf_sysutil_memclr(&retval, sizeof(retval)); while (1) { - int sys_ret = wait(&retval.exit_status); + int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG); if (sys_ret < 0 && errno == EINTR) { vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); diff --git a/sysutil.h b/sysutil.h index c145bdf..13153cd 100644 --- a/sysutil.h +++ b/sysutil.h @@ -175,7 +175,7 @@ struct vsf_sysutil_wait_retval int PRIVATE_HANDS_OFF_syscall_retval; int PRIVATE_HANDS_OFF_exit_status; }; -struct vsf_sysutil_wait_retval vsf_sysutil_wait(void); +struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang); int vsf_sysutil_wait_reap_one(void); int vsf_sysutil_wait_get_retval( const struct vsf_sysutil_wait_retval* p_waitret); diff --git a/twoprocess.c b/twoprocess.c index 33d84dc..b1891e7 100644 --- a/twoprocess.c +++ b/twoprocess.c @@ -47,8 +47,17 @@ static void handle_sigchld(void* duff) { - struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(); + struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0); (void) duff; + if (!vsf_sysutil_wait_get_exitcode(&wait_retval) && + !vsf_sysutil_wait_get_retval(&wait_retval)) + /* There was nobody to wait for, possibly caused by underlying library + * which created a new process through fork()/vfork() and already picked + * it up, e.g. by pam_exec.so or integrity check routines for libraries + * when FIPS mode is on (nss freebl), which can lead to calling prelink + * if the prelink package is installed. + */ + return; /* Child died, so we'll do the same! Report it as an error unless the child * exited normally with zero exit code */ @@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str, priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); if (!p_sess->control_use_ssl) { - (void) vsf_sysutil_wait(); + (void) vsf_sysutil_wait(1); } else { -- 2.14.4