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

[commits] r1383 - in /trunk: libc/ libc/csu/ libc/elf/ libc/iconvdata/ libc/iconvdata/testdata/ libc/include/ libc/locale/ libc/locale...



Author: joseph
Date: Mon Feb  5 09:59:45 2007
New Revision: 1383

Log:
Merge changes between r1192 and r1382 from /fsf/trunk.

Added:
    trunk/libc/iconvdata/brf.c
      - copied unchanged from r1382, fsf/trunk/libc/iconvdata/brf.c
    trunk/libc/iconvdata/testdata/BRF
      - copied unchanged from r1382, fsf/trunk/libc/iconvdata/testdata/BRF
    trunk/libc/iconvdata/testdata/BRF..UTF8
      - copied unchanged from r1382, fsf/trunk/libc/iconvdata/testdata/BRF..UTF8
    trunk/libc/localedata/charmaps/BRF
      - copied unchanged from r1382, fsf/trunk/libc/localedata/charmaps/BRF
    trunk/libc/stdio-common/bug17.c
      - copied unchanged from r1382, fsf/trunk/libc/stdio-common/bug17.c
    trunk/libc/string/strerror_l.c
      - copied unchanged from r1382, fsf/trunk/libc/string/strerror_l.c
    trunk/ports/sysdeps/powerpc/nofpu/fenv_libc.h
      - copied unchanged from r1382, fsf/trunk/ports/sysdeps/powerpc/nofpu/fenv_libc.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c
      - copied unchanged from r1382, fsf/trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/semctl.c
      - copied unchanged from r1382, fsf/trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/semctl.c
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c
      - copied unchanged from r1382, fsf/trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c
Removed:
    trunk/libc/soft-fp/fenv_libc.h
Modified:
    trunk/libc/ChangeLog
    trunk/libc/NEWS
    trunk/libc/csu/libc-start.c
    trunk/libc/elf/dl-lookup.c
    trunk/libc/elf/dl-minimal.c
    trunk/libc/elf/dl-runtime.c
    trunk/libc/elf/dl-sym.c
    trunk/libc/iconvdata/Makefile
    trunk/libc/iconvdata/TESTS
    trunk/libc/iconvdata/gconv-modules
    trunk/libc/iconvdata/tst-tables.sh
    trunk/libc/include/locale.h
    trunk/libc/locale/uselocale.c
    trunk/libc/localedata/ChangeLog
    trunk/libc/math/basic-test.c
    trunk/libc/math/test-misc.c
    trunk/libc/misc/hsearch_r.c
    trunk/libc/nptl/ChangeLog
    trunk/libc/nptl/forward.c
    trunk/libc/nptl/pthread_join.c
    trunk/libc/nptl/sysdeps/pthread/bits/libc-lock.h
    trunk/libc/nptl/sysdeps/pthread/pthread-functions.h
    trunk/libc/nptl/sysdeps/pthread/setxid.h
    trunk/libc/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
    trunk/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
    trunk/libc/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c
    trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
    trunk/libc/nptl/tst-initializers1.c
    trunk/libc/nscd/cache.c
    trunk/libc/nscd/connections.c
    trunk/libc/nscd/nscd-client.h
    trunk/libc/nscd/nscd_getai.c
    trunk/libc/nscd/nscd_getgr_r.c
    trunk/libc/nscd/nscd_gethst_r.c
    trunk/libc/nscd/nscd_getpw_r.c
    trunk/libc/nscd/nscd_getserv_r.c
    trunk/libc/nscd/nscd_helper.c
    trunk/libc/nscd/nscd_initgroups.c
    trunk/libc/po/sv.po
    trunk/libc/scripts/gen-as-const.awk
    trunk/libc/soft-fp/op-common.h
    trunk/libc/stdio-common/Makefile
    trunk/libc/stdio-common/_itoa.c
    trunk/libc/stdio-common/_itoa.h
    trunk/libc/stdio-common/_itowa.c
    trunk/libc/string/Makefile
    trunk/libc/string/Versions
    trunk/libc/string/string.h
    trunk/libc/sysdeps/generic/ldsodefs.h
    trunk/libc/sysdeps/i386/bits/byteswap.h
    trunk/libc/sysdeps/i386/dl-trampoline.S
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_ceill.c
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_copysignl.c
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_floorl.c
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_roundl.c
    trunk/libc/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
    trunk/libc/sysdeps/posix/system.c
    trunk/libc/sysdeps/unix/sysv/linux/fatal-prepare.h
    trunk/libc/sysdeps/unix/sysv/linux/getdents.c
    trunk/libc/sysdeps/unix/sysv/linux/i386/sysdep.h
    trunk/libc/sysdeps/unix/sysv/linux/sys/personality.h
    trunk/libc/sysdeps/unix/sysv/linux/x86_64/sysdep.h
    trunk/libc/sysdeps/x86_64/bits/byteswap.h
    trunk/libc/wcsmbs/wchar.h
    trunk/ports/ChangeLog.arm
    trunk/ports/ChangeLog.hppa
    trunk/ports/ChangeLog.mips
    trunk/ports/ChangeLog.powerpc
    trunk/ports/sysdeps/hppa/dl-trampoline.S
    trunk/ports/sysdeps/unix/sysv/linux/arm/sysdep.h
    trunk/ports/sysdeps/unix/sysv/linux/hppa/sysdep.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h
    trunk/ports/sysdeps/unix/sysv/linux/mips/mips64/syscalls.list

