On 08/04/2016 05:01 PM, Petr Cech wrote:
On 08/04/2016 04:35 PM, Petr Cech wrote:
Hi list,

there is the first version of patch for [1]. I need
to investigate if we have the same issue in other
*_childs.

I tested it with sleep() added into ldap_child code.

[1] https://fedorahosted.org/sssd/ticket/3106


I know, it is not perfect. For example 2 seconds between SIGTERM and
SIGKILL should be constant. I will send the second version with other
childs, but not today.

Regards

Hello all,

there is fixed patch set. There is only one minor change -- constant for time between signals.

Is there better name for global_ccname_file_dummy? I did not want to break the naming... but it looks really long.

I looked at code of others children. I saw the same schema at
src/providers/ad/ad_gpo_child.c:361 (temporary file renamed to solid one).

In my opinion we could fix ad_qpo_child in next patch (not the highest priority for now) and make SIGTERM/SIGKILL more general. Maybe all child processes could have it.

Regards

--
Petr^4 Čech
>From 1fb9c73fdb512bd0292cc9a597ca1f98aa384e54 Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
Date: Thu, 4 Aug 2016 16:25:28 +0200
Subject: [PATCH 1/2] LDAP: Adding support for SIGTERM signal

We add support for handling SIGTERM signal. If ldap_child receives
SIGTERM signal it removes temporary file.

Resolves:
https://fedorahosted.org/sssd/ticket/3106
---
 src/providers/ldap/ldap_child.c | 45 +++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index 52c271f36cb57b774e6091e7322e4b1394c78969..69595db159b0f784b067135f9384e6ca15359540 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -33,6 +33,30 @@
 #include "providers/backend.h"
 #include "providers/krb5/krb5_common.h"
 
+char *global_ccname_file_dummy = NULL;
+
+static void sig_term_handler(int sig)
+{
+    int ret;
+
+    DEBUG(SSSDBG_FATAL_FAILURE, "Received signal [%s] [%i], shutting down\n",
+                                strsignal(sig), sig);
+
+    if (global_ccname_file_dummy != NULL) {
+        ret = unlink(global_ccname_file_dummy);
+        if (ret != 0) {
+            DEBUG(SSSDBG_FATAL_FAILURE, "Unlink file [%s] failed [%i][%s]\n",
+                                        global_ccname_file_dummy,
+                                        errno, strerror(errno));
+        } else {
+            DEBUG(SSSDBG_FATAL_FAILURE, "Unlink file [%s]\n",
+                                        global_ccname_file_dummy);
+        }
+    }
+
+    _exit(0);
+}
+
 static krb5_context krb5_error_ctx;
 #define LDAP_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error)
 
@@ -271,7 +295,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
     int kdc_time_offset_usec;
     int ret;
     TALLOC_CTX *tmp_ctx;
-    char *ccname_file_dummy = NULL;
     char *ccname_file;
 
     tmp_ctx = talloc_new(memctx);
@@ -396,9 +419,9 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
         goto done;
     }
 
-    ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
-                                        DB_PATH, realm_name);
-    if (ccname_file_dummy == NULL) {
+    global_ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
+                                               DB_PATH, realm_name);
+    if (global_ccname_file_dummy == NULL) {
         krberr = ENOMEM;
         DEBUG(SSSDBG_CRIT_FAILURE,
               "talloc_asprintf failed: %s:[%d].\n",
@@ -406,7 +429,7 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
         goto done;
     }
 
-    ret = sss_unique_filename(tmp_ctx, ccname_file_dummy);
+    ret = sss_unique_filename(tmp_ctx, global_ccname_file_dummy);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "sss_unique_filename failed: %s:[%d].\n",
@@ -432,7 +455,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
     }
     DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n");
 
-    ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
+    ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s",
+                                   global_ccname_file_dummy);
     ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
     if (ccname_dummy == NULL || ccname == NULL) {
         krberr = ENOMEM;
@@ -482,14 +506,16 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
 #endif
 
     DEBUG(SSSDBG_TRACE_INTERNAL,
-          "Renaming [%s] to [%s]\n", ccname_file_dummy, ccname_file);
-    ret = rename(ccname_file_dummy, ccname_file);
+          "Renaming [%s] to [%s]\n", global_ccname_file_dummy, ccname_file);
+    ret = rename(global_ccname_file_dummy, ccname_file);
     if (ret == -1) {
         ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE,
               "rename failed [%d][%s].\n", ret, strerror(ret));
         goto done;
     }
