|
|
b69e47 |
From 4f90e73538f1faf101733fcd95392bb77ba9467c Mon Sep 17 00:00:00 2001
|
|
|
b69e47 |
From: William Brown <firstyear@redhat.com>
|
|
|
b69e47 |
Date: Wed, 22 Mar 2017 14:10:11 +1000
|
|
|
b69e47 |
Subject: [PATCH] Ticket 49174 - nunc-stans can not use negative timeout
|
|
|
b69e47 |
|
|
|
b69e47 |
Bug Description: FreeIPA regularly sets up service accounts with
|
|
|
b69e47 |
an nsIdleTimeout of -1. As a result of an issue with NS and libevent
|
|
|
b69e47 |
this would cause an instant timeout and disconnect of the service
|
|
|
b69e47 |
account.
|
|
|
b69e47 |
|
|
|
b69e47 |
Fix Description: Correctly check that jobs are registered to NS.
|
|
|
b69e47 |
Add validation to NS for negative timeouts. During the job registration,
|
|
|
b69e47 |
we force the timeout to be a valid value.
|
|
|
b69e47 |
|
|
|
b69e47 |
https://pagure.io/389-ds-base/issue/49174
|
|
|
b69e47 |
|
|
|
b69e47 |
Author: wibrown
|
|
|
b69e47 |
|
|
|
b69e47 |
Review by: mreynolds(Thanks!!!)
|
|
|
b69e47 |
|
|
|
b69e47 |
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
|
|
|
b69e47 |
---
|
|
|
b69e47 |
ldap/servers/slapd/daemon.c | 39 ++++++++++++++++++++++++++++-------
|
|
|
b69e47 |
src/nunc-stans/ns/ns_event_fw_event.c | 8 -------
|
|
|
b69e47 |
src/nunc-stans/ns/ns_thrpool.c | 16 ++++++++++++++
|
|
|
b69e47 |
src/nunc-stans/test/test_nuncstans.c | 20 ++++++++++++++++++
|
|
|
b69e47 |
4 files changed, 68 insertions(+), 15 deletions(-)
|
|
|
b69e47 |
|
|
|
b69e47 |
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
|
|
|
b69e47 |
index e17a858..a4ea4c0 100644
|
|
|
b69e47 |
--- a/ldap/servers/slapd/daemon.c
|
|
|
b69e47 |
+++ b/ldap/servers/slapd/daemon.c
|
|
|
b69e47 |
@@ -1891,15 +1891,32 @@ ns_connection_post_io_or_closing(Connection *conn)
|
|
|
b69e47 |
tv.tv_usec = slapd_wakeup_timer * 1000;
|
|
|
b69e47 |
conn->c_ns_close_jobs++; /* now 1 active closure job */
|
|
|
b69e47 |
connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework now has a reference */
|
|
|
b69e47 |
- ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
|
|
|
b69e47 |
+ PRStatus job_result = ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
|
|
|
b69e47 |
ns_handle_closure, conn, NULL);
|
|
|
b69e47 |
- slapi_log_err(SLAPI_LOG_CONNS, "ns_connection_post_io_or_closing", "post closure job "
|
|
|
b69e47 |
- "for conn %" NSPRIu64 " for fd=%d\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+#ifdef DEBUG
|
|
|
b69e47 |
+ PR_ASSERT(job_result == PR_SUCCESS);
|
|
|
b69e47 |
+#endif
|
|
|
b69e47 |
+ if (job_result != PR_SUCCESS) {
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_WARNING, "ns_connection_post_io_or_closing", "post closure job "
|
|
|
b69e47 |
+ "for conn %" NSPRIu64 " for fd=%d failed to be added to event queue\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+ } else {
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_CONNS, "ns_connection_post_io_or_closing", "post closure job "
|
|
|
b69e47 |
+ "for conn %" NSPRIu64 " for fd=%d\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
|
|
|
b69e47 |
}
|
|
|
b69e47 |
} else {
|
|
|
b69e47 |
/* process event normally - wait for I/O until idletimeout */
|
|
|
b69e47 |
- tv.tv_sec = conn->c_idletimeout;
|
|
|
b69e47 |
+ /* With nunc-stans there is a quirk. When we have idleTimeout of -1
|
|
|
b69e47 |
+ * which is set on some IPA bind dns for infinite, this causes libevent
|
|
|
b69e47 |
+ * to *instantly* timeout. So if we detect < 0, we set 0 to this timeout, to
|
|
|
b69e47 |
+ * catch all possible times that an admin could set.
|
|
|
b69e47 |
+ */
|
|
|
b69e47 |
+ if (conn->c_idletimeout < 0) {
|
|
|
b69e47 |
+ tv.tv_sec = 0;
|
|
|
b69e47 |
+ } else {
|
|
|
b69e47 |
+ tv.tv_sec = conn->c_idletimeout;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
tv.tv_usec = 0;
|
|
|
b69e47 |
#ifdef DEBUG
|
|
|
b69e47 |
PR_ASSERT(0 == connection_acquire_nolock(conn));
|
|
|
b69e47 |
@@ -1913,11 +1930,19 @@ ns_connection_post_io_or_closing(Connection *conn)
|
|
|
b69e47 |
return;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
#endif
|
|
|
b69e47 |
- ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
|
|
|
b69e47 |
+ PRStatus job_result = ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
|
|
|
b69e47 |
NS_JOB_READ|NS_JOB_PRESERVE_FD,
|
|
|
b69e47 |
ns_handle_pr_read_ready, conn, NULL);
|
|
|
b69e47 |
- slapi_log_err(SLAPI_LOG_CONNS, "ns_connection_post_io_or_closing", "post I/O job for "
|
|
|
b69e47 |
- "conn %" NSPRIu64 " for fd=%d\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+#ifdef DEBUG
|
|
|
b69e47 |
+ PR_ASSERT(job_result == PR_SUCCESS);
|
|
|
b69e47 |
+#endif
|
|
|
b69e47 |
+ if (job_result != PR_SUCCESS) {
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_WARNING, "ns_connection_post_io_or_closing", "post I/O job for "
|
|
|
b69e47 |
+ "conn %" NSPRIu64 " for fd=%d failed to be added to event queue\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+ } else {
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_CONNS, "ns_connection_post_io_or_closing", "post I/O job for "
|
|
|
b69e47 |
+ "conn %" NSPRIu64 " for fd=%d\n", conn->c_connid, conn->c_sd);
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
}
|
|
|
b69e47 |
#endif
|
|
|
b69e47 |
}
|
|
|
b69e47 |
diff --git a/src/nunc-stans/ns/ns_event_fw_event.c b/src/nunc-stans/ns/ns_event_fw_event.c
|
|
|
b69e47 |
index 3acbaf7..76936de 100644
|
|
|
b69e47 |
--- a/src/nunc-stans/ns/ns_event_fw_event.c
|
|
|
b69e47 |
+++ b/src/nunc-stans/ns/ns_event_fw_event.c
|
|
|
b69e47 |
@@ -48,7 +48,6 @@ typedef struct event ns_event_fw_sig_t;
|
|
|
b69e47 |
#include "ns_event_fw.h"
|
|
|
b69e47 |
#include <syslog.h>
|
|
|
b69e47 |
|
|
|
b69e47 |
-
|
|
|
b69e47 |
static void
|
|
|
b69e47 |
event_logger_cb(int severity, const char *msg)
|
|
|
b69e47 |
{
|
|
|
b69e47 |
@@ -248,13 +247,6 @@ ns_event_fw_mod_io(
|
|
|
b69e47 |
}
|
|
|
b69e47 |
if (events) {
|
|
|
b69e47 |
job->ns_event_fw_fd->ev_events = events;
|
|
|
b69e47 |
-
|
|
|
b69e47 |
-#ifdef DEBUG_FSM
|
|
|
b69e47 |
- /* REALLY make sure that we aren't being re-added */
|
|
|
b69e47 |
- if (event_pending(job->ns_event_fw_fd, events, tv)) {
|
|
|
b69e47 |
- abort();
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
-#endif
|
|
|
b69e47 |
event_add(job->ns_event_fw_fd, tv);
|
|
|
b69e47 |
} else {
|
|
|
b69e47 |
/* setting the job_type to remove IO events will remove it from the event system */
|
|
|
b69e47 |
diff --git a/src/nunc-stans/ns/ns_thrpool.c b/src/nunc-stans/ns/ns_thrpool.c
|
|
|
b69e47 |
index a867b39..9d87384 100644
|
|
|
b69e47 |
--- a/src/nunc-stans/ns/ns_thrpool.c
|
|
|
b69e47 |
+++ b/src/nunc-stans/ns/ns_thrpool.c
|
|
|
b69e47 |
@@ -180,6 +180,14 @@ ns_thrpool_is_event_shutdown(struct ns_thrpool_t *tp)
|
|
|
b69e47 |
return result;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
+static int32_t
|
|
|
b69e47 |
+validate_event_timeout(struct timeval *tv) {
|
|
|
b69e47 |
+ if (tv->tv_sec < 0 || tv->tv_usec < 0) {
|
|
|
b69e47 |
+ /* If we get here, you have done something WRONG */
|
|
|
b69e47 |
+ return 1;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+ return 0;
|
|
|
b69e47 |
+}
|
|
|
b69e47 |
|
|
|
b69e47 |
static void
|
|
|
b69e47 |
job_queue_cleanup(void *arg) {
|
|
|
b69e47 |
@@ -864,6 +872,10 @@ ns_add_timeout_job(ns_thrpool_t *tp, struct timeval *tv, ns_job_type_t job_type,
|
|
|
b69e47 |
return PR_FAILURE;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
+ if (validate_event_timeout(tv)) {
|
|
|
b69e47 |
+ return PR_FAILURE;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+
|
|
|
b69e47 |
/* get an event context for a timer job */
|
|
|
b69e47 |
_job = alloc_timeout_context(tp, tv, job_type, func, data);
|
|
|
b69e47 |
if (!_job) {
|
|
|
b69e47 |
@@ -900,6 +912,10 @@ ns_add_io_timeout_job(ns_thrpool_t *tp, PRFileDesc *fd, struct timeval *tv,
|
|
|
b69e47 |
return PR_FAILURE;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
+ if (validate_event_timeout(tv)) {
|
|
|
b69e47 |
+ return PR_FAILURE;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+
|
|
|
b69e47 |
/* Don't allow an accept job to be run outside of the event thread.
|
|
|
b69e47 |
* We do this so a listener job won't shut down while still processing
|
|
|
b69e47 |
* current connections in other threads.
|
|
|
b69e47 |
diff --git a/src/nunc-stans/test/test_nuncstans.c b/src/nunc-stans/test/test_nuncstans.c
|
|
|
b69e47 |
index 8eef9e6..2795302 100644
|
|
|
b69e47 |
--- a/src/nunc-stans/test/test_nuncstans.c
|
|
|
b69e47 |
+++ b/src/nunc-stans/test/test_nuncstans.c
|
|
|
b69e47 |
@@ -385,6 +385,23 @@ ns_job_signal_cb_test(void **state)
|
|
|
b69e47 |
assert_int_equal(ns_job_done(job), 0);
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
+/*
|
|
|
b69e47 |
+ * Test that given a timeout of -1, we fail to create a job.
|
|
|
b69e47 |
+ */
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+static void
|
|
|
b69e47 |
+ns_job_neg_timeout_test(void **state)
|
|
|
b69e47 |
+{
|
|
|
b69e47 |
+ struct ns_thrpool_t *tp = *state;
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ struct timeval tv = { -1, 0 };
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ PR_ASSERT(PR_FAILURE == ns_add_io_timeout_job(tp, 0, &tv, NS_JOB_THREAD, ns_init_do_nothing_cb, NULL, NULL));
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ PR_ASSERT(PR_FAILURE == ns_add_timeout_job(tp, &tv, NS_JOB_THREAD, ns_init_do_nothing_cb, NULL, NULL));
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+}
|
|
|
b69e47 |
+
|
|
|
b69e47 |
int
|
|
|
b69e47 |
main(void)
|
|
|
b69e47 |
{
|
|
|
b69e47 |
@@ -410,6 +427,9 @@ main(void)
|
|
|
b69e47 |
cmocka_unit_test_setup_teardown(ns_job_signal_cb_test,
|
|
|
b69e47 |
ns_test_setup,
|
|
|
b69e47 |
ns_test_teardown),
|
|
|
b69e47 |
+ cmocka_unit_test_setup_teardown(ns_job_neg_timeout_test,
|
|
|
b69e47 |
+ ns_test_setup,
|
|
|
b69e47 |
+ ns_test_teardown),
|
|
|
b69e47 |
};
|
|
|
b69e47 |
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
|
b69e47 |
}
|
|
|
b69e47 |
--
|
|
|
b69e47 |
2.9.3
|
|
|
b69e47 |
|