Modified: trunk/libc/ChangeLog
==============================================================================
--- trunk/libc/ChangeLog (original)
+++ trunk/libc/ChangeLog Mon Feb  5 09:59:45 2007
@@ -1,3 +1,222 @@
+2007-02-03  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* po/sv.po: Update from translation team.
+
+2007-02-02  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* nscd/nscd_helper.c (open_socket): Minor size optimization.
+
+2007-02-02  Jakub Jelinek  <jakub@xxxxxxxxxx>
+
+	* include/locale.h (__uselocale): Add libc_hidden_proto.
+	* locale/uselocale.c (__uselocale): Add libc_hidden_def.
+
+	* nscd/nscd_helper.c (open_socket): Use __gettimeofday instead of
+	gettimeofday.
+
+2007-02-01  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/unix/sysv/linux/i386/sysdep.h (PTR_MANGLE): Roll value before
+	returning.
+	(PTR_DEMANGLE): Real definition now that it's not the same as
+	PRT_MANGLE anymore.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
+
+	* string/strerror_l.c: New file.
+	* string/Makefile (routines): Add strerror_l.
+	* string/string.h: Declare strerror_l.
+	* string/Versions: Export strerror_l for GLIBC_2.6.
+
+2007-01-31  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* nscd/nscd_helper.c (open_socket): Now takes request type and key
+	as parameter.  Construct request record.  Try sending request
+	before the first poll use, it usually succeeds.  Adjust all
+	callers.
+	* nscd/nscd-client.h: Define MAXKEYLEN.
+	* nscd/connections.c (nscd_run): Don't define MAXKEYLEN here.
+
+2007-01-31  Jakub Jelinek  <jakub@xxxxxxxxxx>
+
+	* nscd/nscd-client.h (__nscd_cache_search): Remove const qualifier
+	from return value.
+	* nscd/nscd_helper.c: Include string.h.
+	(__nscd_cache_search): Remove const qualifier from return value.
+	On strict alignment architectures check hash entry and data head
+	alignment.
+	* nscd/nscd_getpw_r.c (nscd_getpw_r): Don't crash or fail because
+	mmapped data during GC cycle contains garbage.  If
+	__nscd_drop_map_ref fails, decrement mapped->counter when returning
+	error or if retrying with NO_MAPPING, only __nscd_unmap if counter
+	dropped to 0.
+	* nscd/nscd_getgr_r.c (nscd_getgr_r): Likewise.
+	* nscd/nscd_initgroups.c (__nscd_getgrouplist): Likewise.
+	* nscd/nscd_gethst_r.c (nscd_gethst_r): Likewise.
+	* nscd/nscd_getai.c (__nscd_getai): Likewise.
+	* nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
+
+2007-01-30  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* misc/hsearch_r.c (hdestroy_r): Remove unnecessary test.
+
+2007-01-26  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/i386/dl-trampoline.S (_dl_runtime_profile): Use register
+	names not numbers in cfi_*.
+
+2007-01-26  Andreas Jaeger  <aj@xxxxxxx>
+
+	* sysdeps/unix/sysv/linux/sys/personality.h (ADDR_NO_RANDOMIZE,
+	ADDR_LIMIT_3GB, PER_LINUX_32BIT, PER_LINUX32_3GB): Add.
+	Correct values of PER_HPUX and PER_OSF4.
+
+2007-01-24  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* elf/dl-minimal.c: Undefine _itoa first.
+	* stdio-common/_itoa.h: Define _itoa and _fitoa for 64-bit platforms.
+	* malloc/mtrace.c: Revert last change.
+	* posix/wordexp.c: Likewise.
+
+2007-01-24  Jakub Jelinek  <jakub@xxxxxxxxxx>
+
+	* sysdeps/i386/bits/byteswap.h (__bswap_32): Add __nocona__, __core2__
+	and __geode__ to the list of i486+ CPUs.
+	* sysdeps/x86_64/bits/byteswap.h (__bswap_32): Likewise.
+
+2007-01-23  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* stdio-common/_itoa.c: Include <limits.h>.
+	* stdio-common/_itowa.c: Likewise.
+
+2007-01-22  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* stdio-common/_itowa.c: Don't compile _itowa for 64-bit
+	platforms.
+	* stdio-common/_itoa.c: Don't compile in _itoa and _fitoa for
+	64-bit platforms.
+	* malloc/mtrace.c (tr_where): Use _fitoa_word instead of _fitoa if
+	possible.
+	* posix/wordexp.c (parse_arith): Use _itoa_word instead of _itoa
+	if possible.
+
+	[BZ #3902]
+	* stdio-common/_itoa.c (_itoa): Make sure at least a zero is emitted.
+	* stdio-common/Makefile (tests): Add bug17.
+	* stdio-common/bug17.c: New file.
+
+2007-01-19  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* iconvdata/brf.c: New file.
+	* iconvdata/testdata/BRF: New file.
+	* iconvdata/testdata/BRF..UTF8: New file.
+	Contributed by Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>.
+	* iconvdata/Makefile: Add rules to build BRF.
+	* iconvdata/TESTS: Add BRF entry.
+	* iconvdata/gconv-modules: Likewise.
+	* iconvdata/tst-tables.sh: Likewise.
+
+2007-01-18  Anton Nikishaev  <anton.nik@xxxxxxxxx>
+
+	* wcsmbs/wchar.h (wcstoll): Fix comment, function returns value of
+	type `long long int', not `long int'.
+	(wcstoq): Likewise.
+
+2007-01-18  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* scripts/gen-as-const.awk: Add cast to long to avoid int promotion
+	of values on 64-bit platforms which are too large.
+
+2007-01-12  Steven Munroe  <sjmunroe@xxxxxxxxxx>
+	    Joe Kerian  <jkerian@xxxxxxxxxxxxx>
+
+	[BZ #2749]
+	* sysdeps/ieee754/ldbl-128ibm/s_copysignl.c: Include
+	<math_ldbl_opt.h>.  Remove weak_alias.  Use long_double_symbol macro.
+	(__copysignl): Use signbit() for comparison.
+	* sysdeps/ieee754/ldbl-128ibm/s_fabsl.c (__fabsl): Correct parms for
+	SET_LDOUBLE_WORDS64.
+
+	[BZ #2423, #2749]
+	* sysdeps/ieee754/ldbl-128ibm/s_ceill.c: Don't include <fenv_libc.h>.
+	(__ceill): Remove calls to fegetround(), fesetround().
+	* sysdeps/ieee754/ldbl-128ibm/s_floorl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_roundl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_truncl.c: Likewise.
+
+2007-01-17  Jakub Jelinek  <jakub@xxxxxxxxxx>
+
+	* nscd/nscd_getserv_r.c (nscd_getserv_r): Fix pastos.
+
+	* sysdeps/unix/sysv/linux/getdents.c (offsetof): Remove.
+
+2007-01-17  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/unix/sysv/linux/fatal-prepare.h: Use PTHFCT_CALL to
+	demangle pointer.
+	* csu/libc-start.c: Likewise.
+
+2007-01-16  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/posix/system.c: Remove NO_WAITPID support, it cannot
+	really work anyway.
+
+2007-01-15  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* nscd/connections.c (servinfo): Renamed to reqinfo.  Change all
+	users.
+	(handle_request): Remove unnecessary tests.
+
+	* nscd/cache.c (cache_add): Record the failure to add to the cache.
+
+2007-01-15  Jakub Jelinek  <jakub@xxxxxxxxxx>
+
+	* soft-fp/op-common.h (FP_TRUNC): When truncating a NaN, clear
+	workbits in semi-raw fraction.
+
+	* math/test-misc.c: Add new tests.
+
+2007-01-14  Steven Munroe  <sjmunroe@xxxxxxxxxx>
+
+	* math/basic-test.c: Include test-skeleton.c.
+	(TEST_TRUNC): Define.
+	(truncdfsf_test, trunctfsf_test, trunctfdf_test): New.
+	(main): Rename to ...
+	(do_test): ...this.  Run new tests.
+	(TEST_FUNCTION): Define.
+
+2006-10-05  Steven Munroe  <sjmunroe@xxxxxxxxxx>
+	    Joe Kerian  <jkerian@xxxxxxxxxxxxx>
+
+	[BZ #2749]
+	* soft-fp/op-4.h (__FP_FRAC_SUB_3, __FP_FRAC_SUB_4): Correct borrow
+	handling for high words.
+	* soft-fp/op-common.h (_FP_OVERFLOW_SEMIRAW): Always set inexact
+	and overflow for infinity.
+
+2007-01-15  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* nscd/connections.c (handle_request): Add a __builtin_expect.
+
+	* nscd/connections.c (serv2db): Change type into structure which
+	also says whether this is a request for data.  Renamed to
+	servinfo.  All users changed.
+	(handle_request): Much simpler test whether we should search the cache.
+
+	* nscd/connections.c (handle_request): Fix thinko in selinux test
+	invocation.
+
+	* sysdeps/generic/ldsodefs.h: Define DL_LOOKUP_SCOPE_LOCK.
+	* elf/dl-lookup.c (add_dependency): If scope map is locked, unlock
+	it before getting dl_load_lock and then relock.
+	(_dl_lookup_symbol_x): Pass flags to add_dependency.
+	When rerunning _dl_lookup_symbol_x, compute symbol_scope again in
+	case we unlocked the scope.
+	* elf/dl-runtime.c (_dl_fixup): Pass DL_LOOKUP_SCOPE_LOCK to
+	_dl_lookup_symbol_x in case we locked the scope.
+	(_dl_profile_fixup): Likewise.
+	* elf/dl-sym.c (do_sym): In flags passed to call_dl_lookup, also
+	set DL_LOOKUP_SCOPE_LOCK.
+
 2007-01-13  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* inet/Makefile: Define CFLAGS-getsrvbynm_r.c and

Modified: trunk/libc/NEWS
==============================================================================
--- trunk/libc/NEWS (original)
+++ trunk/libc/NEWS Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2007-1-13
+GNU C Library NEWS -- history of user-visible changes.  2007-2-1
 Copyright (C) 1992-2006, 2007 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -8,6 +8,8 @@
 Version 2.6
 
 * New Linux interfaces: epoll_pwait.
+
+* New generic interfaces: strerror_l.
 
 * nscd can now cache the services database.   Implemented by Ulrich Drepper.
 

Modified: trunk/libc/csu/libc-start.c
==============================================================================
--- trunk/libc/csu/libc-start.c (original)
+++ trunk/libc/csu/libc-start.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -225,7 +225,7 @@
     {
       /* Remove the thread-local data.  */
 # ifdef SHARED
-      __libc_pthread_functions.ptr__nptl_deallocate_tsd ();
+      PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
 # else
       extern void __nptl_deallocate_tsd (void) __attribute ((weak));
       __nptl_deallocate_tsd ();
@@ -235,7 +235,8 @@
 	 terminate the entire process.  */
       result = 0;
 # ifdef SHARED
-      unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads;
+      unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
+      PTR_DEMANGLE (ptr);
 # else
       extern unsigned int __nptl_nthreads __attribute ((weak));
       unsigned int *const ptr = &__nptl_nthreads;

Modified: trunk/libc/elf/dl-lookup.c
==============================================================================
--- trunk/libc/elf/dl-lookup.c (original)
+++ trunk/libc/elf/dl-lookup.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Look up a symbol in the loaded objects.
-   Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
 #include <ldsodefs.h>
 #include <dl-hash.h>
 #include <dl-machine.h>
+#include <sysdep-cancel.h>
 #include <bits/libc-lock.h>
 #include <tls.h>
 
@@ -85,7 +86,7 @@
 /* Add extra dependency on MAP to UNDEF_MAP.  */
 static int
 internal_function
-add_dependency (struct link_map *undef_map, struct link_map *map)
+add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
 {
   struct link_map **list;
   struct link_map *runp;
@@ -98,8 +99,18 @@
   if (undef_map == map)
     return 0;
 
-  /* Make sure nobody can unload the object while we are at it.  */
-  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  /* Make sure nobody can unload the object while we are at it.
+     If we hold a scope lock drop it now to avoid ABBA locking problems.  */
+  if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0 && !RTLD_SINGLE_THREAD_P)
+    {
+      __rtld_mrlock_unlock (undef_map->l_scope_lock);
+
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+      __rtld_mrlock_lock (undef_map->l_scope_lock);
+    }
+  else
+    __rtld_lock_lock_recursive (GL(dl_load_lock));
 
   /* Avoid references to objects which cannot be unloaded anyway.  */
   if (map->l_type != lt_loaded
@@ -226,9 +237,10 @@
 
   bump_num_relocations ();
 
-  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
-     up a versioned symbol.  */
-  assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
+  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY and DL_LOOKUP_SCOPE_LOCK
+     is allowed if we look up a versioned symbol.  */
+  assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY
+					| DL_LOOKUP_SCOPE_LOCK)) == 0);
 
   size_t i = 0;
   if (__builtin_expect (skip_map != NULL, 0))
@@ -338,12 +350,13 @@
 	 runtime lookups.  */
       && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
       /* Add UNDEF_MAP to the dependencies.  */
-      && add_dependency (undef_map, current_value.m) < 0)
+      && add_dependency (undef_map, current_value.m, flags) < 0)
       /* Something went wrong.  Perhaps the object we tried to reference
 	 was just removed.  Try finding another definition.  */
       return _dl_lookup_symbol_x (undef_name, undef_map, ref,
-				  symbol_scope, version, type_class,
-				  flags, skip_map);
+				  (flags & DL_LOOKUP_SCOPE_LOCK) == 0
+				  ? symbol_scope : undef_map->l_scope, version,
+				  type_class, flags, skip_map);
 
   /* The object is used.  */
   current_value.m->l_used = 1;

Modified: trunk/libc/elf/dl-minimal.c
==============================================================================
--- trunk/libc/elf/dl-minimal.c (original)
+++ trunk/libc/elf/dl-minimal.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Minimal replacements for basic facilities used in the dynamic linker.
-   Copyright (C) 1995-1998,2000-2002,2004,2005,2006
+   Copyright (C) 1995-1998,2000-2002,2004-2006,2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -283,6 +283,7 @@
 }
 
 
+#undef _itoa
 /* We always use _itoa instead of _itoa_word in ld.so since the former
    also has to be present and it is never about speed when these
    functions are used.  */

Modified: trunk/libc/elf/dl-runtime.c
==============================================================================
--- trunk/libc/elf/dl-runtime.c (original)
+++ trunk/libc/elf/dl-runtime.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* On-demand PLT fixup for shared objects.
-   Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -93,14 +93,20 @@
 	    version = NULL;
 	}
 
+      /* We need to keep the scope around so do some locking.  This is
+	 not necessary for objects which cannot be unloaded or when
+	 we are not using any threads (yet).  */
+      int flags = DL_LOOKUP_ADD_DEPENDENCY;
       if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
-	__rtld_mrlock_lock (l->l_scope_lock);
-
-      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
-				    l->l_scope, version, ELF_RTYPE_CLASS_PLT,
-				    DL_LOOKUP_ADD_DEPENDENCY, NULL);
-
-      if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
+	{
+	  __rtld_mrlock_lock (l->l_scope_lock);
+	  flags |= DL_LOOKUP_SCOPE_LOCK;
+	}
+
+      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
+				    version, ELF_RTYPE_CLASS_PLT, flags, NULL);
+
+      if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
 	__rtld_mrlock_unlock (l->l_scope_lock);
 
       /* Currently result contains the base load address (or link map)
@@ -181,15 +187,21 @@
 		version = NULL;
 	    }
 
+	  /* We need to keep the scope around so do some locking.  This is
+	     not necessary for objects which cannot be unloaded or when
+	     we are not using any threads (yet).  */
+	  int flags = DL_LOOKUP_ADD_DEPENDENCY;
 	  if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
-	    __rtld_mrlock_lock (l->l_scope_lock);
-
-	  result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym,
-					l->l_scope, version,
-					ELF_RTYPE_CLASS_PLT,
-					DL_LOOKUP_ADD_DEPENDENCY, NULL);
-
-	  if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
+	    {
+	      __rtld_mrlock_lock (l->l_scope_lock);
+	      flags |= DL_LOOKUP_SCOPE_LOCK;
+	    }
+
+	  result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
+					&defsym, l->l_scope, version,
+					ELF_RTYPE_CLASS_PLT, flags, NULL);
+
+	  if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
 	    __rtld_mrlock_unlock (l->l_scope_lock);
 
 	  /* Currently result contains the base load address (or link map)

Modified: trunk/libc/elf/dl-sym.c
==============================================================================
--- trunk/libc/elf/dl-sym.c (original)
+++ trunk/libc/elf/dl-sym.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Look up a symbol in a shared object loaded by `dlopen'.
-   Copyright (C) 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
+   Copyright (C) 1999-2002,2004,2006,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -126,7 +126,7 @@
 	  args.name = name;
 	  args.map = match;
 	  args.vers = vers;
-	  args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY;
+	  args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_SCOPE_LOCK;
 	  args.refp = &ref;
 
 	  const char *objname;

Modified: trunk/libc/iconvdata/Makefile
==============================================================================
--- trunk/libc/iconvdata/Makefile (original)
+++ trunk/libc/iconvdata/Makefile Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-# Copyright (C) 1997-2004,2005,2006 Free Software Foundation, Inc.
+# Copyright (C) 1997-2004,2005,2006,2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -58,7 +58,7 @@
 	   IBM1142 IBM1143 IBM1144 IBM1145 IBM1146 IBM1147 IBM1148 	 \
 	   IBM1149 IBM1166 IBM1167 IBM4517 IBM4899 IBM4909 IBM4971 	 \
 	   IBM5347 IBM9030 IBM9066 IBM9448 IBM12712 IBM16804             \
-	   IBM1364 IBM1371 IBM1388 IBM1390 IBM1399 ISO_11548-1 MIK
+	   IBM1364 IBM1371 IBM1388 IBM1390 IBM1399 ISO_11548-1 MIK BRF
 
 modules.so := $(addsuffix .so, $(modules))
 
@@ -196,7 +196,8 @@
 	      ibm9030.c ibm9030.h ibm9066.c ibm9066.h ibm9448.c ibm9448.h   \
 	      ibm12712.c ibm12712.h ibm16804.c ibm16804.h                   \
 	      ibm1364.c ibm1364.h ibm1371.c ibm1371.h ibm1388.c ibm1388.h   \
-	      ibm1390.c ibm1390.h ibm1399.c ibm1399.h iso_11548-1.c mik.c
+	      ibm1390.c ibm1390.h ibm1399.c ibm1399.h iso_11548-1.c mik.c   \
+	      brf.c
 
 # We build the transformation modules only when we build shared libs.
 ifeq (yes,$(build-shared))
@@ -237,7 +238,7 @@
 			iso8859-13 iso8859-14 iso8859-15 mac-uk sami-ws2   \
 			iso-ir-197 tis-620 koi8-u ibm874 cp10007 koi8-t	   \
 			georgian-ps georgian-academy iso-ir-209 mac-sami   \
-			iso8859-11 ibm866nav pt154 rk1048 mik
+			iso8859-11 ibm866nav pt154 rk1048 mik brf
 
 gen-special-modules := iso8859-7jp
 

Modified: trunk/libc/iconvdata/TESTS
==============================================================================
--- trunk/libc/iconvdata/TESTS (original)
+++ trunk/libc/iconvdata/TESTS Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 # Available tests for iconv(1) (and therefore iconv(3)) in GNU libc.
-# Copyright (C) 1998-2002, 2005 Free Software Foundation, Inc.
+# Copyright (C) 1998-2002, 2005, 2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1998.
 #
@@ -166,3 +166,4 @@
 IBM1399			IBM1399			N	UTF8
 ISO_11548-1		ISO_11548-1		-	UTF8
 MIK			MIK			Y	UTF8
+BRF			BRF			-	UTF8

Modified: trunk/libc/iconvdata/gconv-modules
==============================================================================
--- trunk/libc/iconvdata/gconv-modules (original)
+++ trunk/libc/iconvdata/gconv-modules Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 # GNU libc iconv configuration.
-# Copyright (C) 1997-2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 1997-2004, 2005, 2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -1907,3 +1907,7 @@
 #	from			to			module		cost
 module	MIK//			INTERNAL		MIK		1
 module	INTERNAL		MIK//			MIK		1
+
+#	from			to			module		cost
+module	BRF//			INTERNAL		BRF		1
+module	INTERNAL		BRF//			BRF		1

Modified: trunk/libc/iconvdata/tst-tables.sh
==============================================================================
--- trunk/libc/iconvdata/tst-tables.sh (original)
+++ trunk/libc/iconvdata/tst-tables.sh Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2000,2001,2002,2003,2004,2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 # Contributed by Bruno Haible <haible@xxxxxxxxxxxxxx>, 2000.
 #
@@ -208,6 +208,7 @@
   PT154
   RK1048
   MIK
+  BRF
   #
   # Multibyte encodings come here
   #

Modified: trunk/libc/include/locale.h
==============================================================================
--- trunk/libc/include/locale.h (original)
+++ trunk/libc/include/locale.h Mon Feb  5 09:59:45 2007
@@ -4,6 +4,7 @@
 extern __typeof (uselocale) __uselocale;
 
 libc_hidden_proto (setlocale)
+libc_hidden_proto (__uselocale)
 
 /* This has to be changed whenever a new locale is defined.  */
 #define __LC_LAST	13