+    talloc_free(global_ccname_file_dummy);
+    global_ccname_file_dummy = NULL;
 
     krberr = 0;
     *ccname_out = talloc_steal(memctx, ccname);
@@ -631,6 +657,9 @@ int main(int argc, const char *argv[])
         }
     }
 
+    BlockSignals(false, SIGTERM);
+    CatchSignal(SIGTERM, sig_term_handler);
+
     DEBUG(SSSDBG_TRACE_FUNC, "ldap_child started.\n");
 
     main_ctx = talloc_new(NULL);
-- 
2.7.4

>From 3f97fac15c7e72fad79a54c47c91860b02bda46c Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
Date: Thu, 4 Aug 2016 16:27:40 +0200
Subject: [PATCH 2/2] LDAP: Adding SIGTERM signal before SIGKILL

We add better termination of ldap_child. If ldap_child reaches
the timeout for termination parent sents SIGTERM signal. Child
has 2 seconds for removing temporary file and exit.
If it is not sufficient there is SIGKILL send to the child.

Resolves:
https://fedorahosted.org/sssd/ticket/3106
---
 src/providers/ldap/sdap_child_helpers.c | 39 +++++++++++++++++++++++++++++----
 src/util/child_common.h                 |  2 ++
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
index 92642e8e47e530e5aef5f78bf1c7a2427979275e..9f9c9b57a7ca5e1217d56ab560cc941432084df8 100644
--- a/src/providers/ldap/sdap_child_helpers.c
+++ b/src/providers/ldap/sdap_child_helpers.c
@@ -416,9 +416,7 @@ int sdap_get_tgt_recv(struct tevent_req *req,
     return EOK;
 }
 
-
-
-static void get_tgt_timeout_handler(struct tevent_context *ev,
+static void get_tgt_sigkill_handler(struct tevent_context *ev,
                                     struct tevent_timer *te,
                                     struct timeval tv, void *pvt)
 {
@@ -428,7 +426,8 @@ static void get_tgt_timeout_handler(struct tevent_context *ev,
     int ret;
 
     DEBUG(SSSDBG_TRACE_ALL,
-          "timeout for tgt child [%d] reached.\n", state->child->pid);
+          "timeout for sending SIGKILL to tgt child [%d] reached.\n",
+          state->child->pid);
 
     ret = kill(state->child->pid, SIGKILL);
     if (ret == -1) {
@@ -439,6 +438,38 @@ static void get_tgt_timeout_handler(struct tevent_context *ev,
     tevent_req_error(req, ETIMEDOUT);
 }
 
+static void get_tgt_timeout_handler(struct tevent_context *ev,
+                                      struct tevent_timer *te,
+                                      struct timeval tv, void *pvt)
+{
+    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+    struct sdap_get_tgt_state *state = tevent_req_data(req,
+                                            struct sdap_get_tgt_state);
+    int ret;
+
+    DEBUG(SSSDBG_TRACE_ALL,
+          "timeout for sending SIGTERM to tgt child [%d] reached.\n",
+          state->child->pid);
+
+    ret = kill(state->child->pid, SIGTERM);
+    if (ret == -1) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Sending SIGTERM failed [%d][%s].\n", errno, strerror(errno));
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC,
+          "Setting %d seconds timeout for sending SIGKILL to tgt child\n",
+          SIGTERM_TO_SIGKILL_TIME);
+
+    tv = tevent_timeval_current_ofs(SIGTERM_TO_SIGKILL_TIME, 0);
+
+    te = tevent_add_timer(ev, req, tv, get_tgt_sigkill_handler, req);
+    if (te == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
+        tevent_req_error(req, ECANCELED);
+    }
+}
+
 static errno_t set_tgt_child_timeout(struct tevent_req *req,
                                      struct tevent_context *ev,
                                      int timeout)
diff --git a/src/util/child_common.h b/src/util/child_common.h
index 2a62869034a466b465a481286950678af73667ab..eb7623987238d5d9e9032b9bbbbef49188f5b1d2 100644
--- a/src/util/child_common.h
+++ b/src/util/child_common.h
@@ -35,6 +35,8 @@
 #define IN_BUF_SIZE         512
 #define CHILD_MSG_CHUNK     256
 
+#define SIGTERM_TO_SIGKILL_TIME 2
+
 struct response {
     uint8_t *buf;
     size_t size;
-- 
2.7.4

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to