]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Robustify libc-side nscd database reader.
authorJakub Jelinek <jakub@redhat.com>
Sat, 16 May 2009 04:17:08 +0000 (21:17 -0700)
committerUlrich Drepper <drepper@redhat.com>
Sat, 16 May 2009 04:17:08 +0000 (21:17 -0700)
The nscd database mapped in processes can change at any time.  We
have to be more vigilant when it comes to using that memory.  Test
the data entries are valid in their entire size, don't read data
again from memory once we verified it, and make sure the trailing
pointer is not going off the deep end.

ChangeLog
nscd/nscd-client.h
nscd/nscd_getai.c
nscd/nscd_getgr_r.c
nscd/nscd_gethst_r.c
nscd/nscd_getpw_r.c
nscd/nscd_getserv_r.c
nscd/nscd_helper.c
nscd/nscd_initgroups.c

index 26ebd219a175ab33d841e55bafc8eb020364e4d2..aa415cbac21438ea0aad0883a46bfce63fd7cb00 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,18 @@
-2009-05-12  Jakub Jelinek  <jakub@redhat.com>
-
-       * include/atomic.h: Formatting.
-       (catomic_compare_and_exchange_val_acq): Don't define if already
-       defined by bits/atomic.h.
-
 2009-05-14  Jakub Jelinek  <jakub@redhat.com>
 
+       * nscd/nscd_helper.c: Include stddef.h.
+       (__nscd_cache_search): Add datalen argument.  Use atomic_forced_read
+       in a couple of places.  Return NULL if trail is not less than
+       datasize, don't consider dataheads with length smaller than
+       offsetof (struct datahead, data) + datalen.
+       * nscd/nscd_client.h (__nscd_cache_search): Adjust prototype.
+       * nscd/nscd_gethst_r.c (nscd_gethst_r): Adjust callers.
+       * nscd/nscd_getpw_r.c (nscd_getpw_r): Likewise.
+       * nscd/nscd_getgr_r.c (nscd_getgr_r): Likewise.
+       * nscd/nscd_getai.c (__nscd_getai): Likewise.
+       * nscd/nscd_initgroups.c (__nscd_getgrouplist): Likewise.
+       * nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
+
        * sysdeps/unix/sysv/linux/i386/fallocate64.c (__fallocate64_l64):
        Rename ...
        (fallocate64): ... to this.
        * sysdeps/unix/sysv/linux/sparc/sparc32/Versions (libc): Likewise.
        * sysdeps/unix/sysv/linux/sh/Versions (libc): Likewise.
 
-2009-05-14  Jakub Jelinek  <jakub@redhat.com>
-
        * nscd/selinux.c (nscd_avc_destroy): Removed.
        * nscd/selinux.h (nscd_avc_destroy): Likewise.
        * nscd/nscd.c (termination_handler): Don't call
        nscd_avc_destroy.
 
+2009-05-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * include/atomic.h: Formatting.
+       (catomic_compare_and_exchange_val_acq): Don't define if already
+       defined by bits/atomic.h.
+
 2009-05-15  Ulrich Drepper  <drepper@redhat.com>
 
        * math/libm-test.inc (expm1_test): Add test for range error.
index 3c9688fd30f48278ff14ac6d1915e3e37f746fe6..f66a658d2a8fb402d3f961ae74e96bd208184b3b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007
+/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@@ -329,7 +329,8 @@ static inline int __nscd_drop_map_ref (struct mapped_database *map,
 extern struct datahead *__nscd_cache_search (request_type type,
                                             const char *key,
                                             size_t keylen,
-                                            const struct mapped_database *mapped);
+                                            const struct mapped_database *mapped,
+                                            size_t datalen);
 
 /* Wrappers around read, readv and write that only read/write less than LEN
    bytes on error or EOF.  */
