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 Regards -- Petr^4 Čech
>From 50d83072b48b198284871a5c950982dfbeeab974 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 bc4ae7cfceb1acada9b7f6b31d7a9a7dfff0cc9f 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 | 40 +++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c index 92642e8e47e530e5aef5f78bf1c7a2427979275e..bfe3fd49174569ee68faa97080ba71910c82faff 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,39 @@ 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 kill_time = 2; + 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", + kill_time); + + tv = tevent_timeval_current_ofs(kill_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) -- 2.7.4
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org