1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
Description: Fix memory leak in libnss-ldap
A memory leak in libnss-ldap over time can cause the nscd process to
grow extremely large.
.
The ldap-nss.c do_init() may be called more then once, to initialize an
ldap session and save the session in __session.ls_conn and
set the __session.ls_stat = LD_INITIALIZED. But it does not check the
state to see if has be initialized, and
at line 1239: __session.ls_conn = NULL;
Bug: http://bugzilla.padl.com/show_bug.cgi?id=418
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libnss-ldap/+bug/292971
Author: Doug Engert <deengert@anl.gov>
Reviewed-by: Mathias Gug <mathiaz@ubuntu.com>
Reviewed-by: Kees Cook <kees@ubuntu.com>
--- a/ldap-nss.c
+++ b/ldap-nss.c
@@ -184,6 +184,7 @@ static void do_atfork_child (void);
static void do_atfork_setup (void);
#endif
+static void do_atexit (void); /* allow exit to cleanup to help valgrind */
/*
* Close the global session, sending an unbind.
*/
@@ -551,11 +552,25 @@ do_atfork_setup (void)
(void) __libc_atfork (do_atfork_prepare, do_atfork_parent, do_atfork_child);
#endif
+atexit(do_atexit); /* allow exit to cleanup to help valgrind */
+
debug ("<== do_atfork_setup");
}
#endif
/*
+ * allow exit to cleanup to help valgrind
+ */
+void
+do_atexit (void)
+{
+ debug ("<== do_atexit");
+ _nss_ldap_enter();
+ do_close();
+ debug ("==> do_atexit (should be no more activity)");
+}
+
+/*
* Acquires global lock, blocks SIGPIPE.
*/
void
@@ -1234,9 +1249,9 @@ do_init (void)
}
}
- __session.ls_conn = NULL;
+/* LOOKS LIKE A PROBLEM. COULD BE INITIALIZED, BUT NOT CONNECTED */
+ if (__session.ls_state == LS_UNINITIALIZED) {
__session.ls_timestamp = 0;
- __session.ls_state = LS_UNINITIALIZED;
#if defined(HAVE_PTHREAD_ONCE) && defined(HAVE_PTHREAD_ATFORK)
if (pthread_once (&__once, do_atfork_setup) != 0)
@@ -1355,6 +1370,10 @@ do_init (void)
__session.ls_state = LS_INITIALIZED;
debug ("<== do_init (initialized session)");
+ } /* if already initialized but not connected */
+ else {
+ debug ("<== do_init (already initialized)");
+ }
return NSS_SUCCESS;
}
@@ -1575,6 +1594,7 @@ do_open (void)
}
else
{
+ syslog(LOG_ERR, "nss-ldap: do_open: do_start_tls failed:stat=%d", stat);
do_close ();
debug ("<== do_open (TLS startup failed)");
return stat;
|