index 674a5e751463a12931076398bc9a785330df799d..d1c5cd14e97414fb9043374b62779c95103cf499 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -75,7 +76,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
   if (mapped != NO_MAPPING)
     {
       struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
-                                                   mapped);
+                                                   mapped, sizeof ai_resp);
       if (found != NULL)
        {
          respdata = (char *) (&found->data[0].aidata + 1);
index b84b06b3ce68b6c3721d1cd9f7b3b43347c713d0..c2d204c3c801952da6f3375bbbb2e674bb33497d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2000, 2002-2005, 2006, 2007
+/* Copyright (C) 1998-2000, 2002-2005, 2006, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998.
@@ -107,7 +107,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 
   if (mapped != NO_MAPPING)
     {
-      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped,
+                                                   sizeof gr_resp);
       if (found != NULL)
        {
          len = (const uint32_t *) (&found->data[0].grdata + 1);
index aea8288594586451908944f1d4c1572eba3aea37..70631fa9610b378741fb53b5c1ff65cce67e1f85 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -137,7 +138,8 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
   if (mapped != NO_MAPPING)
     {
       /* No const qualifier, as it can change during garbage collection.  */
-      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped,
+                                                   sizeof hst_resp);
       if (found != NULL)
        {
          h_name = (char *) (&found->data[0].hstdata + 1);
index 21f792bb4eb9878593d77fa8e557f8a8e9074e57..8a4449d1864c4dd84de7a45a2f514095fc3b5ef4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2003, 2004, 2005, 2007
+/* Copyright (C) 1998, 1999, 2003, 2004, 2005, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998.
@@ -104,7 +104,8 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
 
   if (mapped != NO_MAPPING)
     {
-      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped,
+                                                   sizeof pw_resp);
       if (found != NULL)
        {
          pw_name = (const char *) (&found->data[0].pwdata + 1);
index b1ad7e2e43091d76bbcad7133eab3aa3762d70f5..dce41654821e9bcfc20b6a10f576325952abda2a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
 
@@ -104,7 +104,8 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 
   if (mapped != NO_MAPPING)
     {
-      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
+      struct datahead *found = __nscd_cache_search (type, key, keylen, mapped,
+                                                   sizeof serv_resp);
 
       if (found != NULL)
        {
index cd3fa24196e3e940214cfd188946ec694f8e18a7..db247962b95f77f3fcd562c7ba25f606f6cb1390 100644 (file)
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
+#include <stddef.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
@@ -472,18 +473,20 @@ __nscd_get_map_ref (request_type type, const char *name,
    garbage collection.  */
 struct datahead *
 __nscd_cache_search (request_type type, const char *key, size_t keylen,
-                    const struct mapped_database *mapped)
+                    const struct mapped_database *mapped, size_t datalen)
 {
   unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
   size_t datasize = mapped->datasize;
 
   ref_t trail = mapped->head->array[hash];
+  trail = atomic_forced_read (trail);
   ref_t work = trail;
   int tick = 0;
 
   while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
     {
       struct hashentry *here = (struct hashentry *) (mapped->data + work);
+      ref_t here_key, here_packet;
 
 #ifndef _STRING_ARCH_unaligned
       /* Although during garbage collection when moving struct hashentry
@@ -498,13 +501,14 @@ __nscd_cache_search (request_type type, const char *key, size_t keylen,
 
       if (type == here->type
          && keylen == here->len
-         && here->key + keylen <= datasize
-         && memcmp (key, mapped->data + here->key, keylen) == 0
-         && here->packet + sizeof (struct datahead) <= datasize)
+         && (here_key = atomic_forced_read (here->key)) + keylen <= datasize
+         && memcmp (key, mapped->data + here_key, keylen) == 0
+         && ((here_packet = atomic_forced_read (here->packet))
+             + sizeof (struct datahead) <= datasize))
        {
          /* We found the entry.  Increment the appropriate counter.  */
          struct datahead *dh
-           = (struct datahead *) (mapped->data + here->packet);
+           = (struct datahead *) (mapped->data + here_packet);
 
 #ifndef _STRING_ARCH_unaligned
          if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
@@ -513,11 +517,14 @@ __nscd_cache_search (request_type type, const char *key, size_t keylen,
 
          /* 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)
+         if (dh->usable
+             && here_packet + dh->allocsize <= datasize
+             && (here_packet + offsetof (struct datahead, data) + datalen
+                 <= datasize))
            return dh;
        }
 
-      work = here->next;
+      work = atomic_forced_read (here->next);
       /* Prevent endless loops.  This should never happen but perhaps
         the database got corrupted, accidentally or deliberately.  */
       if (work == trail)
@@ -532,7 +539,11 @@ __nscd_cache_search (request_type type, const char *key, size_t keylen,
          if ((uintptr_t) trailelem & (__alignof__ (*trailelem) - 1))
            return NULL;
 #endif
-         trail = trailelem->next;
+
+         if (trail + sizeof (struct hashentry) > datasize)
+           return NULL;
+
+         trail = atomic_forced_read (trailelem->next);
        }
       tick = 1 - tick;
     }
index 866455a96c09503d813c62bb2242a18d384d826f..5ff60c080c0d43f4be8d2ce3a3fdc578ce234f87 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -55,7 +55,8 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
   if (mapped != NO_MAPPING)
     {
       struct datahead *found = __nscd_cache_search (INITGROUPS, user,
-                                                   userlen, mapped);
+                                                   userlen, mapped,
+                                                   sizeof initgr_resp);
       if (found != NULL)
        {
          respdata = (char *) (&found->data[0].initgrdata + 1);