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.
This commit is contained in:
Jakub Jelinek 2009-05-15 21:17:08 -07:00 committed by Ulrich Drepper
parent 3b1b533bc3
commit cfe1fc1013
9 changed files with 60 additions and 30 deletions

View File

@ -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.

View 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. */

View 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);

View 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);

View 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);

View 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);

View 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)
{

View 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;
}

View 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);