aboutsummaryrefslogtreecommitdiff
path: root/nscd/nscd_helper.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-31 13:33:18 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-31 13:33:18 +0000
commit32c075e1f01849e161724bbd400ba77244e482cc (patch)
tree5f083a3f352104f32bb6c902d57fa3f294bd8d4d /nscd/nscd_helper.c
parentd6220e9ee38c1c9285221b023346201ec5f511b3 (diff)
downloadglibc-32c075e1f01849e161724bbd400ba77244e482cc.zip
glibc-32c075e1f01849e161724bbd400ba77244e482cc.tar.gz
glibc-32c075e1f01849e161724bbd400ba77244e482cc.tar.bz2
.
Diffstat (limited to 'nscd/nscd_helper.c')
-rw-r--r--nscd/nscd_helper.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 7c45981..71ea53e 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002,2003,2004,2005,2006,2007
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -21,6 +22,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
+#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -186,6 +188,7 @@ get_mapping (request_type type, const char *key,
request_header req;
char key[keylen];
} reqdata;
+ size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
int sock = open_socket ();
if (sock < 0)
@@ -200,9 +203,9 @@ get_mapping (request_type type, const char *key,
# define MSG_NOSIGNAL 0
# endif
if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata,
- sizeof (reqdata),
+ real_sizeof_reqdata,
MSG_NOSIGNAL))
- != sizeof (reqdata), 0))
+ != real_sizeof_reqdata, 0))
/* We cannot even write the request. */
goto out_close2;
@@ -240,11 +243,12 @@ get_mapping (request_type type, const char *key,
!= keylen, 0))
goto out_close2;
- mapfd = *(int *) CMSG_DATA (cmsg);
+ if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL
+ || (CMSG_FIRSTHDR (&msg)->cmsg_len
+ != CMSG_LEN (sizeof (int))), 0))
+ goto out_close2;
- if (__builtin_expect (CMSG_FIRSTHDR (&msg)->cmsg_len
- != CMSG_LEN (sizeof (int)), 0))
- goto out_close;
+ mapfd = *(int *) CMSG_DATA (cmsg);
struct stat64 st;
if (__builtin_expect (strcmp (resdata, key) != 0, 0)
@@ -362,7 +366,10 @@ __nscd_get_map_ref (request_type type, const char *name,
}
-const struct datahead *
+/* Don't return const struct datahead *, as eventhough the record
+ is normally constant, it can change arbitrarily during nscd
+ garbage collection. */
+struct datahead *
__nscd_cache_search (request_type type, const char *key, size_t keylen,
const struct mapped_database *mapped)
{
@@ -374,16 +381,32 @@ __nscd_cache_search (request_type type, const char *key, size_t keylen,
{
struct hashentry *here = (struct hashentry *) (mapped->data + work);
+#ifndef _STRING_ARCH_unaligned
+ /* Although during garbage collection when moving struct hashentry
+ records around we first copy from old to new location and then
+ adjust pointer from previous hashentry to it, there is no barrier
+ between those memory writes. It is very unlikely to hit it,
+ so check alignment only if a misaligned load can crash the
+ application. */
+ if ((uintptr_t) here & (__alignof__ (*here) - 1))
+ return NULL;
+#endif
+
if (type == here->type
&& keylen == here->len
- && here->key + here->len <= datasize
+ && here->key + keylen <= datasize
&& memcmp (key, mapped->data + here->key, keylen) == 0
&& here->packet + sizeof (struct datahead) <= datasize)
{
/* We found the entry. Increment the appropriate counter. */
- const struct datahead *dh
+ struct datahead *dh
= (struct datahead *) (mapped->data + here->packet);
+#ifndef _STRING_ARCH_unaligned
+ if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
+ return NULL;
+#endif
+
/* See whether we must ignore the entry or whether something
is wrong because garbage collection is in progress. */
if (dh->usable && here->packet + dh->allocsize <= datasize)