Modified: trunk/libc/locale/uselocale.c
==============================================================================
--- trunk/libc/locale/uselocale.c (original)
+++ trunk/libc/locale/uselocale.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* uselocale -- fetch and set the current per-thread locale
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -70,4 +70,5 @@
 
   return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc;
 }
+libc_hidden_def (__uselocale)
 weak_alias (__uselocale, uselocale)

Modified: trunk/libc/localedata/ChangeLog
==============================================================================
--- trunk/libc/localedata/ChangeLog (original)
+++ trunk/libc/localedata/ChangeLog Mon Feb  5 09:59:45 2007
@@ -1,3 +1,8 @@
+2007-01-19  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* charmaps/BRF: New file.
+	Contributed by Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>.
+
 2006-12-05  Jakub Jelinek  <jakub@xxxxxxxxxx>
 
 	* locales/cs_CZ (LC_TIME): Change d_fmt to %e.%m.%Y from %-d.%-m.%Y.

Modified: trunk/libc/math/basic-test.c
==============================================================================
--- trunk/libc/math/basic-test.c (original)
+++ trunk/libc/math/basic-test.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@xxxxxxx>, 1999.
 
@@ -44,7 +44,7 @@
 									      \
   zero_var = 0.0;							      \
   one_var = 1.0;							      \
-  NaN_var = zero_var/zero_var;						      \
+  NaN_var = zero_var / zero_var;					      \
   Inf_var = one_var / zero_var;						      \
 									      \
   (void) &zero_var;							      \
@@ -103,21 +103,51 @@
   check (#FLOAT " isinf (-HUGE_VALx) == -1", isinf (x1) == -1);		      \
 }
 
+#define TEST_TRUNC(NAME, FLOAT, DOUBLE) \
+void									      \
+NAME (void)								      \
+{									      \
+  volatile DOUBLE Inf_var, NaN_var, zero_var, one_var;			      \
+  FLOAT x1, x2;								      \
+									      \
+  zero_var = 0.0;							      \
+  one_var = 1.0;							      \
+  NaN_var = zero_var / zero_var;					      \
+  Inf_var = one_var / zero_var;						      \
+									      \
+  (void) &NaN_var;							      \
+  (void) &Inf_var;							      \
+									      \
+  x1 = (FLOAT) NaN_var;							      \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") NaN", isnan (x1) != 0);	      \
+  x2 = (FLOAT) Inf_var;							      \
+  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") Inf", isinf (x2) != 0);	      \
+}
+
 TEST_FUNC (float_test, float, nanf, FLT_EPSILON, HUGE_VALF)
 TEST_FUNC (double_test, double, nan, DBL_EPSILON, HUGE_VAL)
+TEST_TRUNC (truncdfsf_test, float, double)
 #ifndef NO_LONG_DOUBLE
 TEST_FUNC (ldouble_test, long double, nanl, LDBL_EPSILON, HUGE_VALL)
+TEST_TRUNC (trunctfsf_test, float, long double)
+TEST_TRUNC (trunctfdf_test, double, long double)
 #endif
 
 int
-main (void)
+do_test (void)
 {
   float_test ();
   double_test ();
+  truncdfsf_test();
 
 #ifndef NO_LONG_DOUBLE
   ldouble_test ();
+  trunctfsf_test();
+  trunctfdf_test();
 #endif
 
   return errors != 0;
 }
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

Modified: trunk/libc/math/test-misc.c
==============================================================================
--- trunk/libc/math/test-misc.c (original)
+++ trunk/libc/math/test-misc.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Miscellaneous tests which don't fit anywhere else.
-   Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2004, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -44,7 +44,6 @@
       }
   }
 
-# if __GNUC__ >= 3 || __GNUC_MINOR__ >= 96
   {
     long double x;
     long double m;
@@ -52,17 +51,17 @@
     int e;
     int i;
 
-#  if LDBL_MANT_DIG == 64
+# if LDBL_MANT_DIG == 64
     m = 0xf.fffffffffffffffp-4L;
-#  elif LDBL_MANT_DIG == 106
+# elif LDBL_MANT_DIG == 106
     /* This has to match the mantissa of LDBL_MAX which actually does have a
        missing bit in the middle.  */
     m = 0x1.fffffffffffff7ffffffffffff8p-1L;
-#  elif LDBL_MANT_DIG == 113
+# elif LDBL_MANT_DIG == 113
     m = 0x1.ffffffffffffffffffffffffffffp-1L;
-#  else
-#   error "Please adjust"
-#  endif
+# else
+#  error "Please adjust"
+# endif
 
     for (i = LDBL_MAX_EXP, x = LDBL_MAX; i >= LDBL_MIN_EXP; --i, x /= 2.0L)
       {
@@ -106,9 +105,8 @@
       }
 
   }
-# endif
-
-#if 0
+
+# if 0
   {
     int e;
     long double r = frexpl (LDBL_MIN * LDBL_EPSILON, &e);
@@ -126,7 +124,7 @@
 	result = 1;
       }
   }
-#endif
+# endif
 #endif
 
   {
@@ -1183,5 +1181,59 @@
     }
 #endif
 
+  volatile float f1 = FLT_MAX;
+  volatile float f2 = FLT_MAX / 2;
+  (void) &f1;
+  (void) &f2;
+  feclearexcept (FE_ALL_EXCEPT);
+  f2 += f1;
+  int fe = fetestexcept (FE_ALL_EXCEPT);
+  if (fe != (FE_OVERFLOW | FE_INEXACT))
+    {
+      printf ("float overflow test failed: %x\n", fe);
+      result = 1;
+    }
+
+  volatile double d1 = DBL_MAX;
+  volatile double d2 = DBL_MAX / 2;
+  (void) &d1;
+  (void) &d2;
+  feclearexcept (FE_ALL_EXCEPT);
+  d2 += d1;
+  fe = fetestexcept (FE_ALL_EXCEPT);
+  if (fe != (FE_OVERFLOW | FE_INEXACT))
+    {
+      printf ("double overflow test failed: %x\n", fe);
+      result = 1;
+    }
+
+#ifndef NO_LONG_DOUBLE
+  volatile long double ld1 = LDBL_MAX;
+  volatile long double ld2 = LDBL_MAX / 2;
+  (void) &ld1;
+  (void) &ld2;
+  feclearexcept (FE_ALL_EXCEPT);
+  ld2 += ld1;
+  fe = fetestexcept (FE_ALL_EXCEPT);
+  if (fe != (FE_OVERFLOW | FE_INEXACT))
+    {
+      printf ("long double overflow test failed: %x\n", fe);
+      result = 1;
+    }
+#endif
+
+#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG == 113
+  volatile long double ld3 = 0x1.0000000000010000000100000001p+1;
+  volatile long double ld4 = 0x1.0000000000000000000000000001p+1;
+  (void) &ld3;
+  (void) &ld4;
+  ld3 -= ld4;
+  if (ld3 != 0x1.0p-47)
+    {
+      printf ("long double subtraction test failed %.28La\n", ld3);
+      result = 1;
+    }
+#endif
+
   return result;
 }

Modified: trunk/libc/misc/hsearch_r.c
==============================================================================
--- trunk/libc/misc/hsearch_r.c (original)
+++ trunk/libc/misc/hsearch_r.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1995,1996,1997,2002,2005 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1995-1997,2002,2005,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxxxxxx>, 1993.
 
@@ -110,9 +110,8 @@
       return;
     }
 
-  if (htab->table != NULL)
-    /* free used memory */
-    free (htab->table);
+  /* Free used memory.  */
+  free (htab->table);
 
   /* the sign for an existing table is an value != NULL in htable */
   htab->table = NULL;

Modified: trunk/libc/nptl/ChangeLog
==============================================================================
--- trunk/libc/nptl/ChangeLog (original)
+++ trunk/libc/nptl/ChangeLog Mon Feb  5 09:59:45 2007
@@ -1,3 +1,26 @@
+2007-01-18  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* tst-initializers1.c: We want to test the initializers as seen
+	outside of libc, so undefined _LIBC.
+
+	* pthread_join.c (cleanup): Avoid warning.
+
+2007-01-17  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+	(__lll_timedwait_tid): Add unwind info.
+
+	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Don't just copy the
+	function table, mangle the pointers.
+	* sysdeps/pthread/pthread-functions.h: Define PTHFCT_CALL.
+	* forward.c: Use PTHFCT_CALL and __libc_pthread_functions_init.
+	* sysdeps/pthread/bits/libc-lock.h: When using __libc_pthread_functions
+	demangle pointers before use.
+	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Use PTHFCT_CALL to
+	demangle pointer.
+	* sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise.
+	* sysdeps/pthread/setxid.h: Likewise.
+
 2007-01-12  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* tst-rwlock7.c: Show some more information in case of correct

Modified: trunk/libc/nptl/forward.c
==============================================================================
--- trunk/libc/nptl/forward.c (original)
+++ trunk/libc/nptl/forward.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -29,16 +29,17 @@
 
 /* Pointers to the libc functions.  */
 struct pthread_functions __libc_pthread_functions attribute_hidden;
