88 lines
2.9 KiB
Diff
88 lines
2.9 KiB
Diff
|
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
|
||
|
|