diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-05-15 21:17:08 -0700 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-05-15 21:17:08 -0700 |
commit | cfe1fc1013d0e7e4863c974fa0e78891cc0a2ed2 (patch) | |
tree | 77134fa880e4dd6db41a701034607e67a4dd9be1 | |
parent | 3b1b533bc3239ef6df1e40e0088e7270ac060be6 (diff) | |
download | glibc-cfe1fc1013d0e7e4863c974fa0e78891cc0a2ed2.zip glibc-cfe1fc1013d0e7e4863c974fa0e78891cc0a2ed2.tar.gz glibc-cfe1fc1013d0e7e4863c974fa0e78891cc0a2ed2.tar.bz2 |
Robustify libc-side nscd database reader.
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.
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | nscd/nscd-client.h | 5 | ||||
-rw-r--r-- | nscd/nscd_getai.c | 5 | ||||
-rw-r--r-- | nscd/nscd_getgr_r.c | 5 | ||||
-rw-r--r-- | nscd/nscd_gethst_r.c | 6 | ||||
-rw-r--r-- | nscd/nscd_getpw_r.c | 5 | ||||
-rw-r--r-- | nscd/nscd_getserv_r.c | 5 | ||||
-rw-r--r-- | nscd/nscd_helper.c | 27 | ||||
-rw-r--r-- | nscd/nscd_initgroups.c | 5 |
9 files changed, 60 insertions, 30 deletions
@@ -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. @@ -22,13 +29,17 @@ * 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. diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index 3c9688f..f66a658 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -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. */ diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c index 674a5e7..d1c5cd1 100644 --- a/nscd/nscd_getai.c +++ b/nscd/nscd_getai.c @@ -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); diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index b84b06b..c2d204c 100644 --- a/nscd/nscd_getgr_r.c +++ b/nscd/nscd_getgr_r.c @@ -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); diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index aea8288..70631fa 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -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); diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index 21f792b..8a4449d 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -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); diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c index b1ad7e2..dce4165 100644 --- a/nscd/nscd_getserv_r.c +++ b/nscd/nscd_getserv_r.c @@ -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) { diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index cd3fa24..db24796 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -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; } diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c index 866455a..5ff60c0 100644 --- a/nscd/nscd_initgroups.c +++ b/nscd/nscd_initgroups.c @@ -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); |