+int __libc_pthread_functions_init attribute_hidden;
 
 
 #define FORWARD2(name, rettype, decl, params, defaction) \
 rettype									      \
 name decl								      \
 {									      \
-  if (__libc_pthread_functions.ptr_##name == NULL)			      \
+  if (!__libc_pthread_functions_init)					      \
     defaction;								      \
 									      \
-  return __libc_pthread_functions.ptr_##name params;			      \
+  return PTHFCT_CALL (ptr_##name, params);				      \
 }
 
 #define FORWARD(name, decl, params, defretval) \

Modified: trunk/libc/nptl/pthread_join.c
==============================================================================
--- trunk/libc/nptl/pthread_join.c (original)
+++ trunk/libc/nptl/pthread_join.c Mon Feb  5 09:59:45 2007
@@ -30,8 +30,8 @@
   /* If we already changed the waiter ID, reset it.  The call cannot
      fail for any reason but the thread not having done that yet so
      there is no reason for a loop.  */
-  atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
-					THREAD_SELF);
+  (void) atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
+					       THREAD_SELF);
 }
 
 

Modified: trunk/libc/nptl/sysdeps/pthread/bits/libc-lock.h
==============================================================================
--- trunk/libc/nptl/sysdeps/pthread/bits/libc-lock.h (original)
+++ trunk/libc/nptl/sysdeps/pthread/bits/libc-lock.h Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* libc-internal interface for mutex locks.  NPTL version.
-   Copyright (C) 1996-2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1996-2003, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -150,13 +150,17 @@
 
 /* Call thread functions through the function pointer table.  */
 #if defined SHARED && !defined NOT_IN_libc
-# define PTF(NAME) __libc_pthread_functions.ptr_##NAME
+# define PTFAVAIL(NAME) __libc_pthread_functions_init
 # define __libc_ptf_call(FUNC, ARGS, ELSE) \
-  (PTF(FUNC) != NULL ? PTF(FUNC) ARGS : ELSE)
-#else
-# define PTF(NAME) NAME
+  (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE)
+# define __libc_ptf_call_always(FUNC, ARGS) \
+  PTHFCT_CALL (ptr_##FUNC, ARGS)
+#else
+# define PTFAVAIL(NAME) (NAME != NULL)
 # define __libc_ptf_call(FUNC, ARGS, ELSE) \
   __libc_maybe_call (FUNC, ARGS, ELSE)
+# define __libc_ptf_call_always(FUNC, ARGS) \
+  FUNC ARGS
 #endif
 
 
@@ -353,8 +357,9 @@
 /* Call handler iff the first call.  */
 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
   do {									      \
-    if (PTF(__pthread_once) != NULL)					      \
-      PTF(__pthread_once) (&(ONCE_CONTROL), INIT_FUNCTION);		      \
+    if (PTFAVAIL (__pthread_once))					      \
+      __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL),		      \
+					       INIT_FUNCTION));		      \
     else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \
       INIT_FUNCTION ();							      \
       (ONCE_CONTROL) |= 2;						      \
@@ -380,9 +385,10 @@
   { struct _pthread_cleanup_buffer _buffer;				      \
     int _avail;								      \
     if (DOIT) {								      \
-      _avail = PTF(_pthread_cleanup_push_defer) != NULL;		      \
+      _avail = PTFAVAIL (_pthread_cleanup_push_defer);			      \
       if (_avail) {							      \
-	PTF(_pthread_cleanup_push_defer) (&_buffer, FCT, ARG);		      \
+	__libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT,  \
+							      ARG));	      \
       } else {								      \
 	_buffer.__routine = (FCT);					      \
 	_buffer.__arg = (ARG);						      \
@@ -394,7 +400,7 @@
 /* End critical region with cleanup.  */
 #define __libc_cleanup_region_end(DOIT) \
     if (_avail) {							      \
-      PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT);		      \
+      __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
     } else if (DOIT)							      \
       _buffer.__routine (_buffer.__arg);				      \
   }
@@ -402,7 +408,7 @@
 /* Sometimes we have to exit the block in the middle.  */
 #define __libc_cleanup_end(DOIT) \
     if (_avail) {							      \
-      PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT);		      \
+      __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
     } else if (DOIT)							      \
       _buffer.__routine (_buffer.__arg)
 

Modified: trunk/libc/nptl/sysdeps/pthread/pthread-functions.h
==============================================================================
--- trunk/libc/nptl/sysdeps/pthread/pthread-functions.h (original)
+++ trunk/libc/nptl/sysdeps/pthread/pthread-functions.h Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2003.
 
@@ -23,6 +23,7 @@
 #include <pthread.h>
 #include <setjmp.h>
 #include <internaltypes.h>
+#include <sysdep.h>
 
 struct xid_command;
 
@@ -100,5 +101,12 @@
 
 /* Variable in libc.so.  */
 extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+extern int __libc_pthread_functions_init attribute_hidden;
+
+#define PTHFCT_CALL(fct, params) \
+  ({ __typeof (__libc_pthread_functions.fct) __p;			      \
+     __p = __libc_pthread_functions.fct;				      \
+     PTR_DEMANGLE (__p);						      \
+     __p params; })
 
 #endif	/* pthread-functions.h */

Modified: trunk/libc/nptl/sysdeps/pthread/setxid.h
==============================================================================
--- trunk/libc/nptl/sysdeps/pthread/setxid.h (original)
+++ trunk/libc/nptl/sysdeps/pthread/setxid.h Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -33,13 +33,12 @@
 # define INLINE_SETXID_SYSCALL(name, nr, args...) \
   ({									\
     int __result;							\
-    if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid	\
-			  != NULL, 0))					\
+    if (__builtin_expect (__libc_pthread_functions_init, 0))		\
       {									\
 	struct xid_command __cmd;					\
 	__cmd.syscall_no = __NR_##name;					\
 	__SETXID_##nr (__cmd, args);					\
-	__result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd);	\
+	__result = PTHFCT_CALL (ptr__nptl_setxid, (&__cmd));		\
 	}								\
     else								\
       __result = INLINE_SYSCALL (name, nr, args);			\

Modified: trunk/libc/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c
==============================================================================
--- trunk/libc/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c (original)
+++ trunk/libc/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Clean up stack frames unwound by longjmp.  Linux version.
-   Copyright (C) 1995, 1997, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -29,11 +29,11 @@
 _longjmp_unwind (jmp_buf env, int val)
 {
 #ifdef SHARED
-# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto
+  if (__libc_pthread_functions_init)
+    PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf,
+					      CURRENT_STACK_FRAME));
 #else
-# define fptr __pthread_cleanup_upto
+  if (__pthread_cleanup_upto != NULL)
+    __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME);
 #endif
-
-  if (fptr != NULL)
-    fptr (env->__jmpbuf, CURRENT_STACK_FRAME);
 }

Modified: trunk/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
==============================================================================
--- trunk/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c (original)
+++ trunk/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <pthreadP.h>
 #include <bits/libc-lock.h>
+#include <sysdep.h>
 
 
 #ifdef TLS_MULTIPLE_THREADS_IN_TCB
@@ -46,11 +47,29 @@
   __register_atfork (NULL, NULL, reclaim, NULL);
 
 #ifdef SHARED
-  /* We copy the content of the variable pointed to by the FUNCTIONS
-     parameter to one in libc.so since this means access to the array
-     can be done with one memory access instead of two.  */
-  memcpy (&__libc_pthread_functions, functions,
-	  sizeof (__libc_pthread_functions));
+  /* Copy the function pointers into an array in libc.  This enables
+     access with just one memory reference but moreso, it prevents
+     hijacking the function pointers with just one pointer change.  We
+     "encrypt" the function pointers since we cannot write-protect the
+     array easily enough.  */
+  union ptrhack
+  {
+    struct pthread_functions pf;
+    void *parr[1];
+  } const *src;
+  union ptrhack *dest;
+# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *))
+
+  src = (const void *) functions;
+  dest = (void *) &__libc_pthread_functions;
+
+  for (size_t cnt = 0; cnt < NPTRS; ++cnt)
+    {
+      void *p = src->parr[cnt];
+      PTR_MANGLE (p);
+      dest->parr[cnt] = p;
+    }
+  __libc_pthread_functions_init = 1;
 #endif
 
 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
@@ -61,7 +80,7 @@
 #ifdef SHARED
 libc_freeres_fn (freeres_libptread)
 {
-  if (__libc_pthread_functions.ptr_freeres != NULL)
-    __libc_pthread_functions.ptr_freeres ();
+  if (__libc_pthread_functions_init)
+    PTHFCT_CALL (ptr_freeres, ());
 }
 #endif

Modified: trunk/libc/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c
==============================================================================
--- trunk/libc/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c (original)
+++ trunk/libc/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c Mon Feb  5 09:59:45 2007
@@ -1,5 +1,5 @@
 /* Clean up stack frames unwound by longjmp.  Linux/s390 version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -28,14 +28,13 @@
 void
 _longjmp_unwind (jmp_buf env, int val)
 {
-#ifdef SHARED
-# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto
-#else
-# define fptr __pthread_cleanup_upto
-#endif
-
   unsigned char local_var;
 
-  if (fptr != NULL)
-    fptr (env->__jmpbuf, &local_var);
+#ifdef SHARED
+  if (__libc_pthread_functions_init)
+    PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, &local_var));
+#else
+  if (__pthread_cleanup_upto != NULL)
+    __pthread_cleanup_upto (env->__jmpbuf, &local_var);
+#endif
 }

Modified: trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
==============================================================================
--- trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (original)
+++ trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -269,13 +269,19 @@
 	.hidden	__lll_timedwait_tid
 	.align	16
 __lll_timedwait_tid:
+	cfi_startproc
 	pushq	%r12
+	cfi_adjust_cfa_offset(8)
 	pushq	%r13
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(%r12, -16)
+	cfi_offset(%r13, -24)
 
 	movq	%rdi, %r12
 	movq	%rsi, %r13
 
 	subq	$16, %rsp
+	cfi_adjust_cfa_offset(16)
 
 	/* Get current time.  */
 2:	movq	%rsp, %rdi
@@ -319,14 +325,21 @@
 4:	xorl	%eax, %eax
 
 8:	addq	$16, %rsp
+	cfi_adjust_cfa_offset(-16)
 	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r13)
 	popq	%r12
-	retq
-
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(%r12)
+	retq
+
+	cfi_adjust_cfa_offset(32)
 1:	cmpq	$-ETIMEDOUT, %rax
 	jne	2b
 
 6:	movl	$ETIMEDOUT, %eax
 	jmp	8b
+	cfi_endproc
 	.size	__lll_timedwait_tid,.-__lll_timedwait_tid
 #endif

Modified: trunk/libc/nptl/tst-initializers1.c
==============================================================================
--- trunk/libc/nptl/tst-initializers1.c (original)
+++ trunk/libc/nptl/tst-initializers1.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@xxxxxxxxxx>, 2005.
 
@@ -16,6 +16,9 @@
    License along with the GNU C Library; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
+
+/* We test the code undef conditions outside of glibc.  */
+#undef _LIBC
 
 #include <pthread.h>
 

Modified: trunk/libc/nscd/cache.c
==============================================================================
--- trunk/libc/nscd/cache.c (original)
+++ trunk/libc/nscd/cache.c Mon Feb  5 09:59:45 2007
@@ -153,7 +153,10 @@
   newp = mempool_alloc (table, sizeof (struct hashentry));
   /* If we cannot allocate memory, just do not do anything.  */
   if (newp == NULL)
-    return -1;
+    {
+      ++table->head->addfailed;
+      return -1;
+    }
 
   newp->type = type;
   newp->first = first;

Modified: trunk/libc/nscd/connections.c
==============================================================================
--- trunk/libc/nscd/connections.c (original)
+++ trunk/libc/nscd/connections.c Mon Feb  5 09:59:45 2007
@@ -181,24 +181,31 @@
 
 
 /* Mapping of request type to database.  */
