Winbindd using 100% of CPU. Any solution?

Jeremy Allison jra at samba.org
Mon Jan 6 16:41:27 MST 2014


On Mon, Jan 06, 2014 at 09:54:15AM -0800, Richard Sharpe wrote:
> 
> Sure. I know it took me a long while to figure this out.
> 
> It starts in rescan_forest_trusts and relates to the fact that two
> domains, XCHANGE and EXCHANGE, which both have DNS names
> xchange.some.dom, are reported.
> 
> In the loop we do not find the domain in find_domain_from_name_noinit,
> but further down, because the flags seem to be correct, we call
> add_trusted_domain because the earlier find came up empty.
> 
> add_trusted_domain does not find the domain based on its domain name,
> but does find it based on its alternate name, and so it returns that
> domain, after possibly updating the SID.
> 
> Back in rescan_forest_trusts, if we come up with a domain from
> add_trusted_domain, we call setup_domain_child, which only calls
> setup_child which sets the socket to -1 on a possibly already in the
> list child ...

Ok, I chatted with Richard and the underlying problem
is a disconnect with setup_domain_child() being called on
domain structs that have already been added into the list,
instead of only being called when a struct is allocated
and added into the list.

The solution to that is to move the call to setup_domain_child()
inside of the add_trusted_domain() function, so it is
only called when a new domain struct is added.

Attached is a small patchset that does this, and
also keeps the logic identical by also moving the
setting of 'domain->primary = true' inside
add_trusted_domain() to ensure the current
ordering of variable changes is the same.

That could also be done by adding a 'bool primary'
parameter to the add_trusted_domain() parameter
list, but I know how much Volker hates new arbitrary
bool parameters, so I though it was cleaner to
do it this way :-).

I'm pretty sure this is the correct way to
fix the logic, but getting a reproducer (or
a site that can reproduce and test the patches)
will be needed.

