1From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001 2From: Martin Sehnoutka <msehnout@redhat.com> 3Date: Thu, 17 Nov 2016 13:02:27 +0100 4Subject: [PATCH] Prevent hanging in SIGCHLD handler. 5 6vsftpd can now handle pam_exec.so in pam.d config without hanging 7in SIGCHLD handler. 8 9[Abdelmalek: 10Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1198259 11Fetched from: 12https://src.fedoraproject.org/cgit/rpms/vsftpd.git/plain/0026-Prevent-hanging-in-SIGCHLD-handler.patch] 13Signed-off-by: Abdelmalek Benelouezzane <abdelmalek.benelouezzane@savoirfairelinux.com> 14--- 15 sysutil.c | 4 ++-- 16 sysutil.h | 2 +- 17 twoprocess.c | 13 +++++++++++-- 18 3 files changed, 14 insertions(+), 5 deletions(-) 19 20diff --git a/sysutil.c b/sysutil.c 21index 6d7cb3f..099748f 100644 22--- a/sysutil.c 23+++ b/sysutil.c 24@@ -592,13 +592,13 @@ vsf_sysutil_exit(int exit_code) 25 } 26 27 struct vsf_sysutil_wait_retval 28-vsf_sysutil_wait(void) 29+vsf_sysutil_wait(int hang) 30 { 31 struct vsf_sysutil_wait_retval retval; 32 vsf_sysutil_memclr(&retval, sizeof(retval)); 33 while (1) 34 { 35- int sys_ret = wait(&retval.exit_status); 36+ int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG); 37 if (sys_ret < 0 && errno == EINTR) 38 { 39 vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); 40diff --git a/sysutil.h b/sysutil.h 41index c145bdf..13153cd 100644 42--- a/sysutil.h 43+++ b/sysutil.h 44@@ -175,7 +175,7 @@ struct vsf_sysutil_wait_retval 45 int PRIVATE_HANDS_OFF_syscall_retval; 46 int PRIVATE_HANDS_OFF_exit_status; 47 }; 48-struct vsf_sysutil_wait_retval vsf_sysutil_wait(void); 49+struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang); 50 int vsf_sysutil_wait_reap_one(void); 51 int vsf_sysutil_wait_get_retval( 52 const struct vsf_sysutil_wait_retval* p_waitret); 53diff --git a/twoprocess.c b/twoprocess.c 54index 33d84dc..b1891e7 100644 55--- a/twoprocess.c 56+++ b/twoprocess.c 57@@ -47,8 +47,17 @@ static void 58 handle_sigchld(void* duff) 59 { 60 61- struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(); 62+ struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0); 63 (void) duff; 64+ if (!vsf_sysutil_wait_get_exitcode(&wait_retval) && 65+ !vsf_sysutil_wait_get_retval(&wait_retval)) 66+ /* There was nobody to wait for, possibly caused by underlying library 67+ * which created a new process through fork()/vfork() and already picked 68+ * it up, e.g. by pam_exec.so or integrity check routines for libraries 69+ * when FIPS mode is on (nss freebl), which can lead to calling prelink 70+ * if the prelink package is installed. 71+ */ 72+ return; 73 /* Child died, so we'll do the same! Report it as an error unless the child 74 * exited normally with zero exit code 75 */ 76@@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str, 77 priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); 78 if (!p_sess->control_use_ssl) 79 { 80- (void) vsf_sysutil_wait(); 81+ (void) vsf_sysutil_wait(1); 82 } 83 else 84 { 85-- 862.14.4 87 88