| From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001 |
| From: Martin Sehnoutka <msehnout@redhat.com> |
| 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 <abdelmalek.benelouezzane@savoirfairelinux.com> |
| --- |
| 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 |
| @@ -608,13 +608,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 |
| @@ -177,7 +177,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 |
| |