From: Stefan Metzmacher Date: Fri, 7 Feb 2025 12:43:10 +0000 (+0100) Subject: winbindd: add struct winbindd_domain_ref infrastructure X-Git-Tag: tevent-0.17.0~842 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d9db5cccc086bfcefa33daa7c03443d0614e982;p=thirdparty%2Fsamba.git winbindd: add struct winbindd_domain_ref infrastructure In the next commits it will be possible that struct winbindd_domain instances become stale because trusted domains were reloaded. That means aync state structure should not use pointers to 'struct winbindd_domain' as they can become stale! Instead they should use 'struct winbindd_domain_ref domain' in the async state and use winbindd_domain_ref_set/get() to manage the 'struct winbindd_domain' pointer. Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index dd1163663b0..144fd466e6e 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -67,6 +67,35 @@ struct winbindd_cli_state { struct getgrent_state *grent_state; /* State for getgrent() */ }; +struct winbindd_domain; + +struct winbindd_domain_ref_internals { + const char *location; + const char *func; + bool stale; + struct dom_sid sid; + uint64_t generation; + struct winbindd_domain *domain; /* might be stale */ +}; + +struct winbindd_domain_ref { + struct winbindd_domain_ref_internals internals; +}; + +void _winbindd_domain_ref_set(struct winbindd_domain_ref *ref, + struct winbindd_domain *domain, + const char *location, + const char *func); +#define winbindd_domain_ref_set(__ref, __domain) \ + _winbindd_domain_ref_set(__ref, __domain, __location__, __func__) + +bool _winbindd_domain_ref_get(struct winbindd_domain_ref *ref, + struct winbindd_domain **_domain, + const char *location, + const char *func); +#define winbindd_domain_ref_get(__ref, __domain) \ + _winbindd_domain_ref_get(__ref, __domain, __location__, __func__) + struct getpwent_state { struct winbindd_domain *domain; uint32_t next_user; @@ -101,8 +130,6 @@ struct winbindd_cm_conn { /* Async child */ -struct winbindd_domain; - struct winbindd_child { pid_t pid; struct winbindd_domain *domain; /* if valid also talloc (grant) parent */ diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 23b34b01641..e66e0754604 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -53,6 +53,7 @@ the domain name instead. */ static struct winbindd_domain *_domain_list = NULL; +static uint64_t domain_list_generation; struct winbindd_domain *domain_list(void) { @@ -87,6 +88,79 @@ struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain) return domain; } +void _winbindd_domain_ref_set(struct winbindd_domain_ref *ref, + struct winbindd_domain *domain, + const char *location, + const char *func) +{ + if (domain == NULL) { + ref->internals = (struct winbindd_domain_ref_internals) { + .location = location, + .func = func, + }; + return; + } + + ref->internals = (struct winbindd_domain_ref_internals) { + .location = location, + .func = func, + .sid = domain->sid, + .generation = domain_list_generation, + .domain = domain, + }; +} + +bool _winbindd_domain_ref_get(struct winbindd_domain_ref *ref, + struct winbindd_domain **_domain, + const char *location, + const char *func) +{ + struct winbindd_domain *domain = NULL; + + if (ref->internals.stale) { + goto stale; + } + + if (ref->internals.domain == NULL) { + *_domain = NULL; + return true; + } + + if (ref->internals.generation == domain_list_generation) { + *_domain = ref->internals.domain; + return true; + } + + domain = find_domain_from_sid_noinit(&ref->internals.sid); +stale: + if (domain == NULL) { + struct dom_sid_buf sbuf = {}; + + D_ERR("%s:%s: stale domain %s, set in %s\n", + func, + location, + dom_sid_str_buf(&ref->internals.sid, &sbuf), + ref->internals.location); + + ref->internals.stale = true; + ref->internals.domain = NULL; + + *_domain = NULL; + return false; + } + + ref->internals = (struct winbindd_domain_ref_internals) { + .location = location, + .func = func, + .sid = domain->sid, + .generation = domain_list_generation, + .domain = domain, + }; + + *_domain = domain; + return true; +} + static bool is_internal_domain(const struct dom_sid *sid) { if (sid == NULL) @@ -292,6 +366,7 @@ static NTSTATUS add_trusted_domain(const char *domain_name, /* Link to domain list */ DLIST_ADD_END(_domain_list, domain); + domain_list_generation += 1; wcache_tdc_add_domain( domain );