For [BZ#14122], plug memory leaks in nsswitch.c.
This commit is contained in:
parent
da0331a873
commit
d44638b0a7
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
2012-05-22 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||||
|
|
||||||
|
[BZ #14122]
|
||||||
|
* nss/nsswitch.c (defconfig_entries): New variable.
|
||||||
|
(__nss_database_lookup): Don't leak defconfig entries.
|
||||||
|
(nss_parse_service_list): Don't leak on error paths.
|
||||||
|
(free_database_entries): New function.
|
||||||
|
(free_defconfig): New function.
|
||||||
|
(free_mem): Move common code to free_database_entries.
|
||||||
|
|
||||||
2012-05-22 H.J. Lu <hongjiu.lu@intel.com>
|
2012-05-22 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/x86_64/x32/Makefile (sysdep_routines):
|
* sysdeps/unix/sysv/linux/x86_64/x32/Makefile (sysdep_routines):
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* Copyright (C) 1996-2012
|
/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||||||
Free Software Foundation, Inc.
|
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||||
|
|
||||||
|
@ -86,6 +85,12 @@ static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
|
||||||
/* The root of the whole data base. */
|
/* The root of the whole data base. */
|
||||||
static name_database *service_table;
|
static name_database *service_table;
|
||||||
|
|
||||||
|
/* List of default service lists that were generated by glibc because
|
||||||
|
/etc/nsswitch.conf did not provide a value.
|
||||||
|
The list is only maintained so we can free such service lists in
|
||||||
|
__libc_freeres. */
|
||||||
|
static name_database_entry *defconfig_entries;
|
||||||
|
|
||||||
|
|
||||||
/* Nonzero if this is the nscd process. */
|
/* Nonzero if this is the nscd process. */
|
||||||
static bool is_nscd;
|
static bool is_nscd;
|
||||||
|
@ -141,8 +146,27 @@ __nss_database_lookup (const char *database, const char *alternate_name,
|
||||||
DEFCONFIG specifies the default service list for this database,
|
DEFCONFIG specifies the default service list for this database,
|
||||||
or null to use the most common default. */
|
or null to use the most common default. */
|
||||||
if (*ni == NULL)
|
if (*ni == NULL)
|
||||||
*ni = nss_parse_service_list (defconfig
|
{
|
||||||
?: "nis [NOTFOUND=return] files");
|
*ni = nss_parse_service_list (defconfig
|
||||||
|
?: "nis [NOTFOUND=return] files");
|
||||||
|
if (*ni != NULL)
|
||||||
|
{
|
||||||
|
/* Record the memory we've just allocated in defconfig_entries list,
|
||||||
|
so we can free it later. */
|
||||||
|
name_database_entry *entry;
|
||||||
|
|
||||||
|
/* Allocate ENTRY plus size of name (1 here). */
|
||||||
|
entry = (name_database_entry *) malloc (sizeof (*entry) + 1);
|
||||||
|
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
entry->next = defconfig_entries;
|
||||||
|
entry->service = *ni;
|
||||||
|
entry->name[0] = '\0';
|
||||||
|
defconfig_entries = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__libc_lock_unlock (lock);
|
__libc_lock_unlock (lock);
|
||||||
|
|
||||||
|
@ -644,7 +668,7 @@ nss_parse_service_list (const char *line)
|
||||||
else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
|
else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
|
||||||
status = NSS_STATUS_UNAVAIL;
|
status = NSS_STATUS_UNAVAIL;
|
||||||
else
|
else
|
||||||
return result;
|
goto finish;
|
||||||
}
|
}
|
||||||
else if (line - name == 8)
|
else if (line - name == 8)
|
||||||
{
|
{
|
||||||
|
@ -653,15 +677,15 @@ nss_parse_service_list (const char *line)
|
||||||
else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
|
else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
|
||||||
status = NSS_STATUS_TRYAGAIN;
|
status = NSS_STATUS_TRYAGAIN;
|
||||||
else
|
else
|
||||||
return result;
|
goto finish;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return result;
|
goto finish;
|
||||||
|
|
||||||
while (isspace (line[0]))
|
while (isspace (line[0]))
|
||||||
++line;
|
++line;
|
||||||
if (line[0] != '=')
|
if (line[0] != '=')
|
||||||
return result;
|
goto finish;
|
||||||
do
|
do
|
||||||
++line;
|
++line;
|
||||||
while (isspace (line[0]));
|
while (isspace (line[0]));
|
||||||
|
@ -677,7 +701,7 @@ nss_parse_service_list (const char *line)
|
||||||
&& __strncasecmp (name, "CONTINUE", 8) == 0)
|
&& __strncasecmp (name, "CONTINUE", 8) == 0)
|
||||||
action = NSS_ACTION_CONTINUE;
|
action = NSS_ACTION_CONTINUE;
|
||||||
else
|
else
|
||||||
return result;
|
goto finish;
|
||||||
|
|
||||||
if (not)
|
if (not)
|
||||||
{
|
{
|
||||||
|
@ -705,6 +729,11 @@ nss_parse_service_list (const char *line)
|
||||||
|
|
||||||
*nextp = new_service;
|
*nextp = new_service;
|
||||||
nextp = &new_service->next;
|
nextp = &new_service->next;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
free (new_service);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,22 +845,9 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
/* Free all resources if necessary. */
|
free_database_entries (name_database_entry *entry)
|
||||||
libc_freeres_fn (free_mem)
|
|
||||||
{
|
{
|
||||||
name_database *top = service_table;
|
|
||||||
name_database_entry *entry;
|
|
||||||
service_library *library;
|
|
||||||
|
|
||||||
if (top == NULL)
|
|
||||||
/* Maybe we have not read the nsswitch.conf file. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Don't disturb ongoing other threads (if there are any). */
|
|
||||||
service_table = NULL;
|
|
||||||
|
|
||||||
entry = top->entry;
|
|
||||||
while (entry != NULL)
|
while (entry != NULL)
|
||||||
{
|
{
|
||||||
name_database_entry *olde = entry;
|
name_database_entry *olde = entry;
|
||||||
|
@ -851,6 +867,36 @@ libc_freeres_fn (free_mem)
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
free (olde);
|
free (olde);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free all resources if necessary. */
|
||||||
|
libc_freeres_fn (free_defconfig)
|
||||||
|
{
|
||||||
|
name_database_entry *entry = defconfig_entries;
|
||||||
|
|
||||||
|
if (entry == NULL)
|
||||||
|
/* defconfig was not used. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Don't disturb ongoing other threads (if there are any). */
|
||||||
|
defconfig_entries = NULL;
|
||||||
|
|
||||||
|
free_database_entries (entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
libc_freeres_fn (free_mem)
|
||||||
|
{
|
||||||
|
name_database *top = service_table;
|
||||||
|
service_library *library;
|
||||||
|
|
||||||
|
if (top == NULL)
|
||||||
|
/* Maybe we have not read the nsswitch.conf file. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Don't disturb ongoing other threads (if there are any). */
|
||||||
|
service_table = NULL;
|
||||||
|
|
||||||
|
free_database_entries (top->entry);
|
||||||
|
|
||||||
library = top->library;
|
library = top->library;
|
||||||
while (library != NULL)
|
while (library != NULL)
|
||||||
|
|
Loading…
Reference in New Issue