about summary refs log tree commit diff
path: root/nscd
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-04-19 16:42:41 +0000
committerUlrich Drepper <drepper@redhat.com>2008-04-19 16:42:41 +0000
commitc52137d39101515cacb67a2bcd43b77bd06284e0 (patch)
tree301583f49438de52f3a7cf54676d958b4158ec8f /nscd
parent87a71b8d67e501d422528b8435e733e8e78a165a (diff)
downloadglibc-c52137d39101515cacb67a2bcd43b77bd06284e0.tar.gz
glibc-c52137d39101515cacb67a2bcd43b77bd06284e0.tar.xz
glibc-c52137d39101515cacb67a2bcd43b77bd06284e0.zip
[BZ #5209, BZ #5381]
2008-04-15  Ulrich Drepper  <drepper@redhat.com>
	[BZ #5209]
	* sysdeps/unix/sysv/linux/times.c: New file.

	[BZ #5381]
	* nscd/nscd.h: Define enum in_flight, mem_in_flight, and
	mem_in_flight_list variables.  Add new parameter to mempool_alloc
	prototype.
	* nscd/mem.c (mempool_alloc): Take additional parameter.  Initialize
	appropriate mem_in_flight element.
	(gc): Take allocations which have not yet been committed to the
	database into account.
	* nscd/cache.c (cache_add): Add new parameter to mempool_alloc call.
	Reset mem_in_flight before returning.
	* nscd/connections.c (nscd_run_worker): Initialize mem_in_flight and
	cue it up in mem_in_flight_list.
	* nscd/aicache.c: Adjust mempool_alloc call.
	* nscd/grpcache.c: Likewise.
	* nscd/hstcache.c: Likewise.
	* nscd/initgrcache.c: Likewise.
	* nscd/pwdcache.c: Likewise.
	* nscd/servicescache.c: Likewise.
	* nscd/Makefile (nscd-flags): Until ld is fixed, use -fpic instead
	of -fpie.

	* nscd/connections.c (handle_request): Provide better error message
	in case SELinux forbids the service.

	* version.h (VERSION): Bump to 2.8.90.
Diffstat (limited to 'nscd')
-rw-r--r--nscd/Makefile5
-rw-r--r--nscd/aicache.c11
-rw-r--r--nscd/cache.c13
-rw-r--r--nscd/connections.c47
-rw-r--r--nscd/grpcache.c11
-rw-r--r--nscd/hstcache.c11
-rw-r--r--nscd/initgrcache.c11
-rw-r--r--nscd/mem.c35
-rw-r--r--nscd/nscd.h28
-rw-r--r--nscd/pwdcache.c11
-rw-r--r--nscd/servicescache.c11
11 files changed, 160 insertions, 34 deletions
diff --git a/nscd/Makefile b/nscd/Makefile
index f83e40049a..74df824769 100644
--- a/nscd/Makefile
+++ b/nscd/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007
+# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007,2008
 #	Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
@@ -90,7 +90,8 @@ CFLAGS-nscd_initgroups.c = -fexceptions
 
 nscd-cflags = -DIS_IN_nscd=1 -D_FORTIFY_SOURCE=2
 ifeq (yesyes,$(have-fpie)$(build-shared))
-nscd-cflags += -fpie
+#nscd-cflags += -fpie
+nscd-cflags += -fpic
 endif
 ifeq (yes,$(have-ssp))
 nscd-cflags += -fstack-protector
diff --git a/nscd/aicache.c b/nscd/aicache.c
index a69a7781d3..2518f80128 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -1,5 +1,5 @@
 /* Cache handling for host lookup.
-   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -262,7 +262,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 		{
 		  dataset = (struct dataset *) mempool_alloc (db,
 							      total
-							      + req->key_len);
+							      + req->key_len,
+							      IDX_result_data);
 		  if (dataset == NULL)
 		    ++db->head->addfailed;
 		}
@@ -338,7 +339,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 		      struct dataset *newp
 			= (struct dataset *) mempool_alloc (db,
 							    total
-							    + req->key_len);
+							    + req->key_len,
+							    IDX_result_data);
 		      if (__builtin_expect (newp != NULL, 1))
 			{
 			  /* Adjust pointer into the memory block.  */
@@ -424,7 +426,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
       if (fd != -1)
 	TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
 
-      dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+      dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+			       IDX_result_data);
       /* If we cannot permanently store the result, so be it.  */
       if (dataset != NULL)
 	{
diff --git a/nscd/cache.c b/nscd/cache.c
index 12c4f01e40..b1dc2c5052 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998, 1999, 2003-2006, 2007 Free Software Foundation, Inc.
+/* Copyright (c) 1998, 1999, 2003-2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -155,11 +155,16 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet,
   unsigned long int hash = __nis_hash (key, len) % table->head->module;
   struct hashentry *newp;
 
-  newp = mempool_alloc (table, sizeof (struct hashentry));
+  newp = mempool_alloc (table, sizeof (struct hashentry), IDX_record_data);
   /* If we cannot allocate memory, just do not do anything.  */
   if (newp == NULL)
     {
       ++table->head->addfailed;
+
+      /* Mark the in-flight memory as unused.  */
+      for (enum in_flight idx = 0; idx < IDX_record_data; ++idx)
+	mem_in_flight.block[idx].dbidx = -1;
+
       return -1;
     }
 
@@ -215,6 +220,10 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet,
     else
       next_wakeup = table->wakeup_time;
 
+  /* Mark the in-flight memory as unused.  */
+  for (enum in_flight idx = 0; idx < IDX_last; ++idx)
+    mem_in_flight.block[idx].dbidx = -1;
+
   return 0;
 }
 
diff --git a/nscd/connections.c b/nscd/connections.c
index 5da5e5f08a..64c82cb892 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -225,6 +225,11 @@ static int sock;
 /* Number of times clients had to wait.  */
 unsigned long int client_queued;
 
+/* Data structure for recording in-flight memory allocation.  */
+__thread struct mem_in_flight mem_in_flight;
+/* Global list of the mem_in_flight variables of all the threads.  */
+struct mem_in_flight *mem_in_flight_list;
+
 
 ssize_t
 writeall (int fd, const void *buf, size_t len)
@@ -964,7 +969,7 @@ send_ro_fd (struct database_dyn *db, char *key, int fd)
 
 /* Handle new request.  */
 static void
-handle_request (int fd, request_header *req, void *key, uid_t uid)
+handle_request (int fd, request_header *req, void *key, uid_t uid, pid_t pid)
 {
   if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
     {
@@ -979,7 +984,31 @@ cannot handle old request version %d; current version is %d"),
   if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0)
     {
       if (debug_level > 0)
-	dbg_log (_("request not handled due to missing permission"));
+	{
+#ifdef SO_PEERCRED
+# ifdef PATH_MAX
+	  char buf[PATH_MAX];
+# else
+	  char buf[4096];
+# endif
+
+	  snprintf (buf, sizeof (buf), "/proc/%ld/exe", (long int) pid);
+	  ssize_t n = readlink (buf, buf, sizeof (buf) - 1);
+
+	  if (n <= 0)
+	    dbg_log (_("\
+request from %ld not handled due to missing permission"), (long int) pid);
+	  else
+	    {
+	      buf[n] = '\0';
+	      dbg_log (_("\
+request from '%s' [%ld] not handled due to missing permission"),
+		       buf, (long int) pid);
+	    }
+#else
+	  dbg_log (_("request not handled due to missing permission"));
+#endif
+	}
       return;
     }
 
@@ -1426,6 +1455,16 @@ nscd_run_worker (void *p)
 {
   char buf[256];
 
+  /* Initialize the memory-in-flight list.  */
+  for (enum in_flight idx = 0; idx < IDX_last; ++idx)
+    mem_in_flight.block[idx].dbidx = -1;
+  /* And queue this threads structure.  */
+  do
+    mem_in_flight.next = mem_in_flight_list;
+  while (atomic_compare_and_exchange_bool_acq (&mem_in_flight_list,
+					       &mem_in_flight,
+					       mem_in_flight.next) != 0);
+
   /* Initial locking.  */
   pthread_mutex_lock (&readylist_lock);
 
@@ -1491,6 +1530,8 @@ nscd_run_worker (void *p)
 	  if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
 	    pid = caller.pid;
 	}
+#else
+      const pid_t pid = 0;
 #endif
 
       /* It should not be possible to crash the nscd with a silly
@@ -1531,7 +1572,7 @@ handle_request: request received (Version = %d)"), req.version);
 	    }
 
 	  /* Phew, we got all the data, now process it.  */
-	  handle_request (fd, &req, keybuf, uid);
+	  handle_request (fd, &req, keybuf, uid, pid);
 	}
 
     close_and_out:
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
index 002f04fb3e..dbc406fcbd 100644
--- a/nscd/grpcache.c
+++ b/nscd/grpcache.c
@@ -1,5 +1,5 @@
 /* Cache handling for group lookup.
-   Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -113,7 +113,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
 	  written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
 					      MSG_NOSIGNAL));
 
-	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+				   IDX_result_data);
 	  /* If we cannot permanently store the result, so be it.  */
 	  if (dataset != NULL)
 	    {
@@ -204,7 +205,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
 
       if (he == NULL)
 	{
-	  dataset = (struct dataset *) mempool_alloc (db, total + n);
+	  dataset = (struct dataset *) mempool_alloc (db, total + n,
+						      IDX_result_data);
 	  if (dataset == NULL)
 	    ++db->head->addfailed;
 	}
@@ -274,7 +276,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
 	      /* We have to create a new record.  Just allocate
 		 appropriate memory and copy it.  */
 	      struct dataset *newp
-		= (struct dataset *) mempool_alloc (db, total + n);
+		= (struct dataset *) mempool_alloc (db, total + n,
+						    IDX_result_data);
 	      if (newp != NULL)
 		{
 		  /* Adjust pointers into the memory block.  */
diff --git a/nscd/hstcache.c b/nscd/hstcache.c
index cc041581e1..b93d418878 100644
--- a/nscd/hstcache.c
+++ b/nscd/hstcache.c
@@ -1,5 +1,5 @@
 /* Cache handling for host lookup.
-   Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -121,7 +121,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
 	    written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
 						MSG_NOSIGNAL));
 
-	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+				   IDX_result_data);
 	  /* If we cannot permanently store the result, so be it.  */
 	  if (dataset != NULL)
 	    {
@@ -226,7 +227,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
       if (he == NULL && h_addr_list_cnt == 1)
 	{
 	  dataset = (struct dataset *) mempool_alloc (db,
-						      total + req->key_len);
+						      total + req->key_len,
+						      IDX_result_data);
 	  if (dataset == NULL)
 	    ++db->head->addfailed;
 	}
@@ -312,7 +314,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
 		     appropriate memory and copy it.  */
 		  struct dataset *newp
 		    = (struct dataset *) mempool_alloc (db,
-							total + req->key_len);
+							total + req->key_len,
+							IDX_result_data);
 		  if (newp != NULL)
 		    {
 		      /* Adjust pointers into the memory block.  */
diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c
index 157cd7860c..4d6513b5d7 100644
--- a/nscd/initgrcache.c
+++ b/nscd/initgrcache.c
@@ -1,5 +1,5 @@
 /* Cache handling for host lookup.
-   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -197,7 +197,8 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
 	    written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
 						MSG_NOSIGNAL));
 
-	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+				   IDX_result_data);
 	  /* If we cannot permanently store the result, so be it.  */
 	  if (dataset != NULL)
 	    {
@@ -259,7 +260,8 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
       if (he == NULL)
 	{
 	  dataset = (struct dataset *) mempool_alloc (db,
-						      total + req->key_len);
+						      total + req->key_len,
+						      IDX_result_data);
 	  if (dataset == NULL)
 	    ++db->head->addfailed;
 	}
@@ -329,7 +331,8 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
 	      /* We have to create a new record.  Just allocate
 		 appropriate memory and copy it.  */
 	      struct dataset *newp
-		= (struct dataset *) mempool_alloc (db, total + req->key_len);
+		= (struct dataset *) mempool_alloc (db, total + req->key_len,
+						    IDX_result_data);
 	      if (newp != NULL)
 		{
 		  /* Adjust pointer into the memory block.  */
diff --git a/nscd/mem.c b/nscd/mem.c
index 048e3ddd32..14928d633c 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -1,5 +1,5 @@
 /* Cache memory handling.
-   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -197,6 +197,31 @@ gc (struct database_dyn *db)
     }
   assert (cnt == db->head->nentries);
 
+  /* Go through the list of in-flight memory blocks.  */
+  struct mem_in_flight *mrunp = mem_in_flight_list;
+  while (mrunp != NULL)
+    {
+      /* NB: There can be no race between this test and another thread
+        setting the field to the index we are looking for because
+        this would require the other thread to also have the memlock
+        for the database.
+
+	NB2: we do not have to look at latter blocks (higher indices) if
+	earlier blocks are not in flight.  They are always allocated in
+	sequence.  */
+      for (enum in_flight idx = IDX_result_data;
+	   idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx)
+	{
+	 assert ((char *) mrunp->block[idx].blockaddr > db->data);
+	 assert ((char *) mrunp->block[idx].blockaddr
+		 + mrunp->block[0].blocklen <= db->data + db->memsize);
+	 markrange (mark, (char *) mrunp->block[idx].blockaddr -  db->data,
+		    mrunp->block[idx].blocklen);
+	}
+
+      mrunp = mrunp->next;
+    }
+
   /* Sort the entries by the addresses of the referenced data.  All
      the entries pointing to the same DATAHEAD object will have the
      same key.  Stability of the sorting is unimportant.  */
@@ -503,7 +528,7 @@ gc (struct database_dyn *db)
 
 
 void *
-mempool_alloc (struct database_dyn *db, size_t len)
+mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx)
 {
   /* Make sure LEN is a multiple of our maximum alignment so we can
      keep track of used memory is multiples of this alignment value.  */
@@ -567,6 +592,12 @@ mempool_alloc (struct database_dyn *db, size_t len)
       db->head->first_free += len;
 
       db->last_alloc_failed = false;
+
+      /* Remember that we have allocated this memory.  */
+      assert (idx >= 0 && idx < IDX_last);
+      mem_in_flight.block[idx].dbidx = db - dbs;
+      mem_in_flight.block[idx].blocklen = len;
+      mem_in_flight.block[idx].blockaddr = res;
     }
 
   pthread_mutex_unlock (&db->memlock);
diff --git a/nscd/nscd.h b/nscd/nscd.h
index ec2d9454ca..cbea8e1a96 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -181,6 +181,31 @@ extern uid_t old_uid;
 extern gid_t old_gid;
 
 
+/* Memory allocation in flight.  Each thread can have a limited number
+   of allocation in flight.  No need to create dynamic data
+   structures.  We use fixed indices.  */
+enum in_flight
+  {
+    IDX_result_data = 0,
+    /* Keep the IDX_record_data entry last at all times.  */
+    IDX_record_data = 1,
+    IDX_last
+  };
+extern __thread struct mem_in_flight
+{
+  struct
+  {
+    int dbidx;
+    nscd_ssize_t blocklen;
+    void *blockaddr;
+  } block[IDX_last];
+
+  struct mem_in_flight *next;
+} mem_in_flight;
+/* Global list of the mem_in_flight variables of all the threads.  */
+extern struct mem_in_flight *mem_in_flight_list;
+
+
 /* Prototypes for global functions.  */
 
 /* nscd.c */
@@ -271,7 +296,8 @@ extern void readdservbyport (struct database_dyn *db, struct hashentry *he,
 			     struct datahead *dh);
 
 /* mem.c */
-extern void *mempool_alloc (struct database_dyn *db, size_t len);
+extern void *mempool_alloc (struct database_dyn *db, size_t len,
+			    enum in_flight idx);
 extern void gc (struct database_dyn *db);
 
 
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
index bc1b6bab2f..e1bf6e9518 100644
--- a/nscd/pwdcache.c
+++ b/nscd/pwdcache.c
@@ -1,5 +1,5 @@
 /* Cache handling for passwd lookup.
-   Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -120,7 +120,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
 	    written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
 						MSG_NOSIGNAL));
 
-	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+				   IDX_result_data);
 	  /* If we cannot permanently store the result, so be it.  */
 	  if (dataset != NULL)
 	    {
@@ -199,7 +200,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
 
       if (he == NULL)
 	{
-	  dataset = (struct dataset *) mempool_alloc (db, total + n);
+	  dataset = (struct dataset *) mempool_alloc (db, total + n,
+						      IDX_result_data);
 	  if (dataset == NULL)
 	    ++db->head->addfailed;
 	}
@@ -270,7 +272,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
 	      /* We have to create a new record.  Just allocate
 		 appropriate memory and copy it.  */
 	      struct dataset *newp
-		= (struct dataset *) mempool_alloc (db, total + n);
+		= (struct dataset *) mempool_alloc (db, total + n,
+						    IDX_result_data);
 	      if (newp != NULL)
 		{
 		  /* Adjust pointer into the memory block.  */
diff --git a/nscd/servicescache.c b/nscd/servicescache.c
index e122cb3f16..164b6e298d 100644
--- a/nscd/servicescache.c
+++ b/nscd/servicescache.c
@@ -1,5 +1,5 @@
 /* Cache handling for services lookup.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@drepper.com>, 2007.
 
@@ -103,7 +103,8 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req,
 	  written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
 					      MSG_NOSIGNAL));
 
-	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
+	  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
+				   IDX_result_data);
 	  /* If we cannot permanently store the result, so be it.  */
 	  if (dataset != NULL)
 	    {
@@ -190,7 +191,8 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req,
       if (he == NULL)
 	{
 	  dataset = (struct dataset *) mempool_alloc (db,
-						      total + req->key_len);
+						      total + req->key_len,
+						      IDX_result_data);
 	  if (dataset == NULL)
 	    ++db->head->addfailed;
 	}
@@ -261,7 +263,8 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req,
 	      /* We have to create a new record.  Just allocate
 		 appropriate memory and copy it.  */
 	      struct dataset *newp
-		= (struct dataset *) mempool_alloc (db, total + req->key_len);
+		= (struct dataset *) mempool_alloc (db, total + req->key_len,
+						    IDX_result_data);
 	      if (newp != NULL)
 		{
 		  /* Adjust pointers into the memory block.  */