2.8-2 fedora-glibc-2_8-2
authorjakub <jakub>
Wed, 30 Apr 2008 12:11:28 +0000 (12:11 +0000)
committerjakub <jakub>
Wed, 30 Apr 2008 12:11:28 +0000 (12:11 +0000)
15 files changed:
ChangeLog
fedora/glibc.spec.in
nptl/ChangeLog
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
nscd/aicache.c
nscd/cache.c
nscd/connections.c
nscd/grpcache.c
nscd/hstcache.c
nscd/initgrcache.c
nscd/mem.c
nscd/nscd.h
nscd/pwdcache.c
nscd/servicescache.c
sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c

index f1969c4..826b080 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2008-04-25  David S. Miller  <davem@davemloft.net>
+
+       * sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c (semctl):
+       Pass "union semun" properly in to sys_ipc, it must be passed
+       by value, not by reference.
+
+2008-04-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * nscd/Makefile (nscd-cflags): Set back to -fpie.
+       * nscd/nscd.h (mem_in_flight): Add attribute_tls_model_ie.
+       * nscd/connections.c (mem_in_flight): Likewise.
+
+       * nscd/nscd.h (dbs): Make hidden.
+
+2008-04-15  Ulrich Drepper  <drepper@redhat.com>
+
+       [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.
+
 2008-04-11  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/unix/sysv/linux/powerpc/bits/mathinline.h (__signbitl):
index 2b39ca9..c58ba1b 100644 (file)
@@ -19,7 +19,7 @@
 Summary: The GNU libc libraries
 Name: glibc
 Version: @glibcversion@
-Release: 1
+Release: 2
 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
 # Things that are linked directly into dynamically linked programs
 # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
@@ -976,6 +976,11 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Wed Apr 30 2008 Jakub Jelinek <jakub@redhat.com> 2.8-2
+- fix nscd races during GC (BZ#5381)
+- rebuilt with fixed GCC to fix regex miscompilation on power6
+- SPARC fixes
+
 * Sat Apr 12 2008 Jakub Jelinek <jakub@redhat.com> 2.8-1
 - 2.8 release
 
index 63b0eab..ba94a95 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-14  David S. Miller  <davem@davemloft.net>
+
+       * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
+       (__old_sem_wait): Fix argument to lll_futex_wait().
+
 2007-11-26  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * pthread_create.c: Require pthread_mutex_trylock and
index 3c71c96..b14f976 100644 (file)
@@ -155,7 +155,7 @@ __old_sem_wait (sem_t *sem)
       /* Enable asynchronous cancellation.  Required by the standard.  */
       int oldtype = __pthread_enable_asynccancel ();
 
-      err = lll_futex_wait (futex, 0,
+      err = lll_futex_wait (&isem->value, 0,
                            isem->private ^ FUTEX_PRIVATE_FLAG);
 
       /* Disable asynchronous cancellation.  */
index a69a778..3de8482 100644 (file)
@@ -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)
        {
index 12c4f01..7e9b0dc 100644 (file)
@@ -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;
 }
 
index 5da5e5f..15148bd 100644 (file)
@@ -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 attribute_tls_model_ie;
+/* 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:
index 002f04f..57fcd0f 100644 (file)
@@ -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.  */
index cc04158..7777723 100644 (file)
@@ -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.  */
index 157cd78..6a95fb5 100644 (file)
@@ -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.  */
index 048e3dd..508d934 100644 (file)
@@ -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);
index ec2d945..66813e7 100644 (file)
@@ -130,7 +130,7 @@ struct database_dyn
 
 
 /* Global variables.  */
-extern struct database_dyn dbs[lastdb];
+extern struct database_dyn dbs[lastdb] attribute_hidden;
 extern const char *const dbnames[lastdb];
 extern const char *const serv2str[LASTREQ];
 
@@ -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 attribute_tls_model_ie;
+/* 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);
 
 
index bc1b6ba..3d1e824 100644 (file)
@@ -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.  */
index e122cb3..e2d1e26 100644 (file)
@@ -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.  */
index 057e287..4f826b1 100644 (file)
@@ -54,5 +54,5 @@ semctl (int semid, int semnum, int cmd, ...)
   va_end (ap);
 
   return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd,
-                        CHECK_SEMCTL (&arg, semid, cmd));
+                        CHECK_SEMCTL (&arg, semid, cmd)->array);
 }