Please review + test. I'll also attach this
to the bug report (https://bugzilla.samba.org/show_bug.cgi?id=10358).

Cheers,

	Jeremy.
-------------- next part --------------
From e8df82a13d21d5a50233fe209e502df5b901c9de Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 6 Jan 2014 15:15:37 -0800
Subject: [PATCH 1/2] s3: winbindd: Move the logic of whether to set
 'domain->primary' into add_trusted_domain().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10358

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/winbindd/winbindd_util.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 85b014d..10ca132 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -99,6 +99,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 	char *idmap_config_option;
 	const char *param;
 	const char **ignored_domains, **dom;
+	int role = lp_server_role();
 
 	ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
 	for (dom=ignored_domains; dom && *dom; dom++) {
@@ -196,6 +197,15 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 		sid_copy(&domain->sid, sid);
 	}
 
+	/* Is this our primary domain ? */
+	if (strequal(domain_name, get_global_sam_name()) &&
+			(role != ROLE_DOMAIN_MEMBER)) {
+		domain->primary = true;
+	} else if (strequal(domain_name, lp_workgroup()) &&
+			(role == ROLE_DOMAIN_MEMBER)) {
+		domain->primary = true;
+	}
+
 	/* Link to domain list */
 	DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
 
@@ -628,9 +638,6 @@ bool init_domain_list(void)
 	domain = add_trusted_domain(get_global_sam_name(), NULL,
 				    &cache_methods, get_global_sam_sid());
 	if (domain) {
-		if ( role != ROLE_DOMAIN_MEMBER ) {
-			domain->primary = True;
-		}
 		setup_domain_child(domain);
 	}
 
@@ -647,7 +654,6 @@ bool init_domain_list(void)
 		domain = add_trusted_domain( lp_workgroup(), lp_realm(),
 					     &cache_methods, &our_sid);
 		if (domain) {
-			domain->primary = True;
 			setup_domain_child(domain);
 
 			/* Even in the parent winbindd we'll need to
-- 
1.8.5.1


From 2895fb19671a9a40224eabed83af9701d88d3ce0 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 6 Jan 2014 15:22:59 -0800
Subject: [PATCH 2/2] s3: winbindd: Move calling setup_domain_child() into
 add_trusted_domain().

Ensure it only gets called when a new domain is allocated
and added to the list.

This should fix problems with the previous logic where
setup_domain_child() was called in places where an existing
domain was returned.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=10358

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/winbindd/winbindd_util.c | 36 ++++++------------------------------
 1 file changed, 6 insertions(+), 30 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 10ca132..98b70a8 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -242,6 +242,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 done:
 
+	setup_domain_child(domain);
+
 	DEBUG(2,("Added domain %s %s %s\n",
 		 domain->name, domain->alt_name,
 		 &domain->sid?sid_string_dbg(&domain->sid):""));
@@ -315,9 +317,7 @@ static void trustdom_list_done(struct tevent_req *req)
 	while ((p != NULL) && (*p != '\0')) {
 		char *q, *sidstr, *alt_name;
 		struct dom_sid sid;
-		struct winbindd_domain *domain;
 		char *alternate_name = NULL;
-		bool domain_exists;
 
 		alt_name = strchr(p, '\\');
 		if (alt_name == NULL) {
@@ -351,26 +351,16 @@ static void trustdom_list_done(struct tevent_req *req)
 		if ( !strequal( alt_name, "(null)" ) )
 			alternate_name = alt_name;
 
-		/* Check if we already have a child for the domain */
-		domain_exists = (find_domain_from_name_noinit(p) != NULL);
-
 		/*
 		 * We always call add_trusted_domain() cause on an existing
 		 * domain structure, it will update the SID if necessary.
 		 * This is important because we need the SID for sibling
 		 * domains.
 		 */
-		domain = add_trusted_domain(p, alternate_name,
+		(void)add_trusted_domain(p, alternate_name,
 					    &cache_methods,
 					    &sid);
 
-		/*
-		 * If the domain doesn't exist yet and got correctly added,
-		 * setup a new domain child.
-		 */
-		if (!domain_exists && domain != NULL) {
-			setup_domain_child(domain);
-		}
 		p=q;
 		if (p != NULL)
 			p += 1;
@@ -444,9 +434,6 @@ static void rescan_forest_root_trusts( void )
 						dom_list[i].dns_name,
 						&cache_methods,
 						&dom_list[i].sid );
-			if (d != NULL) {
-				setup_domain_child(d);
-			}
 		}
 
 		if (d == NULL) {
@@ -516,9 +503,6 @@ static void rescan_forest_trusts( void )
 							dom_list[i].dns_name,
 							&cache_methods,
 							&dom_list[i].sid );
-				if (d != NULL) {
-					setup_domain_child(d);
-				}
 			}
 
 			if (d == NULL) {
@@ -619,7 +603,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai
 /* Look up global info for the winbind daemon */
 bool init_domain_list(void)
 {
-	struct winbindd_domain *domain;
 	int role = lp_server_role();
 
 	/* Free existing list */
@@ -627,23 +610,18 @@ bool init_domain_list(void)
 
 	/* BUILTIN domain */
 
-	domain = add_trusted_domain("BUILTIN", NULL, &cache_methods,
+	(void)add_trusted_domain("BUILTIN", NULL, &cache_methods,
 				    &global_sid_Builtin);
-	if (domain) {
-		setup_domain_child(domain);
-	}
 
 	/* Local SAM */
 
-	domain = add_trusted_domain(get_global_sam_name(), NULL,
+	(void)add_trusted_domain(get_global_sam_name(), NULL,
 				    &cache_methods, get_global_sam_sid());
-	if (domain) {
-		setup_domain_child(domain);
-	}
 
 	/* Add ourselves as the first entry. */
 
 	if ( role == ROLE_DOMAIN_MEMBER ) {
+		struct winbindd_domain *domain;
 		struct dom_sid our_sid;
 
 		if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
@@ -654,8 +632,6 @@ bool init_domain_list(void)
 		domain = add_trusted_domain( lp_workgroup(), lp_realm(),
 					     &cache_methods, &our_sid);
 		if (domain) {
-			setup_domain_child(domain);
-
 			/* Even in the parent winbindd we'll need to
 			   talk to the DC, so try and see if we can
 			   contact it. Theoretically this isn't neccessary
-- 
1.8.5.1



More information about the samba-technical mailing list