a9ec530
From 673c2ce9b3371241de872b2bd206f732485888cb Mon Sep 17 00:00:00 2001
a9ec530
From: Stephen Gallagher <sgallagh@redhat.com>
a9ec530
Date: Fri, 19 Jun 2009 11:09:33 -0400
a9ec530
Subject: [PATCH] Fix segfault in update_monitor_config
a9ec530
a9ec530
We were stealing the memory context of only the first value in
a9ec530
the linked-list of domains (and also services). This patch adds a
a9ec530
memory context to hold the lists so that can be stolen along with
a9ec530
all of the entries.
a9ec530
---
a9ec530
 server/confdb/confdb.c   |    4 ++++
a9ec530
 server/monitor/monitor.c |   34 ++++++++++++++++++++++++++--------
a9ec530
 2 files changed, 30 insertions(+), 8 deletions(-)
a9ec530
a9ec530
diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c
a9ec530
index 8eefcfb..8b8dc74 100644
a9ec530
--- a/server/confdb/confdb.c
a9ec530
+++ b/server/confdb/confdb.c
a9ec530
@@ -709,6 +709,10 @@ int confdb_get_domain(struct confdb_ctx *cdb,
a9ec530
     }
a9ec530
 
a9ec530
     domain = talloc_zero(mem_ctx, struct sss_domain_info);
a9ec530
+    if (!domain) {
a9ec530
+        ret = ENOMEM;
a9ec530
+        goto done;
a9ec530
+    }
a9ec530
 
a9ec530
     tmp = ldb_msg_find_attr_as_string(res->msgs[0], "cn", NULL);
a9ec530
     if (!tmp) {
a9ec530
diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c
a9ec530
index 906d157..e4fca25 100644
a9ec530
--- a/server/monitor/monitor.c
a9ec530
+++ b/server/monitor/monitor.c
a9ec530
@@ -84,7 +84,9 @@ struct mt_svc {
a9ec530
 struct mt_ctx {
a9ec530
     struct tevent_context *ev;
a9ec530
     struct confdb_ctx *cdb;
a9ec530
+    TALLOC_CTX *domain_ctx; /* Memory context for domain list */
a9ec530
     struct sss_domain_info *domains;
a9ec530
+    TALLOC_CTX *service_ctx; /* Memory context for services */
a9ec530
     char **services;
a9ec530
     struct mt_svc *svc_list;
a9ec530
     struct sbus_srv_ctx *sbus_srv;
a9ec530
@@ -619,8 +621,13 @@ int get_monitor_config(struct mt_ctx *ctx)
a9ec530
         return ret;
a9ec530
     }
a9ec530
 
a9ec530
-    ret = confdb_get_string_as_list(ctx->cdb, ctx, SERVICE_CONF_ENTRY,
a9ec530
-                                    "activeServices", &ctx->services);
a9ec530
+    ctx->service_ctx = talloc_new(ctx);
a9ec530
+    if(!ctx->service_ctx) {
a9ec530
+        return ENOMEM;
a9ec530
+    }
a9ec530
+    ret = confdb_get_string_as_list(ctx->cdb, ctx->service_ctx,
a9ec530
+                                    SERVICE_CONF_ENTRY, "activeServices",
a9ec530
+                                    &ctx->services);
a9ec530
     if (ret != EOK) {
a9ec530
         DEBUG(0, ("No services configured!\n"));
a9ec530
         return EINVAL;
a9ec530
@@ -631,7 +638,11 @@ int get_monitor_config(struct mt_ctx *ctx)
a9ec530
         return ret;
a9ec530
     }
a9ec530
 
a9ec530
-    ret = confdb_get_domains(ctx->cdb, ctx, &ctx->domains);
a9ec530
+    ctx->domain_ctx = talloc_new(ctx);
a9ec530
+    if(!ctx->domain_ctx) {
a9ec530
+        return ENOMEM;
a9ec530
+    }
a9ec530
+    ret = confdb_get_domains(ctx->cdb, ctx->domain_ctx, &ctx->domains);
a9ec530
     if (ret != EOK) {
a9ec530
         DEBUG(2, ("No domains configured. LOCAL should always exist!\n"));
a9ec530
         return ret;
a9ec530
@@ -861,7 +872,12 @@ static int update_monitor_config(struct mt_ctx *ctx)
a9ec530
     struct mt_svc *cur_svc;
a9ec530
     struct mt_svc *new_svc;
a9ec530
     struct sss_domain_info *dom, *new_dom;
a9ec530
-    struct mt_ctx *new_config = talloc_zero(NULL, struct mt_ctx);
a9ec530
+    struct mt_ctx *new_config;
a9ec530
+
a9ec530
+    new_config = talloc_zero(NULL, struct mt_ctx);
a9ec530
+    if(!new_config) {
a9ec530
+        return ENOMEM;
a9ec530
+    }
a9ec530
 
a9ec530
     new_config->ev = ctx->ev;
a9ec530
     new_config->cdb = ctx->cdb;
a9ec530
@@ -953,8 +969,9 @@ static int update_monitor_config(struct mt_ctx *ctx)
a9ec530
     }
a9ec530
 
a9ec530
     /* Replace the old service list with the new one */
a9ec530
-    talloc_free(ctx->services);
a9ec530
-    ctx->services = talloc_steal(ctx, new_config->services);
a9ec530
+    talloc_free(ctx->service_ctx);
a9ec530
+    ctx->service_ctx = talloc_steal(ctx, new_config->service_ctx);
a9ec530
+    ctx->services = new_config->services;
a9ec530
 
a9ec530
     /* Compare data providers */
a9ec530
     /* Have any providers been disabled? */
a9ec530
@@ -1040,8 +1057,9 @@ static int update_monitor_config(struct mt_ctx *ctx)
a9ec530
     }
a9ec530
 
a9ec530
     /* Replace the old domain list with the new one */
a9ec530
-    talloc_free(ctx->domains);
a9ec530
-    ctx->domains = talloc_steal(ctx, new_config->domains);
a9ec530
+    talloc_free(ctx->domain_ctx);
a9ec530
+    ctx->domain_ctx = talloc_steal(ctx, new_config->domain_ctx);
a9ec530
+    ctx->domains = new_config->domains;
a9ec530
 
a9ec530
     /* Signal all services to reload their configuration */
a9ec530
     for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
a9ec530
-- 
a9ec530
1.6.2.2
a9ec530