Comment 72 for bug 423252

Revision history for this message
Howard Chu (hyc) wrote : Re: NSS using LDAP on Karmic breaks 'su' and 'sudo'

I read all of the diffs between 1.4.1 and 1.4.4 but didn't find any likely suspects. However, tracing the library initialization in gdb, I found the specific problem.

Ordinarily gnutls will initialize the gcrypt library, if no app has done so already. In the gnutls initialization, it specifically turns gcrypt's secure malloc off, and everything works fine.

However, in my trace on Lucid, libnss-ldap is linked to libldap_r, not libldap. And because libldap_r has to support threads, it is required to initialize libgcrypt's thread callbacks, and it must do this before doing anything else with libgcrypt or gnutls.

http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html#Multi_002dThreading

The problem with that is, once we do this thread initialization, libgcrypt considers itself fully initialized. When we next call gnutls's init function, it checks to see if gcrypt is init'd or not, sees that it is, and skips any further init'ing. So the secure malloc stuff remains enabled.

I guess in this case we could do the initialization that gnutls skips, but that's rather ugly, libldap shouldn't have to know or duplicate the initialization steps inside gnutls_global_init(). Alternatively, libgcrypt could be changed to not call its global_init() right after setting the thread callbacks, since it's obvious that the caller still has other initialization calls that it needs to make. (Frankly I think this is the correct option.)

Finally, gnutls_global_init() could be changed to check for initialization_finished, instead of initialization_started. (i.e., check for GCRYCTL_INITIALIZATION_FINISHED_P, instead of GCRYCTL_ANY_INITIALIZATION_P). But this latter is pretty dicey, gnutls really has no way to know if it should be meddling in a half-initialized libgcrypt or not.

I'm trying really hard not to say "I told you so" again, but I just can't stop myself.