about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Jaeger <aj@suse.de>2012-05-15 20:35:53 +0200
committerAndreas Jaeger <aj@suse.de>2012-05-15 20:37:05 +0200
commit509072a0f7f8a37bedf61a78c0cdd7783368c65a (patch)
tree32ac15ad1aba98673f42bc475d053fb1b4b3b864
parentba75122dd93b6188d1be446df0502c4cbe5c32e6 (diff)
downloadglibc-509072a0f7f8a37bedf61a78c0cdd7783368c65a.tar.gz
glibc-509072a0f7f8a37bedf61a78c0cdd7783368c65a.tar.xz
glibc-509072a0f7f8a37bedf61a78c0cdd7783368c65a.zip
Avoid race in nscd
2012-05-15  Jeff Law  <law@redhat.com>
            Andreas Jaeger  <aj@suse.de>

        [BZ #13594]
        * nscd/nscd-client.h (__nscd_acquire_maplock): New function, split
        out from...
        * nscd/nscd_helper.c (__nscd_get_map_ref): ... here.
        * nscd/nscd-client.h: Add __nscd_acquire_maplock.
        * nscd/nscd_gethst_r.c (__nscd_get_nl_timestamp): Add locking to
        code changing __hst_map_handle.map.
-rw-r--r--ChangeLog11
-rw-r--r--NEWS20
-rw-r--r--nscd/nscd-client.h21
-rw-r--r--nscd/nscd_gethst_r.c21
-rw-r--r--nscd/nscd_helper.c15
5 files changed, 60 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 7576361c77..b635a19058 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-05-15  Jeff Law  <law@redhat.com>
+	    Andreas Jaeger  <aj@suse.de>
+
+	[BZ #13594]
+	* nscd/nscd-client.h (__nscd_acquire_maplock): New function, split
+	out from...
+	* nscd/nscd_helper.c (__nscd_get_map_ref): ... here.
+	* nscd/nscd-client.h: Add __nscd_acquire_maplock.
+	* nscd/nscd_gethst_r.c (__nscd_get_nl_timestamp): Add locking to
+	code changing __hst_map_handle.map.
+
 2012-05-15  Roland McGrath  <roland@hack.frob.com>
 
 	* configure.in (sysnames): Look for Implies-before and Implies-after
diff --git a/NEWS b/NEWS
index 39def0430e..e869471884 100644
--- a/NEWS
+++ b/NEWS
@@ -18,16 +18,16 @@ Version 2.16
   11494, 11521, 11677, 11837, 11959, 12047, 12097, 12193, 12297, 12298,
   12301, 12340, 12354, 13058, 13361, 13525, 13526, 13527, 13528, 13529,
   13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555, 13556,
-  13559, 13563, 13566, 13583, 13592, 13613, 13618, 13637, 13656, 13658,
-  13673, 13691, 13695, 13704, 13705, 13706, 13726, 13738, 13739, 13750,
-  13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806, 13824, 13840,
-  13841, 13844, 13846, 13851, 13852, 13854, 13871, 13872, 13873, 13879,
-  13883, 13884, 13885, 13886, 13892, 13895, 13908, 13910, 13911, 13912,
-  13913, 13914, 13915, 13916, 13917, 13918, 13919, 13920, 13921, 13922,
-  13923, 13924, 13926, 13927, 13928, 13938, 13941, 13942, 13954, 13955,
-  13956, 13963, 13967, 13970, 13973, 13979, 13983, 13986, 14012, 14027,
-  14033, 14034, 14040, 14043, 14044, 14049, 14053, 14055, 14064, 14080,
-  14083, 14103, 14104
+  13559, 13563, 13566, 13583, 13592, 13594, 13613, 13618, 13637, 13656,
+  13658, 13673, 13691, 13695, 13704, 13705, 13706, 13726, 13738, 13739,
+  13750, 13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806, 13824,
+  13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13872, 13873,
+  13879, 13883, 13884, 13885, 13886, 13892, 13895, 13908, 13910, 13911,
+  13912, 13913, 13914, 13915, 13916, 13917, 13918, 13919, 13920, 13921,
+  13922, 13923, 13924, 13926, 13927, 13928, 13938, 13941, 13942, 13954,
+  13955, 13956, 13963, 13967, 13970, 13973, 13979, 13983, 13986, 14012,
+  14027, 14033, 14034, 14040, 14043, 14044, 14049, 14053, 14055, 14064,
+  14080, 14083, 14103, 14104
 
 * ISO C11 support:
 
diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h
index e57a23c057..325368e73b 100644
--- a/nscd/nscd-client.h
+++ b/nscd/nscd-client.h
@@ -1,5 +1,4 @@
-/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2011
-   Free Software Foundation, Inc.
+/* Copyright (c) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
 
@@ -322,6 +321,24 @@ struct locked_map_ptr
 };
 #define libc_locked_map_ptr(class, name) class struct locked_map_ptr name
 
+/* Try acquiring lock for mapptr, returns true if it succeeds, false
+   if not.  */
+static inline bool __nscd_acquire_maplock (volatile struct locked_map_ptr *mapptr)
+{
+  int cnt = 0;
+  while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
+								1, 0) != 0, 0))
+    {
+      // XXX Best number of rounds?
+      if (__builtin_expect (++cnt > 5, 0))
+	return false;
+
+      atomic_delay ();
+    }
+
+  return true;
+}
+
 
 /* Open socket connection to nscd server.  */
 extern int __nscd_open_socket (const char *key, size_t keylen,
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
index c1661f86d4..d64ad2e7b6 100644
--- a/nscd/nscd_gethst_r.c
+++ b/nscd/nscd_gethst_r.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1998-2005, 2006, 2007, 2008, 2009, 2011
-   Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -100,9 +99,18 @@ libc_freeres_fn (hst_map_free)
 uint32_t
 __nscd_get_nl_timestamp (void)
 {
+  uint32_t retval;
   if (__nss_not_use_nscd_hosts != 0)
     return 0;
 
+  /* __nscd_get_mapping can change hst_map_handle.mapped to NO_MAPPING.
+   However, __nscd_get_mapping assumes the prior value was not NO_MAPPING.
+   Thus we have to acquire the lock to prevent this thread from changing
+   hst_map_handle.mapped to NO_MAPPING while another thread is inside
+    __nscd_get_mapping.  */
+  if (!__nscd_acquire_maplock (&__hst_map_handle))
+    return 0;
+
   struct mapped_database *map = __hst_map_handle.mapped;
 
   if (map == NULL
@@ -112,9 +120,14 @@ __nscd_get_nl_timestamp (void)
     map = __nscd_get_mapping (GETFDHST, "hosts", &__hst_map_handle.mapped);
 
   if (map == NO_MAPPING)
-    return 0;
+    retval = 0;
+  else
+    retval = map->head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP];
+
+  /* Release the lock.  */
+  __hst_map_handle.lock = 0;
 
-  return map->head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP];
+  return retval;
 }
 
 
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 92558b6a51..96fb93db76 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -419,7 +419,6 @@ __nscd_get_mapping (request_type type, const char *key,
   return result;
 }
 
-
 struct mapped_database *
 __nscd_get_map_ref (request_type type, const char *name,
 		    volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
@@ -428,16 +427,8 @@ __nscd_get_map_ref (request_type type, const char *name,
   if (cur == NO_MAPPING)
     return cur;
 
-  int cnt = 0;
-  while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
-								1, 0) != 0, 0))
-    {
-      // XXX Best number of rounds?
-      if (__builtin_expect (++cnt > 5, 0))
-	return NO_MAPPING;
-
-      atomic_delay ();
-    }
+  if (!__nscd_acquire_maplock (mapptr))
+    return NO_MAPPING;
 
   cur = mapptr->mapped;