Blame SOURCES/0026-Prevent-hanging-in-SIGCHLD-handler.patch

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