-static struct database_dyn *const serv2db[LASTREQ] =
-{
-  [GETPWBYNAME] = &dbs[pwddb],
-  [GETPWBYUID] = &dbs[pwddb],
-  [GETGRBYNAME] = &dbs[grpdb],
-  [GETGRBYGID] = &dbs[grpdb],
-  [GETHOSTBYNAME] = &dbs[hstdb],
-  [GETHOSTBYNAMEv6] = &dbs[hstdb],
-  [GETHOSTBYADDR] = &dbs[hstdb],
-  [GETHOSTBYADDRv6] = &dbs[hstdb],
-  [GETFDPW] = &dbs[pwddb],
-  [GETFDGR] = &dbs[grpdb],
-  [GETFDHST] = &dbs[hstdb],
-  [GETAI] = &dbs[hstdb],
-  [INITGROUPS] = &dbs[grpdb],
-  [GETSERVBYNAME] = &dbs[servdb],
-  [GETSERVBYPORT] = &dbs[servdb],
-  [GETFDSERV] = &dbs[servdb]
+static struct
+{
+  bool data_request;
+  struct database_dyn *db;
+} const reqinfo[LASTREQ] =
+{
+  [GETPWBYNAME] = { true, &dbs[pwddb] },
+  [GETPWBYUID] = { true, &dbs[pwddb] },
+  [GETGRBYNAME] = { true, &dbs[grpdb] },
+  [GETGRBYGID] = { true, &dbs[grpdb] },
+  [GETHOSTBYNAME] = { true, &dbs[hstdb] },
+  [GETHOSTBYNAMEv6] = { true, &dbs[hstdb] },
+  [GETHOSTBYADDR] = { true, &dbs[hstdb] },
+  [GETHOSTBYADDRv6] = { true, &dbs[hstdb] },
+  [SHUTDOWN] = { false, NULL },
+  [GETSTAT] = { false, NULL },
+  [SHUTDOWN] = { false, NULL },
+  [GETFDPW] = { false, &dbs[pwddb] },
+  [GETFDGR] = { false, &dbs[grpdb] },
+  [GETFDHST] = { false, &dbs[hstdb] },
+  [GETAI] = { true, &dbs[hstdb] },
+  [INITGROUPS] = { true, &dbs[grpdb] },
+  [GETSERVBYNAME] = { true, &dbs[servdb] },
+  [GETSERVBYPORT] = { true, &dbs[servdb] },
+  [GETFDSERV] = { false, &dbs[servdb] }
 };
 
 
@@ -385,7 +392,7 @@
 
 	  /* Make sure the record is for this type of service.  */
 	  if (here->type >= LASTREQ
-	      || serv2db[here->type] != &dbs[dbnr])
+	      || reqinfo[here->type].db != &dbs[dbnr])
 	    goto fail;
 
 	  /* Validate boolean field value.  */
@@ -933,24 +940,14 @@
       return;
     }
 
-  /* Make the SELinux check before we go on to the standard checks.  We
-     need to verify that the request type is valid, since it has not
-     yet been checked at this point.  */
-  if (selinux_enabled
-      && __builtin_expect (req->type >= GETPWBYNAME, 1)
-      && __builtin_expect (req->type < LASTREQ, 1)
-      && __builtin_expect (req->type < SHUTDOWN || req->type > INVALIDATE, 1)
-      && nscd_request_avc_has_perm (fd, req->type) != 0)
+  /* Make the SELinux check before we go on to the standard checks.  */
+  if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0)
     return;
 
-  struct database_dyn *db = serv2db[req->type];
-
-  // XXX Clean up so that each new command need not introduce a
-  // XXX new conditional.
-  if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
-       && __builtin_expect (req->type, GETHOSTBYADDRv6) <= GETHOSTBYADDRv6)
-      || req->type == GETAI || req->type == INITGROUPS
-      || req->type == GETSERVBYNAME || req->type == GETSERVBYPORT)
+  struct database_dyn *db = reqinfo[req->type].db;
+
+  /* See whether we can service the request from the cache.  */
+  if (__builtin_expect (reqinfo[req->type].data_request, true))
     {
       if (__builtin_expect (debug_level, 0) > 0)
 	{
@@ -968,7 +965,7 @@
 	}
 
       /* Is this service enabled?  */
-      if (!db->enabled)
+      if (__builtin_expect (!db->enabled, 0))
 	{
 	  /* No, sent the prepared record.  */
 	  if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
@@ -1149,7 +1146,7 @@
     case GETFDHST:
     case GETFDSERV:
 #ifdef SCM_RIGHTS
-      send_ro_fd (serv2db[req->type], key, fd);
+      send_ro_fd (reqinfo[req->type].db, key, fd);
 #endif
       break;
 
@@ -1433,7 +1430,6 @@
 
       /* It should not be possible to crash the nscd with a silly
 	 request (i.e., a terribly large key).  We limit the size to 1kb.  */
-#define MAXKEYLEN 1024
       if (__builtin_expect (req.key_len, 1) < 0
 	  || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
 	{

Modified: trunk/libc/nscd/nscd-client.h
==============================================================================
--- trunk/libc/nscd/nscd-client.h (original)
+++ trunk/libc/nscd/nscd-client.h Mon Feb  5 09:59:45 2007
@@ -43,6 +43,9 @@
 
 /* Path for the configuration file.  */
 #define _PATH_NSCDCONF	 "/etc/nscd.conf"
+
+/* Maximu allowed length for the key.  */
+#define MAXKEYLEN 1024
 
 
 /* Available services.  */
@@ -323,10 +326,10 @@
 
 
 /* Search the mapped database.  */
-extern const struct datahead *__nscd_cache_search (request_type type,
-						   const char *key,
-						   size_t keylen,
-						   const struct mapped_database *mapped);
+extern struct datahead *__nscd_cache_search (request_type type,
+					     const char *key,
+					     size_t keylen,
+					     const struct mapped_database *mapped);
 
 /* Wrappers around read, readv and write that only read/write less than LEN
    bytes on error or EOF.  */

Modified: trunk/libc/nscd/nscd_getai.c
==============================================================================
--- trunk/libc/nscd/nscd_getai.c (original)
+++ trunk/libc/nscd/nscd_getai.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2004.
 
@@ -42,6 +42,7 @@
 {
   size_t keylen = strlen (key) + 1;
   int gc_cycle;
+  int nretries = 0;
 
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
@@ -50,49 +51,53 @@
 			       &gc_cycle);
 
  retry:;
-  const ai_response_header *ai_resp = NULL;
   struct nscd_ai_result *resultbuf = NULL;
   const char *recend = (const char *) ~UINTMAX_C (0);
   char *respdata = NULL;
   int retval = -1;
   int sock = -1;
+  ai_response_header ai_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
+						    mapped);
       if (found != NULL)
 	{
-	  ai_resp = &found->data[0].aidata;
-	  respdata = (char *) (ai_resp + 1);
+	  respdata = (char *) (&found->data[0].aidata + 1);
+	  ai_resp = found->data[0].aidata;
 	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust ai_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
 	}
     }
 
   /* If we do not have the cache mapped, try to get the data over the
      socket.  */
-  ai_response_header ai_resp_mem;
-  if (ai_resp == NULL)
-    {
-      sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp_mem,
-				 sizeof (ai_resp_mem));
+  if (respdata == NULL)
+    {
+      sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp,
+				 sizeof (ai_resp));
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
 	  __nss_not_use_nscd_hosts = 1;
 	  goto out;
 	}
-
-      ai_resp = &ai_resp_mem;
-    }
-
-  if (ai_resp->found == 1)
-    {
-      size_t datalen = ai_resp->naddrs + ai_resp->addrslen + ai_resp->canonlen;
-
-      /* This check is really only affects the case where the data
+    }
+
+  if (ai_resp.found == 1)
+    {
+      size_t datalen = ai_resp.naddrs + ai_resp.addrslen + ai_resp.canonlen;
+
+      /* This check really only affects the case where the data
 	 comes from the mapped cache.  */
-      if ((char *) (ai_resp + 1) + datalen > recend)
+      if (respdata + datalen > recend)
 	{
 	  assert (sock == -1);
 	  goto out;
@@ -108,10 +113,10 @@
 	}
 
       /* Set up the data structure, including pointers.  */
-      resultbuf->naddrs = ai_resp->naddrs;
+      resultbuf->naddrs = ai_resp.naddrs;
       resultbuf->addrs = (char *) (resultbuf + 1);
-      resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp->addrslen);
-      if (ai_resp->canonlen != 0)
+      resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp.addrslen);
+      if (ai_resp.canonlen != 0)
 	resultbuf->canon = (char *) (resultbuf->family + resultbuf->naddrs);
       else
 	resultbuf->canon = NULL;
@@ -137,10 +142,13 @@
 
 	  /* Try to detect corrupt databases.  */
 	  if (resultbuf->canon != NULL
-	      && resultbuf->canon[ai_resp->canonlen - 1] != '\0')
+	      && resultbuf->canon[ai_resp.canonlen - 1] != '\0')
 	    /* We cannot use the database.  */
 	    {
-	      free (resultbuf);
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      else
+		free (resultbuf);
 	      goto out_close;
 	    }
 
@@ -150,7 +158,7 @@
     }
   else
     {
-      if (__builtin_expect (ai_resp->found == -1, 0))
+      if (__builtin_expect (ai_resp.found == -1, 0))
 	{
 	  /* The daemon does not cache this database.  */
 	  __nss_not_use_nscd_hosts = 1;
@@ -158,7 +166,7 @@
 	}
 
       /* Store the error number.  */
-      *h_errnop = ai_resp->error;
+      *h_errnop = ai_resp.error;
 
       /* The `errno' to some value != ERANGE.  */
       __set_errno (ENOENT);
@@ -170,22 +178,25 @@
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      *result = NULL;
-      free (resultbuf);
-
-      goto retry;
+      if (retval != -1)
+	{
+	  *result = NULL;
+	  free (resultbuf);
+	  goto retry;
+	}
     }
 
   return retval;

Modified: trunk/libc/nscd/nscd_getgr_r.c
==============================================================================
--- trunk/libc/nscd/nscd_getgr_r.c (original)
+++ trunk/libc/nscd/nscd_getgr_r.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2000, 2002-2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2000, 2002-2005, 2006, 2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@xxxxxxxxxxxxxxxx>, 1998.
 
@@ -88,6 +89,7 @@
 	      struct group **result)
 {
   int gc_cycle;
+  int nretries = 0;
   const uint32_t *len = NULL;
   size_t lensize = 0;
 
@@ -97,55 +99,59 @@
 						       &__gr_map_handle,
 						       &gc_cycle);
  retry:;
-  const gr_response_header *gr_resp = NULL;
   const char *gr_name = NULL;
   size_t gr_name_len = 0;
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
+  gr_response_header gr_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  gr_resp = &found->data[0].grdata;
-	  len = (const uint32_t *) (gr_resp + 1);
-	  /* The alignment is always sufficient.  */
+	  len = (const uint32_t *) (&found->data[0].grdata + 1);
+	  gr_resp = found->data[0].grdata;
+	  gr_name = ((const char *) len
+		     + gr_resp.gr_mem_cnt * sizeof (uint32_t));
+	  gr_name_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len;
+	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust gr_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+
+	  /* The alignment is always sufficient, unless GC is in progress.  */
 	  assert (((uintptr_t) len & (__alignof__ (*len) - 1)) == 0);
-	  gr_name = ((const char *) len
-		     + gr_resp->gr_mem_cnt * sizeof (uint32_t));
-	  gr_name_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len;
-	  recend = (const char *) found->data + found->recsize;
-	}
-    }
-
-  gr_response_header gr_resp_mem;
+	}
+    }
+
   int sock = -1;
