>From 8a8873a1ff85ebfeaebe65eb998b3ffe8910f0d3 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Wed, 20 May 2015 13:46:06 +0200 Subject: [PATCH] proxy: Do not crash if proxy_child returns error proxy_child_init_send creates request; forks a process and register handler for signal SIGCHLD. Talloc parent of tevent_signal is previously created request. If proxy_child fails (return code is not 0) then SIGCHLD is received handler pc_init_sig_handler is called. However pc_init_sig_handler can call tevent_req_error for request which calls request callback and released request (including siginfo). It caused crash in tevent when signall callback pc_init_sig_handler finished. Resolves: https://fedorahosted.org/sssd/ticket/2654 --- src/providers/proxy/proxy.h | 1 + src/providers/proxy/proxy_auth.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h index 7f4dfc984c5a6488f2888f270c771574a4bc1898..c292814a3a250c6879e26756ce76806c30bdb606 100644 --- a/src/providers/proxy/proxy.h +++ b/src/providers/proxy/proxy.h @@ -131,6 +131,7 @@ struct proxy_child_ctx { struct pc_init_ctx { char *command; pid_t pid; + int error; struct tevent_timer *timeout; struct tevent_signal *sige; struct proxy_child_ctx *child_ctx; diff --git a/src/providers/proxy/proxy_auth.c b/src/providers/proxy/proxy_auth.c index d85320cf64dc004fb0939ffc9acaf2656eed5d5b..da1f5c604648ddef8fa96d9625a1949d17b6d09b 100644 --- a/src/providers/proxy/proxy_auth.c +++ b/src/providers/proxy/proxy_auth.c @@ -318,6 +318,19 @@ static struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx, } } +static void proxy_child_init_finish_with_error(struct tevent_context *ev, + struct tevent_immediate *imm, + void *pvt) +{ + struct tevent_req *req; + struct pc_init_ctx *init_ctx; + + req = talloc_get_type(pvt, struct tevent_req); + init_ctx = tevent_req_data(req, struct pc_init_ctx); + + tevent_req_error(req, init_ctx->error); +} + static void pc_init_sig_handler(struct tevent_context *ev, struct tevent_signal *sige, int signum, int count, void *__siginfo, void *pvt) @@ -326,6 +339,7 @@ static void pc_init_sig_handler(struct tevent_context *ev, int child_status; struct tevent_req *req; struct pc_init_ctx *init_ctx; + struct tevent_immediate *imm; if (count <= 0) { DEBUG(SSSDBG_FATAL_FAILURE, @@ -353,12 +367,12 @@ static void pc_init_sig_handler(struct tevent_context *ev, DEBUG(SSSDBG_CONF_SETTINGS, "child [%d] exited with status [%d].\n", ret, WEXITSTATUS(child_status)); - tevent_req_error(req, EIO); + ret = EIO; } else if (WIFSIGNALED(child_status)) { DEBUG(SSSDBG_CONF_SETTINGS, "child [%d] was terminate by signal [%d].\n", ret, WTERMSIG(child_status)); - tevent_req_error(req, EIO); + ret = EIO; } else { if (WIFSTOPPED(child_status)) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -374,6 +388,20 @@ static void pc_init_sig_handler(struct tevent_context *ev, "Child is still running, no new child is started.\n"); return; } + + /* Invoke the callback in a tevent_immediate handler + * so that it is safe to free the tevent_signal * + */ + imm = tevent_create_immediate(req); + if (imm == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Out of memory invoking sig handler callback\n"); + return; + } + + init_ctx->error = ret; + tevent_schedule_immediate(imm, ev, proxy_child_init_finish_with_error, + req); } } -- 2.4.1