Re: AutoFS segfaults in get_query_dn()

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

 



On Wed, 2012-03-28 at 11:42 -0400, Leonardo Chiquitto wrote:
> On Tue, Mar 27, 2012 at 8:48 PM, Ian Kent <raven@xxxxxxxxxx> wrote:
> > On Wed, 2012-03-28 at 08:26 +0800, Ian Kent wrote:
> >> On Thu, 2012-03-15 at 23:15 -0400, Leonardo Chiquitto wrote:
> >> >
> >> > 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.
> >>
> >
> > An even better approach would be to move the read of the search dns to
> > the lookup_init() module function. That should still do what is needed
> > and reduce the code executed at lookup a little.
> >
> > autofs-5.0.6 - fix segfault in get_query_dn()
> >
> > From: Leonardo Chiquitto <leonardo.lists@xxxxxxxxx>
> >
> > 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.
> >
> > edit: Ian Kent <raven@xxxxxxxxxx>
> > move the read of configured search dns to lookup_init().
> > edit end
> > ---
> 
> Thanks for the updated patch, Ian. I verified that it also resolves
> the problem (I know it's obvious but, as the test case is trivial,
> I wanted to verify).

Ha, disregard my last comment, I'm still half asleep, I'll actually
commit this.

> 
> Leonardo
> 
> >  modules/lookup_ldap.c |   13 +++----------
> >  1 files changed, 3 insertions(+), 10 deletions(-)
> >
> >
> > diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
> > index b6875fe..8d12920 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,15 +329,6 @@ 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;
> > -               }
> > -       }
> > -
> >        dn = NULL;
> >        if (!ctxt->sdns) {
> >                rv = ldap_search_s(ldap, ctxt->base,
> > @@ -1467,6 +1457,9 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
> >                return 1;
> >        }
> >
> > +       if (!ctxt->base)
> > +               ctxt->sdns = defaults_get_searchdns();
> > +
> >        ctxt->timeout = defaults_get_ldap_timeout();
> >        ctxt->network_timeout = defaults_get_ldap_network_timeout();
> >


--
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