-  if (gr_resp == NULL)
-    {
-      sock = __nscd_open_socket (key, keylen, type, &gr_resp_mem,
-				 sizeof (gr_resp_mem));
+  if (gr_name == NULL)
+    {
+      sock = __nscd_open_socket (key, keylen, type, &gr_resp,
+				 sizeof (gr_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_group = 1;
 	  goto out;
 	}
-
-      gr_resp = &gr_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (gr_resp->found == -1, 0))
+  if (__builtin_expect (gr_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_group = 1;
       goto out_close;
     }
 
-  if (gr_resp->found == 1)
+  if (gr_resp.found == 1)
     {
       struct iovec vec[2];
       char *p = buffer;
@@ -157,8 +163,8 @@
 	 align the pointer.  */
       align = ((__alignof__ (char *) - (p - ((char *) 0)))
 	       & (__alignof__ (char *) - 1));
-      total_len = (align + (1 + gr_resp->gr_mem_cnt) * sizeof (char *)
-		   + gr_resp->gr_name_len + gr_resp->gr_passwd_len);
+      total_len = (align + (1 + gr_resp.gr_mem_cnt) * sizeof (char *)
+		   + gr_resp.gr_name_len + gr_resp.gr_passwd_len);
       if (__builtin_expect (buflen < total_len, 0))
 	{
 	no_room:
@@ -170,16 +176,16 @@
 
       p += align;
       resultbuf->gr_mem = (char **) p;
-      p += (1 + gr_resp->gr_mem_cnt) * sizeof (char *);
+      p += (1 + gr_resp.gr_mem_cnt) * sizeof (char *);
 
       /* Set pointers for strings.  */
       resultbuf->gr_name = p;
-      p += gr_resp->gr_name_len;
+      p += gr_resp.gr_name_len;
       resultbuf->gr_passwd = p;
-      p += gr_resp->gr_passwd_len;
+      p += gr_resp.gr_passwd_len;
 
       /* Fill in what we know now.  */
-      resultbuf->gr_gid = gr_resp->gr_gid;
+      resultbuf->gr_gid = gr_resp.gr_gid;
 
       /* Read the length information, group name, and password.  */
       if (gr_name == NULL)
@@ -187,17 +193,17 @@
 	  /* Allocate array to store lengths.  */
 	  if (lensize == 0)
 	    {
-	      lensize = gr_resp->gr_mem_cnt * sizeof (uint32_t);
+	      lensize = gr_resp.gr_mem_cnt * sizeof (uint32_t);
 	      len = (uint32_t *) alloca (lensize);
 	    }
-	  else if (gr_resp->gr_mem_cnt * sizeof (uint32_t) > lensize)
+	  else if (gr_resp.gr_mem_cnt * sizeof (uint32_t) > lensize)
 	    len = extend_alloca (len, lensize,
-				 gr_resp->gr_mem_cnt * sizeof (uint32_t));
+				 gr_resp.gr_mem_cnt * sizeof (uint32_t));
 
 	  vec[0].iov_base = (void *) len;
-	  vec[0].iov_len = gr_resp->gr_mem_cnt * sizeof (uint32_t);
+	  vec[0].iov_len = gr_resp.gr_mem_cnt * sizeof (uint32_t);
 	  vec[1].iov_base = resultbuf->gr_name;
-	  vec[1].iov_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len;
+	  vec[1].iov_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len;
 	  total_len = vec[0].iov_len + vec[1].iov_len;
 
 	  /* Get this data.  */
@@ -209,14 +215,14 @@
 	/* We already have the data.  Just copy the group name and
 	   password.  */
 	memcpy (resultbuf->gr_name, gr_name,
-		gr_resp->gr_name_len + gr_resp->gr_passwd_len);
+		gr_resp.gr_name_len + gr_resp.gr_passwd_len);
 
       /* Clear the terminating entry.  */
-      resultbuf->gr_mem[gr_resp->gr_mem_cnt] = NULL;
+      resultbuf->gr_mem[gr_resp.gr_mem_cnt] = NULL;
 
       /* Prepare reading the group members.  */
       total_len = 0;
-      for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt)
+      for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
 	{
 	  resultbuf->gr_mem[cnt] = p;
 	  total_len += len[cnt];
@@ -224,9 +230,25 @@
 	}
 
       if (__builtin_expect (gr_name + gr_name_len + total_len > recend, 0))
-	goto out_close;
+	{
+	  /* len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
       if (__builtin_expect (total_len > buflen, 0))
-	goto no_room;
+	{
+	  /* len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  else
+	    goto no_room;
+	}
 
       retval = 0;
       if (gr_name == NULL)
@@ -248,14 +270,14 @@
 
 	  /* Try to detect corrupt databases.  */
 	  if (resultbuf->gr_name[gr_name_len - 1] != '\0'
-	      || resultbuf->gr_passwd[gr_resp->gr_passwd_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt)
+	      || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
 		     if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
 		       break;
-	  	   cnt < gr_resp->gr_mem_cnt; }))
+	  	   cnt < gr_resp.gr_mem_cnt; }))
 	    {
 	      /* We cannot use the database.  */
-	      retval = -1;
+	      retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
 	      goto out_close;
 	    }
 
@@ -274,19 +296,21 @@
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;

Modified: trunk/libc/nscd/nscd_gethst_r.c
==============================================================================
--- trunk/libc/nscd/nscd_gethst_r.c (original)
+++ trunk/libc/nscd/nscd_gethst_r.c Mon Feb  5 09:59:45 2007
@@ -113,7 +113,6 @@
 			       &gc_cycle);
 
  retry:;
-  const hst_response_header *hst_resp = NULL;
   const char *h_name = NULL;
   const uint32_t *aliases_len = NULL;
   const char *addr_list = NULL;
@@ -121,18 +120,27 @@
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
   int sock = -1;
+  hst_response_header hst_resp;
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      /* No const qualifier, as it can change during garbage collection.  */
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  hst_resp = &found->data[0].hstdata;
-	  h_name = (char *) (hst_resp + 1);
-	  aliases_len = (uint32_t *) (h_name + hst_resp->h_name_len);
+	  h_name = (char *) (&found->data[0].hstdata + 1);
+	  hst_resp = found->data[0].hstdata;
+	  aliases_len = (uint32_t *) (h_name + hst_resp.h_name_len);
 	  addr_list = ((char *) aliases_len
-		       + hst_resp->h_aliases_cnt * sizeof (uint32_t));
-	  addr_list_len = hst_resp->h_addr_list_cnt * INADDRSZ;
+		       + hst_resp.h_aliases_cnt * sizeof (uint32_t));
+	  addr_list_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust hst_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
 
 #ifndef _STRING_ARCH_unaligned
 	  /* The aliases_len array in the mapped database might very
@@ -142,51 +150,47 @@
 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
 	      != 0)
 	    {
-	      uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
+	      uint32_t *tmp = alloca (hst_resp.h_aliases_cnt
 				      * sizeof (uint32_t));
 	      aliases_len = memcpy (tmp, aliases_len,
-				    hst_resp->h_aliases_cnt
+				    hst_resp.h_aliases_cnt
 				    * sizeof (uint32_t));
 	    }
 #endif
 	  if (type != GETHOSTBYADDR && type != GETHOSTBYNAME)
 	    {
-	      if (hst_resp->h_length == INADDRSZ)
+	      if (hst_resp.h_length == INADDRSZ)
 		addr_list += addr_list_len;
-	      addr_list_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
-	    }
-	  recend = (const char *) found->data + found->recsize;
+	      addr_list_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+	    }
 	  if (__builtin_expect ((const char *) addr_list + addr_list_len
 				> recend, 0))
-	    goto out_close;
-	}
-    }
-
-  hst_response_header hst_resp_mem;
-  if (hst_resp == NULL)
-    {
-      sock = __nscd_open_socket (key, keylen, type, &hst_resp_mem,
-				 sizeof (hst_resp_mem));
+	    goto out;
+	}
+    }
+
+  if (h_name == NULL)
+    {
+      sock = __nscd_open_socket (key, keylen, type, &hst_resp,
+				 sizeof (hst_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_hosts = 1;
 	  goto out;
 	}
-
-      hst_resp = &hst_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (hst_resp->found == -1, 0))
+  if (__builtin_expect (hst_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_hosts = 1;
       goto out_close;
     }
 
-  if (hst_resp->found == 1)
+  if (hst_resp.found == 1)
     {
       char *cp = buffer;
       uintptr_t align1;
@@ -201,15 +205,15 @@
 	 align the pointer and the base of the h_addr_list pointers.  */
       align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp->h_name_len)
+      align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp.h_name_len)
 					 - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      if (buflen < (align1 + hst_resp->h_name_len + align2
-		    + ((hst_resp->h_aliases_cnt + hst_resp->h_addr_list_cnt
+      if (buflen < (align1 + hst_resp.h_name_len + align2
+		    + ((hst_resp.h_aliases_cnt + hst_resp.h_addr_list_cnt
 			+ 2)
 		       * sizeof (char *))
-		    + hst_resp->h_addr_list_cnt * (type == AF_INET
-						   ? INADDRSZ : IN6ADDRSZ)))
+		    + hst_resp.h_addr_list_cnt * (type == AF_INET
+						  ? INADDRSZ : IN6ADDRSZ)))
 	{
 	no_room:
 	  *h_errnop = NETDB_INTERNAL;
@@ -221,12 +225,12 @@
 
       /* Prepare the result as far as we can.  */
       resultbuf->h_aliases = (char **) cp;
-      cp += (hst_resp->h_aliases_cnt + 1) * sizeof (char *);
+      cp += (hst_resp.h_aliases_cnt + 1) * sizeof (char *);
       resultbuf->h_addr_list = (char **) cp;
-      cp += (hst_resp->h_addr_list_cnt + 1) * sizeof (char *);
+      cp += (hst_resp.h_addr_list_cnt + 1) * sizeof (char *);
 
       resultbuf->h_name = cp;
-      cp += hst_resp->h_name_len + align2;
+      cp += hst_resp.h_name_len + align2;
 
       if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
 	{
@@ -238,7 +242,7 @@
 	  resultbuf->h_addrtype = AF_INET6;
 	  resultbuf->h_length = IN6ADDRSZ;
 	}
-      for (cnt = 0; cnt < hst_resp->h_addr_list_cnt; ++cnt)
+      for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt)
 	{
 	  resultbuf->h_addr_list[cnt] = cp;
 	  cp += resultbuf->h_length;
@@ -250,47 +254,47 @@
 	  struct iovec vec[4];
 
 	  vec[0].iov_base = resultbuf->h_name;
-	  vec[0].iov_len = hst_resp->h_name_len;
-	  total_len = hst_resp->h_name_len;
+	  vec[0].iov_len = hst_resp.h_name_len;
+	  total_len = hst_resp.h_name_len;
 	  n = 1;
 
-	  if (hst_resp->h_aliases_cnt > 0)
-	    {
-	      aliases_len = alloca (hst_resp->h_aliases_cnt
+	  if (hst_resp.h_aliases_cnt > 0)
+	    {
+	      aliases_len = alloca (hst_resp.h_aliases_cnt
 				    * sizeof (uint32_t));
 	      vec[n].iov_base = (void *) aliases_len;
-	      vec[n].iov_len = hst_resp->h_aliases_cnt * sizeof (uint32_t);
-
-	      total_len += hst_resp->h_aliases_cnt * sizeof (uint32_t);
+	      vec[n].iov_len = hst_resp.h_aliases_cnt * sizeof (uint32_t);
+
+	      total_len += hst_resp.h_aliases_cnt * sizeof (uint32_t);
 	      ++n;
 	    }
 
 	  if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
 	    {
 	      vec[n].iov_base = resultbuf->h_addr_list[0];
-	      vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
-
-	      total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
+	      vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+
+	      total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
 
 	      ++n;
 	    }
 	  else
 	    {
-	      if (hst_resp->h_length == INADDRSZ)
+	      if (hst_resp.h_length == INADDRSZ)
 		{
-		  ignore = alloca (hst_resp->h_addr_list_cnt * INADDRSZ);
+		  ignore = alloca (hst_resp.h_addr_list_cnt * INADDRSZ);
 		  vec[n].iov_base = ignore;
-		  vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
-
-		  total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
+		  vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+
+		  total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
 
 		  ++n;
 		}
 
 	      vec[n].iov_base = resultbuf->h_addr_list[0];
-	      vec[n].iov_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
-
-	      total_len += hst_resp->h_addr_list_cnt * IN6ADDRSZ;
+	      vec[n].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+
+	      total_len += hst_resp.h_addr_list_cnt * IN6ADDRSZ;
 
 	      ++n;
 	    }
@@ -300,13 +304,13 @@
 	}
       else
 	{
-	  memcpy (resultbuf->h_name, h_name, hst_resp->h_name_len);
+	  memcpy (resultbuf->h_name, h_name, hst_resp.h_name_len);
 	  memcpy (resultbuf->h_addr_list[0], addr_list, addr_list_len);
 	}
 
       /*  Now we also can read the aliases.  */
       total_len = 0;
-      for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
+      for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
 	{
 	  resultbuf->h_aliases[cnt] = cp;
 	  cp += aliases_len[cnt];
@@ -316,10 +320,25 @@
 
       if (__builtin_expect ((const char *) addr_list + addr_list_len
 			    + total_len > recend, 0))
-	goto out_close;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
       /* See whether this would exceed the buffer capacity.  */
       if (__builtin_expect (cp > buffer + buflen, 0))
-	goto no_room;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  goto no_room;
+	}
 
       /* And finally read the aliases.  */
       if (addr_list == NULL)
@@ -338,14 +357,18 @@
 		  (const char *) addr_list + addr_list_len, total_len);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->h_name[hst_resp->h_name_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
+	  if (resultbuf->h_name[hst_resp.h_name_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
 		     if (resultbuf->h_aliases[cnt][aliases_len[cnt] - 1]
 			 != '\0')
 		       break;
-		   cnt < hst_resp->h_aliases_cnt; }))
-	    /* We cannot use the database.  */
-	    goto out_close;
+		   cnt < hst_resp.h_aliases_cnt; }))
+	    {
+	      /* We cannot use the database.  */
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      goto out_close;
+	    }
 
 	  retval = 0;
 	  *result = resultbuf;
