Re: AutoFS segfaults in get_query_dn()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2012-03-15 at 23:15 -0400, Leonardo Chiquitto wrote:
> Hello,
> 
> The automounter can crash if two threads execute get_query_dn()
> simultaneously. To reproduce the problem you'll need to:
> 
> - Setup AutoFS with an indirect map on LDAP
> - Set the LDAP base dn ($SEARCH_BASE) in /etc/sysconfig/autofs
> - Trigger many mounts simultaneously (it doesn't matter
 if the keys
>   exist or not in the map). Something like this will be 
enough:
> 
>    $ for i in $(seq 1 100); do
>        nohup ls test$i &
>       done
> 
> Thread "a" crashes when it tries to dereference the "this" pointer:
> 
>  369     } else {
>  370         struct ldap_searchdn *this = ctxt->sdns;
>  371
>  372         debug(logopt, MODPREFIX "check search base list");
>  373
>  374         result = NULL;
>  375         while (this) {
>  376             rv = ldap_search_s(ldap, this->basedn,        <= here
>  377                        scope, query, attrs, 0, &result);
>  378             if ((rv == LDAP_SUCCESS) && result) {
>  379                 debug(logopt, MODPREFIX
>  380                       "found search base under %s",
>  381                       this->basedn);                      <= or here
> 
> Because Thread "b" is running this other section of the same function:
> 
>  333     if (!ctxt->base) {
>  334         sdns = defaults_get_searchdns();
>  335         if (sdns) {
>  336             if (ctxt->sdns)
>  337                 defaults_free_searchdns(ctxt->sdns);   <= frees sdns
>  338             ctxt->sdns = sdns;
>  339         }
>  340     }
> 
> So ctxt->sdns is freed but Thread "a" still keeps a copy of the pointer
> and tries to use it.
> 
> The patch below resolves the problem, but I don't know if it is correct.
> AutoFS rereads $SEARCH_BASE from /etc/sysconfig/autofs every
> time get_query_dn() is called. This *looks* unnecessary, unless the
> intention is to react to sysconfig changes without restarting the
> daemon.

Although the get_query_dn() function was originally only called on map
read and at startup that has changed and it is called on every connect
or reconnect so I agree that we shouldn't reading the search dns every
time.

> 
> Ian, I'd appreciate if you could review the patch.
> 
> Thanks!
> Leonardo
> 
> ---
> 
> Fix segfault in get_query_dn()
> 
> Automount will segfault when two threads run get_query_dn()
> simultaneously and $SEARCH_BASE is defined in sysconfig.
> This happens because a thread tries to dereference ctxt->sdns
> while another thread running the same function frees the
> memory.
> 
> I believe we don't need to reread $SEARCH_BASE every time
> get_query_dn() is called.
> 
> diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
> index b6875fe..6ed3e17 100644
> --- a/modules/lookup_ldap.c
> +++ b/modules/lookup_ldap.c
> @@ -281,7 +281,6 @@ static int get_query_dn(unsigned logopt, LDAP
> *ldap, struct lookup_context *ctxt
>  	char buf[MAX_ERR_BUF];
>  	char *query, *dn, *qdn;
>  	LDAPMessage *result = NULL, *e;
> -	struct ldap_searchdn *sdns = NULL;
>  	char *attrs[2];
>  	struct berval **value;
>  	int scope;
> @@ -330,14 +329,8 @@ static int get_query_dn(unsigned logopt, LDAP
> *ldap, struct lookup_context *ctxt
>  		scope = LDAP_SCOPE_SUBTREE;
>  	}
> 
> -	if (!ctxt->base) {
> -		sdns = defaults_get_searchdns();
> -		if (sdns) {
> -			if (ctxt->sdns)
> -				defaults_free_searchdns(ctxt->sdns);
> -			ctxt->sdns = sdns;
> -		}
> -	}
> +	if (!ctxt->base && !ctxt->sdns)
> +		ctxt->sdns = defaults_get_searchdns();

While this narrows the race window and should prevent the fault, it
still has a problem since ctxt->sdns can change while it is in use. The
above two lines are a non-atomic read then update which can (at the
least) lead to a memory leak when the if (...) is evaluated while
another thread is executing defaults_get_searchdns().

So a mutex is still needed around these two lines.

> 
>  	dn = NULL;
>  	if (!ctxt->sdns) {
> --
> To unsubscribe from this list: send the line "unsubscribe autofs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe autofs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux Ext4]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux