[SSSD] [PATCH] proxy: Do not crash if proxy_child returns error

Lukas Slebodnik lslebodn at redhat.com
Wed May 20 12:20:48 UTC 2015


ehlo,

attached patch fixes a crash if return code of proxy_child is not 0.
You can reproduce it with sssd in non-root mode or
you can replace proxy_child with bash script.

I'm not sure about the name of tevent_immediate callback
so feel free to propose better name.

LS
-------------- next part --------------
>From 8a8873a1ff85ebfeaebe65eb998b3ffe8910f0d3 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
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



More information about the sssd-devel mailing list