@@ -354,7 +377,7 @@
   else
     {
       /* Store the error number.  */
-      *h_errnop = hst_resp->error;
+      *h_errnop = hst_resp.error;
 
       /* The `errno' to some value != ERANGE.  */
       __set_errno (ENOENT);
@@ -366,19 +389,21 @@
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0 || ++nretries == 5)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;

Modified: trunk/libc/nscd/nscd_getpw_r.c
==============================================================================
--- trunk/libc/nscd/nscd_getpw_r.c (original)
+++ trunk/libc/nscd/nscd_getpw_r.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2003, 2004, 2005, 2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@xxxxxxxxxxxxxxxx>, 1998.
 
@@ -88,76 +89,81 @@
 	      struct passwd **result)
 {
   int gc_cycle;
+  int nretries = 0;
+
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
   struct mapped_database *mapped;
   mapped = __nscd_get_map_ref (GETFDPW, "passwd", &map_handle, &gc_cycle);
 
  retry:;
-  const pw_response_header *pw_resp = NULL;
   const char *pw_name = NULL;
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
+  pw_response_header pw_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
       if (found != NULL)
 	{
-	  pw_resp = &found->data[0].pwdata;
-	  pw_name = (const char *) (pw_resp + 1);
+	  pw_name = (const char *) (&found->data[0].pwdata + 1);
+	  pw_resp = found->data[0].pwdata;
 	  recend = (const char *) found->data + found->recsize;
-	}
-    }
-
-  pw_response_header pw_resp_mem;
+	  /* Now check if we can trust pw_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+	}
+    }
+
   int sock = -1;
-  if (pw_resp == NULL)
-    {
-      sock = __nscd_open_socket (key, keylen, type, &pw_resp_mem,
-				 sizeof (pw_resp_mem));
+  if (pw_name == NULL)
+    {
+      sock = __nscd_open_socket (key, keylen, type, &pw_resp,
+				 sizeof (pw_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_passwd = 1;
 	  goto out;
 	}
-
-      pw_resp = &pw_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (pw_resp->found == -1, 0))
+  if (__builtin_expect (pw_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_passwd = 1;
       goto out_close;
     }
 
-  if (pw_resp->found == 1)
+  if (pw_resp.found == 1)
     {
       /* Set the information we already have.  */
-      resultbuf->pw_uid = pw_resp->pw_uid;
-      resultbuf->pw_gid = pw_resp->pw_gid;
+      resultbuf->pw_uid = pw_resp.pw_uid;
+      resultbuf->pw_gid = pw_resp.pw_gid;
 
       char *p = buffer;
       /* get pw_name */
       resultbuf->pw_name = p;
-      p += pw_resp->pw_name_len;
+      p += pw_resp.pw_name_len;
       /* get pw_passwd */
       resultbuf->pw_passwd = p;
-      p += pw_resp->pw_passwd_len;
+      p += pw_resp.pw_passwd_len;
       /* get pw_gecos */
       resultbuf->pw_gecos = p;
-      p += pw_resp->pw_gecos_len;
+      p += pw_resp.pw_gecos_len;
       /* get pw_dir */
       resultbuf->pw_dir = p;
-      p += pw_resp->pw_dir_len;
+      p += pw_resp.pw_dir_len;
       /* get pw_pshell */
       resultbuf->pw_shell = p;
-      p += pw_resp->pw_shell_len;
+      p += pw_resp.pw_shell_len;
 
       ssize_t total = p - buffer;
       if (__builtin_expect (pw_name + total > recend, 0))
@@ -189,14 +195,14 @@
 	  memcpy (resultbuf->pw_name, pw_name, total);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->pw_name[pw_resp->pw_name_len - 1] != '\0'
-	      || resultbuf->pw_passwd[pw_resp->pw_passwd_len - 1] != '\0'
-	      || resultbuf->pw_gecos[pw_resp->pw_gecos_len - 1] != '\0'
-	      || resultbuf->pw_dir[pw_resp->pw_dir_len - 1] != '\0'
-	      || resultbuf->pw_shell[pw_resp->pw_shell_len - 1] != '\0')
+	  if (resultbuf->pw_name[pw_resp.pw_name_len - 1] != '\0'
+	      || resultbuf->pw_passwd[pw_resp.pw_passwd_len - 1] != '\0'
+	      || resultbuf->pw_gecos[pw_resp.pw_gecos_len - 1] != '\0'
+	      || resultbuf->pw_dir[pw_resp.pw_dir_len - 1] != '\0'
+	      || resultbuf->pw_shell[pw_resp.pw_shell_len - 1] != '\0')
 	    {
 	      /* We cannot use the database.  */
-	      retval = -1;
+	      retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
 	      goto out_close;
 	    }
 
@@ -215,19 +221,21 @@
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;

Modified: trunk/libc/nscd/nscd_getserv_r.c
==============================================================================
--- trunk/libc/nscd/nscd_getserv_r.c (original)
+++ trunk/libc/nscd/nscd_getserv_r.c Mon Feb  5 09:59:45 2007
@@ -93,7 +93,6 @@
 		     "/", 1), proto ?: "", protolen + 1);
 
  retry:;
-  const serv_response_header *serv_resp = NULL;
   const char *s_name = NULL;
   const char *s_proto = NULL;
   const uint32_t *aliases_len = NULL;
@@ -101,19 +100,32 @@
   int retval = -1;
   const char *recend = (const char *) ~UINTMAX_C (0);
   int sock = -1;
+  serv_response_header serv_resp;
+
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (type, key, keylen,
-							  mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
 
       if (found != NULL)
 	{
-	  serv_resp = &found->data[0].servdata;
-	  s_name = (char *) (serv_resp + 1);
-	  s_proto = s_name + serv_resp->s_name_len;
-	  aliases_len = (uint32_t *) (s_proto + serv_resp->s_proto_len);
+	  s_name = (char *) (&found->data[0].servdata + 1);
+	  serv_resp = found->data[0].servdata;
+	  s_proto = s_name + serv_resp.s_name_len;
+	  aliases_len = (uint32_t *) (s_proto + serv_resp.s_proto_len);
 	  aliases_list = ((char *) aliases_len
-			  + serv_resp->s_aliases_cnt * sizeof (uint32_t));
+			  + serv_resp.s_aliases_cnt * sizeof (uint32_t));
+	  recend = (const char *) found->data + found->recsize;
+	  /* Now check if we can trust serv_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+	  if (__builtin_expect ((const char *) aliases_len
+				+ serv_resp.s_aliases_cnt * sizeof (uint32_t)
+				> recend, 0))
+	    goto out;
 
 #ifndef _STRING_ARCH_unaligned
 	  /* The aliases_len array in the mapped database might very
@@ -123,46 +135,38 @@
 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
 	      != 0)
 	    {
-	      uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
+	      uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
 				      * sizeof (uint32_t));
 	      aliases_len = memcpy (tmp, aliases_len,
-				    hst_resp->h_aliases_cnt
+				    serv_resp.s_aliases_cnt
 				    * sizeof (uint32_t));
 	    }
 #endif
-	  recend = (const char *) found->data + found->recsize;
-	  if (__builtin_expect ((const char *) aliases_len
-				+ serv_resp->s_aliases_cnt * sizeof (uint32_t)
-				> recend, 0))
-	    goto out_close;
-	}
-    }
-
-  serv_response_header serv_resp_mem;
-  if (serv_resp == NULL)
-    {
-      sock = __nscd_open_socket (key, keylen, type, &serv_resp_mem,
-				 sizeof (serv_resp_mem));
+	}
+    }
+
+  if (s_name == NULL)
+    {
+      sock = __nscd_open_socket (key, keylen, type, &serv_resp,
+				 sizeof (serv_resp));
       if (sock == -1)
 	{
 	  __nss_not_use_nscd_services = 1;
 	  goto out;
 	}
-
-      serv_resp = &serv_resp_mem;
     }
 
   /* No value found so far.  */
   *result = NULL;
 
-  if (__builtin_expect (serv_resp->found == -1, 0))
+  if (__builtin_expect (serv_resp.found == -1, 0))
     {
       /* The daemon does not cache this database.  */
       __nss_not_use_nscd_services = 1;
       goto out_close;
     }
 
-  if (serv_resp->found == 1)
+  if (serv_resp.found == 1)
     {
       char *cp = buf;
       uintptr_t align1;
@@ -176,13 +180,13 @@
 	 align the pointer and the base of the h_addr_list pointers.  */
       align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp->s_name_len
-					  + serv_resp->s_proto_len)
+      align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp.s_name_len
+					  + serv_resp.s_proto_len)
 					 - ((char *) 0)))
 		& (__alignof__ (char *) - 1));
