about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@redhat.com>2014-01-02 10:05:27 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2014-01-02 10:05:27 +0530
commit9a3c6a6ff602c88d7155139a7d7d0000b7b7e946 (patch)
tree021305585a78e7240421927f81151787e25e6b42
parentd41242129ba693cdbc8db85b846fcaccf9f0b7c4 (diff)
downloadglibc-9a3c6a6ff602c88d7155139a7d7d0000b7b7e946.tar.gz
glibc-9a3c6a6ff602c88d7155139a7d7d0000b7b7e946.tar.xz
glibc-9a3c6a6ff602c88d7155139a7d7d0000b7b7e946.zip
Fix return code from getent netgroup when the netgroup is not found (bz #16366)
nscd incorrectly returns a success even when the netgroup in question
is not found and adds a positive result in the cache.  this patch
fixes this behaviour by adding a negative lookup entry to cache and
returning an error when the netgroup is not found.
-rw-r--r--ChangeLog4
-rw-r--r--NEWS2
-rw-r--r--nscd/netgroupcache.c91
3 files changed, 67 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index dd7bd66970..33aa2bd2bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2013-01-02  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
+	[BZ #16366]
+	* nscd/netgroupcache.c (do_notfound): New function.
+	(addgetnetgrentX): Use it.
+
 	[BZ # 16365]
 	* nscd/netgroupcache.c (addgetnetgrentX): Break if status is
 	NSS_STATUS_NOTFOUND.
diff --git a/NEWS b/NEWS
index 869d3b9096..47ab1217de 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.19
   16038, 16041, 16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112,
   16143, 16144, 16146, 16150, 16151, 16153, 16167, 16172, 16195, 16214,
   16245, 16271, 16274, 16283, 16289, 16293, 16314, 16316, 16330, 16337,
-  16338, 16356, 16365, 16369, 16372, 16375, 16379.
+  16338, 16356, 16365, 16366, 16369, 16372, 16375, 16379.
 
 * Slovenian translations for glibc messages have been contributed by the
   Translation Project's Slovenian team of translators.
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index 50936ee7eb..9fc16640ae 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -65,6 +65,55 @@ struct dataset
   char strdata[0];
 };
 
+/* Sends a notfound message and prepares a notfound dataset to write to the
+   cache.  Returns true if there was enough memory to allocate the dataset and
+   returns the dataset in DATASETP, total bytes to write in TOTALP and the
+   timeout in TIMEOUTP.  KEY_COPY is set to point to the copy of the key in the
+   dataset. */
+static bool
+do_notfound (struct database_dyn *db, int fd, request_header *req,
+	       const char *key, struct dataset **datasetp, ssize_t *totalp,
+	       time_t *timeoutp, char **key_copy)
+{
+  struct dataset *dataset;
+  ssize_t total;
+  time_t timeout;
+  bool cacheable = false;
+
+  total = sizeof (notfound);
+  timeout = time (NULL) + db->negtimeout;
+
+  if (fd != -1)
+    TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
+
+  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
+  /* If we cannot permanently store the result, so be it.  */
+  if (dataset != NULL)
+    {
+      dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
+      dataset->head.recsize = total;
+      dataset->head.notfound = true;
+      dataset->head.nreloads = 0;
+      dataset->head.usable = true;
+
+      /* Compute the timeout time.  */
+      timeout = dataset->head.timeout = time (NULL) + db->negtimeout;
+      dataset->head.ttl = db->negtimeout;
+
+      /* This is the reply.  */
+      memcpy (&dataset->resp, &notfound, total);
+
+      /* Copy the key data.  */
+      memcpy (dataset->strdata, key, req->key_len);
+      *key_copy = dataset->strdata;
+
+      cacheable = true;
+    }
+  *timeoutp = timeout;
+  *totalp = total;
+  *datasetp = dataset;
+  return cacheable;
+}
 
 static time_t
 addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
@@ -84,6 +133,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
   struct dataset *dataset;
   bool cacheable = false;
   ssize_t total;
+  bool found = false;
 
   char *key_copy = NULL;
   struct __netgrent data;
@@ -103,35 +153,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
       && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
     {
       /* No such service.  */
-      total = sizeof (notfound);
-      timeout = time (NULL) + db->negtimeout;
-
-      if (fd != -1)
-	TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
-
-      dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
-      /* If we cannot permanently store the result, so be it.  */
-      if (dataset != NULL)
-	{
-	  dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
-	  dataset->head.recsize = total;
-	  dataset->head.notfound = true;
-	  dataset->head.nreloads = 0;
-	  dataset->head.usable = true;
-
-	  /* Compute the timeout time.  */
-	  timeout = dataset->head.timeout = time (NULL) + db->negtimeout;
-	  dataset->head.ttl = db->negtimeout;
-
-	  /* This is the reply.  */
-	  memcpy (&dataset->resp, &notfound, total);
-
-	  /* Copy the key data.  */
-	  memcpy (dataset->strdata, key, req->key_len);
-
-	  cacheable = true;
-	}
-
+      cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+			       &key_copy);
       goto writeout;
     }
 
@@ -167,6 +190,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 
 	  if (status == NSS_STATUS_SUCCESS)
 	    {
+	      found = true;
 	      union
 	      {
 		enum nss_status (*f) (struct __netgrent *, char *, size_t,
@@ -326,6 +350,15 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 	}
     }
 
+  /* No results.  Return a failure and write out a notfound record in the
+     cache.  */
+  if (!found)
+    {
+      cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+			       &key_copy);
+      goto writeout;
+    }
+
   total = buffilled;
 
   /* Fill in the dataset.  */