summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-04-30 12:11:31 +0000
committerJakub Jelinek <jakub@redhat.com>2008-04-30 12:11:31 +0000
commitef73dbc1301bc42c132d15ae6ca866233c0beeb4 (patch)
tree7386ab88c4f2c43ac417a2ea0b0b19239bdc0b19
parent14e44061ad888abbea7239599a9109b41776e41c (diff)
-rw-r--r--ChangeLog40
-rw-r--r--fedora/glibc.spec.in7
-rw-r--r--nptl/ChangeLog5
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c2
-rw-r--r--nscd/aicache.c9
-rw-r--r--nscd/cache.c11
-rw-r--r--nscd/connections.c47
-rw-r--r--nscd/grpcache.c9
-rw-r--r--nscd/hstcache.c9
-rw-r--r--nscd/initgrcache.c9
-rw-r--r--nscd/mem.c33
-rw-r--r--nscd/nscd.h30
-rw-r--r--nscd/pwdcache.c9
-rw-r--r--nscd/servicescache.c9
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c2
15 files changed, 203 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index f1969c4e33..826b080137 100644
--- 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):
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index 2b39ca9e26..c58ba1b48f 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -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
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 63b0eab9c3..ba94a95dac 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -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
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
index 3c71c969b8..b14f976a61 100644
--- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
@@ -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. */
diff --git a/nscd/aicache.c b/nscd/aicache.c
index a69a7781d3..3de84821a4 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -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..7e9b0dc2df 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -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..15148bdf3d 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 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:
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
index 002f04fb3e..57fcd0f7d2 100644
--- a/nscd/grpcache.c
+++ b/nscd/grpcache.c
@@ -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..7777723463 100644
--- a/nscd/hstcache.c
+++ b/nscd/hstcache.c
@@ -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..6a95fb5992 100644
--- a/nscd/initgrcache.c
+++ b/nscd/initgrcache.c
@@ -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..508d9343d0 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -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..66813e7480 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -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);
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
index bc1b6bab2f..3d1e8241ec 100644
--- a/nscd/pwdcache.c
+++ b/nscd/pwdcache.c
@@ -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..e2d1e26a2f 100644
--- a/nscd/servicescache.c
+++ b/nscd/servicescache.c
@@ -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. */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c b/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c
index 057e287828..4f826b156d 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c
@@ -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);
}