-      if (buflen < (align1 + serv_resp->s_name_len + serv_resp->s_proto_len
+      if (buflen < (align1 + serv_resp.s_name_len + serv_resp.s_proto_len
 		    + align2
-		    + (serv_resp->s_aliases_cnt + 1) * sizeof (char *)))
+		    + (serv_resp.s_aliases_cnt + 1) * sizeof (char *)))
 	{
 	no_room:
 	  __set_errno (ERANGE);
@@ -193,31 +197,31 @@
 
       /* Prepare the result as far as we can.  */
       resultbuf->s_aliases = (char **) cp;
-      cp += (serv_resp->s_aliases_cnt + 1) * sizeof (char *);
+      cp += (serv_resp.s_aliases_cnt + 1) * sizeof (char *);
 
       resultbuf->s_name = cp;
-      cp += serv_resp->s_name_len;
+      cp += serv_resp.s_name_len;
       resultbuf->s_proto = cp;
-      cp += serv_resp->s_proto_len + align2;
-      resultbuf->s_port = serv_resp->s_port;
+      cp += serv_resp.s_proto_len + align2;
+      resultbuf->s_port = serv_resp.s_port;
 
       if (s_name == NULL)
 	{
 	  struct iovec vec[2];
 
 	  vec[0].iov_base = resultbuf->s_name;
-	  vec[0].iov_len = serv_resp->s_name_len + serv_resp->s_proto_len;
+	  vec[0].iov_len = serv_resp.s_name_len + serv_resp.s_proto_len;
 	  total_len = vec[0].iov_len;
 	  n = 1;
 
-	  if (serv_resp->s_aliases_cnt > 0)
-	    {
-	      aliases_len = alloca (serv_resp->s_aliases_cnt
+	  if (serv_resp.s_aliases_cnt > 0)
+	    {
+	      aliases_len = alloca (serv_resp.s_aliases_cnt
 				    * sizeof (uint32_t));
 	      vec[n].iov_base = (void *) aliases_len;
-	      vec[n].iov_len = serv_resp->s_aliases_cnt * sizeof (uint32_t);
-
-	      total_len += serv_resp->s_aliases_cnt * sizeof (uint32_t);
+	      vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
+
+	      total_len += serv_resp.s_aliases_cnt * sizeof (uint32_t);
 	      ++n;
 	    }
 
@@ -226,11 +230,11 @@
 	}
       else
 	memcpy (resultbuf->s_name, s_name,
-		serv_resp->s_name_len + serv_resp->s_proto_len);
+		serv_resp.s_name_len + serv_resp.s_proto_len);
 
       /*  Now we also can read the aliases.  */
       total_len = 0;
-      for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
+      for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
 	{
 	  resultbuf->s_aliases[cnt] = cp;
 	  cp += aliases_len[cnt];
@@ -240,10 +244,26 @@
 
       if (__builtin_expect ((const char *) aliases_list + total_len > recend,
 			    0))
-	goto out_close;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    retval = -2;
+	  goto out_close;
+	}
+
       /* See whether this would exceed the buffer capacity.  */
       if (__builtin_expect (cp > buf + buflen, 0))
-	goto no_room;
+	{
+	  /* aliases_len array might contain garbage during nscd GC cycle,
+	     retry rather than fail in that case.  */
+	  if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out_close;
+	    }
+	  goto no_room;
+	}
 
       /* And finally read the aliases.  */
       if (aliases_list == NULL)
@@ -261,15 +281,19 @@
 	  memcpy (resultbuf->s_aliases[0], aliases_list, total_len);
 
 	  /* Try to detect corrupt databases.  */
-	  if (resultbuf->s_name[serv_resp->s_name_len - 1] != '\0'
-	      || resultbuf->s_proto[serv_resp->s_proto_len - 1] != '\0'
-	      || ({for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
+	  if (resultbuf->s_name[serv_resp.s_name_len - 1] != '\0'
+	      || resultbuf->s_proto[serv_resp.s_proto_len - 1] != '\0'
+	      || ({for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
 		     if (resultbuf->s_aliases[cnt][aliases_len[cnt] - 1]
 			 != '\0')
 		       break;
-		   cnt < serv_resp->s_aliases_cnt; }))
-	    /* We cannot use the database.  */
-	    goto out_close;
+		   cnt < serv_resp.s_aliases_cnt; }))
+	    {
+	      /* We cannot use the database.  */
+	      if (mapped->head->gc_cycle != gc_cycle)
+		retval = -2;
+	      goto out_close;
+	    }
 
 	  retval = 0;
 	  *result = resultbuf;
@@ -287,19 +311,21 @@
   if (sock != -1)
     close_not_cancel_no_status (sock);
  out:
-  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
+  if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
     {
       /* When we come here this means there has been a GC cycle while we
 	 were looking for the data.  This means the data might have been
 	 inconsistent.  Retry if possible.  */
-      if ((gc_cycle & 1) != 0 || ++nretries == 5)
+      if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
 	{
 	  /* nscd is just running gc now.  Disable using the mapping.  */
-	  __nscd_unmap (mapped);
+	  if (atomic_decrement_val (&mapped->counter) == 0)
+	    __nscd_unmap (mapped);
 	  mapped = NO_MAPPING;
 	}
 
-      goto retry;
+      if (retval != -1)
+	goto retry;
     }
 
   return retval;

Modified: trunk/libc/nscd/nscd_helper.c
==============================================================================
--- trunk/libc/nscd/nscd_helper.c (original)
+++ trunk/libc/nscd/nscd_helper.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002,2003,2004,2005,2006,2007
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1998.
 
@@ -21,6 +22,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
+#include <string.h>
 #include <time.h>
 #include <unistd.h>
 #include <sys/mman.h>
@@ -95,16 +97,20 @@
 
 
 static int
-open_socket (void)
+open_socket (request_type type, const char *key, size_t keylen)
 {
   int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
   if (sock < 0)
     return -1;
 
+  struct
+  {
+    request_header req;
+    char key[keylen];
+  } reqdata;
+
   /* Make socket non-blocking.  */
-  int fl = __fcntl (sock, F_GETFL);
-  if (fl != -1)
-    __fcntl (sock, F_SETFL, fl | O_NONBLOCK);
+  __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
 
   struct sockaddr_un sun;
   sun.sun_family = AF_UNIX;
@@ -113,13 +119,56 @@
       && errno != EINPROGRESS)
     goto out;
 
-  struct pollfd fds[1];
-  fds[0].fd = sock;
-  fds[0].events = POLLOUT | POLLERR | POLLHUP;
-  if (__poll (fds, 1, 5 * 1000) > 0)
-    /* Success.  We do not check for success of the connect call here.
-       If it failed, the following operations will fail.  */
-    return sock;
+  reqdata.req.version = NSCD_VERSION;
+  reqdata.req.type = type;
+  reqdata.req.key_len = keylen;
+
+  memcpy (reqdata.key, key, keylen);
+
+  bool first_try = true;
+  struct timeval tvend;
+  /* Fake initializing tvend.  */
+  asm ("" : "=m" (tvend));
+  while (1)
+    {
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+      ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
+						 sizeof (reqdata),
+						 MSG_NOSIGNAL));
+      if (__builtin_expect (wres == (ssize_t) sizeof (reqdata), 1))
+	/* We managed to send the request.  */
+	return sock;
+
+      if (wres != -1 || errno != EAGAIN)
+	/* Something is really wrong, no chance to continue.  */
+	break;
+
+      /* The daemon is busy wait for it.  */
+      int to;
+      struct timeval now;
+      (void) __gettimeofday (&now, NULL);
+      if (first_try)
+	{
+	  tvend.tv_usec = now.tv_usec;
+	  tvend.tv_sec = now.tv_sec + 5;
+	  to = 5 * 1000;
+	  first_try = false;
+	}
+      else
+	to = ((tvend.tv_sec - now.tv_sec) * 1000
+	      + (tvend.tv_usec - now.tv_usec) / 1000);
+
+      struct pollfd fds[1];
+      fds[0].fd = sock;
+      fds[0].events = POLLOUT | POLLERR | POLLHUP;
+      if (__poll (fds, 1, to) <= 0)
+	/* The connection timed out or broke down.  */
+	break;
+
+      /* We try to write again.  */
+    }
 
  out:
   close_not_cancel_no_status (sock);
@@ -179,36 +228,15 @@
   int saved_errno = errno;
 
   int mapfd = -1;
-
-  /* Send the request.  */
-  struct
-  {
-    request_header req;
-    char key[keylen];
-  } reqdata;
-
-  int sock = open_socket ();
+  char resdata[keylen];
+
+  /* Open a socket and send the request.  */
+  int sock = open_socket (type, key, keylen);
   if (sock < 0)
     goto out;
 
-  reqdata.req.version = NSCD_VERSION;
-  reqdata.req.type = type;
-  reqdata.req.key_len = keylen;
-  memcpy (reqdata.key, key, keylen);
-
-# ifndef MSG_NOSIGNAL
-#  define MSG_NOSIGNAL 0
-# endif
-  if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata,
-						    sizeof (reqdata),
-						    MSG_NOSIGNAL))
-			!= sizeof (reqdata), 0))
-    /* We cannot even write the request.  */
-    goto out_close2;
-
   /* Room for the data sent along with the file descriptor.  We expect
      the key name back.  */
-# define resdata reqdata.key
   struct iovec iov[1];
   iov[0].iov_base = resdata;
   iov[0].iov_len = keylen;
@@ -362,7 +390,10 @@
 }
 
 
-const struct datahead *
+/* Don't return const struct datahead *, as eventhough the record
+   is normally constant, it can change arbitrarily during nscd
+   garbage collection.  */
+struct datahead *
 __nscd_cache_search (request_type type, const char *key, size_t keylen,
 		     const struct mapped_database *mapped)
 {
@@ -374,15 +405,31 @@
     {
       struct hashentry *here = (struct hashentry *) (mapped->data + work);
 
+#ifndef _STRING_ARCH_unaligned
+      /* Although during garbage collection when moving struct hashentry
+	 records around we first copy from old to new location and then
+	 adjust pointer from previous hashentry to it, there is no barrier
+	 between those memory writes.  It is very unlikely to hit it,
+	 so check alignment only if a misaligned load can crash the
+	 application.  */
+      if ((uintptr_t) here & (__alignof__ (*here) - 1))
+	return NULL;
+#endif
+
       if (type == here->type
 	  && keylen == here->len
-	  && here->key + here->len <= datasize
+	  && here->key + keylen <= datasize
 	  && memcmp (key, mapped->data + here->key, keylen) == 0
 	  && here->packet + sizeof (struct datahead) <= datasize)
 	{
 	  /* We found the entry.  Increment the appropriate counter.  */
-	  const struct datahead *dh
+	  struct datahead *dh
 	    = (struct datahead *) (mapped->data + here->packet);
+
+#ifndef _STRING_ARCH_unaligned
+	  if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
+	    return NULL;
+#endif
 
 	  /* See whether we must ignore the entry or whether something
 	     is wrong because garbage collection is in progress.  */
@@ -402,28 +449,22 @@
 __nscd_open_socket (const char *key, size_t keylen, request_type type,
 		    void *response, size_t responselen)
 {
+  /* This should never happen and it is something the nscd daemon
+     enforces, too.  He it helps to limit the amount of stack
+     used.  */
+  if (keylen > MAXKEYLEN)
+    return -1;
+
   int saved_errno = errno;
 
-  int sock = open_socket ();
+  int sock = open_socket (type, key, keylen);
   if (sock >= 0)
     {
-      request_header req;
-      req.version = NSCD_VERSION;
-      req.type = type;
-      req.key_len = keylen;
-
-      struct iovec vec[2];
-      vec[0].iov_base = &req;
-      vec[0].iov_len = sizeof (request_header);
-      vec[1].iov_base = (void *) key;
-      vec[1].iov_len = keylen;
-
-      ssize_t nbytes = TEMP_FAILURE_RETRY (__writev (sock, vec, 2));
-      if (nbytes == (ssize_t) (sizeof (request_header) + keylen)
-	  /* Wait for data.  */
-	  && wait_on_socket (sock) > 0)
-	{
-	  nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen));
+      /* Wait for data.  */
+      if (wait_on_socket (sock) > 0)
+	{
+	  ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
+						       responselen));
 	  if (nbytes == (ssize_t) responselen)
 	    return sock;
 	}

Modified: trunk/libc/nscd/nscd_initgroups.c
==============================================================================
--- trunk/libc/nscd/nscd_initgroups.c (original)
+++ trunk/libc/nscd/nscd_initgroups.c Mon Feb  5 09:59:45 2007
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2004.
 
@@ -39,6 +39,7 @@
 {
   size_t userlen = strlen (user) + 1;
   int gc_cycle;
+  int nretries = 0;
 
   /* If the mapping is available, try to search there instead of
      communicating with the nscd.  */
@@ -46,44 +47,49 @@
   mapped = __nscd_get_map_ref (GETFDGR, "group", &__gr_map_handle, &gc_cycle);
 
  retry:;
-  const initgr_response_header *initgr_resp = NULL;
   char *respdata = NULL;
   int retval = -1;
   int sock = -1;
+  initgr_response_header initgr_resp;
 
   if (mapped != NO_MAPPING)
     {
-      const struct datahead *found = __nscd_cache_search (INITGROUPS, user,
-							  userlen, mapped);
+      struct datahead *found = __nscd_cache_search (INITGROUPS, user,
+						    userlen, mapped);
       if (found != NULL)
 	{
-	  initgr_resp = &found->data[0].initgrdata;
-	  respdata = (char *) (initgr_resp + 1);
+	  respdata = (char *) (&found->data[0].initgrdata + 1);
+	  initgr_resp = found->data[0].initgrdata;
 	  char *recend = (char *) found->data + found->recsize;
 
-	  if (respdata + initgr_resp->ngrps * sizeof (int32_t) > recend)
+	  /* Now check if we can trust initgr_resp fields.  If GC is
+	     in progress, it can contain anything.  */
+	  if (mapped->head->gc_cycle != gc_cycle)
+	    {
+	      retval = -2;
+	      goto out;
+	    }
+
+	  if (respdata + initgr_resp.ngrps * sizeof (int32_t) > recend)
 	    goto out;
 	}
     }
 
   /* If we do not have the cache mapped, try to get the data over the
      socket.  */
-  initgr_response_header initgr_resp_mem;

[... 1654 lines stripped ...]