diff options
Diffstat (limited to 'nscd')
-rw-r--r-- | nscd/Makefile | 45 | ||||
-rw-r--r-- | nscd/aicache.c | 60 | ||||
-rw-r--r-- | nscd/cache.c | 97 | ||||
-rw-r--r-- | nscd/connections.c | 587 | ||||
-rw-r--r-- | nscd/dbg_log.c | 24 | ||||
-rw-r--r-- | nscd/gai.c | 21 | ||||
-rw-r--r-- | nscd/getgrgid_r.c | 22 | ||||
-rw-r--r-- | nscd/getgrnam_r.c | 22 | ||||
-rw-r--r-- | nscd/gethstbyad_r.c | 22 | ||||
-rw-r--r-- | nscd/gethstbynm2_r.c | 22 | ||||
-rw-r--r-- | nscd/getpwnam_r.c | 22 | ||||
-rw-r--r-- | nscd/getpwuid_r.c | 22 | ||||
-rw-r--r-- | nscd/grpcache.c | 80 | ||||
-rw-r--r-- | nscd/hstcache.c | 58 | ||||
-rw-r--r-- | nscd/initgrcache.c | 63 | ||||
-rw-r--r-- | nscd/mem.c | 52 | ||||
-rw-r--r-- | nscd/nscd-client.h | 26 | ||||
-rw-r--r-- | nscd/nscd.c | 102 | ||||
-rw-r--r-- | nscd/nscd.conf | 11 | ||||
-rw-r--r-- | nscd/nscd.h | 34 | ||||
-rw-r--r-- | nscd/nscd.init | 43 | ||||
-rw-r--r-- | nscd/nscd_conf.c | 194 | ||||
-rw-r--r-- | nscd/nscd_getai.c | 83 | ||||
-rw-r--r-- | nscd/nscd_getgr_r.c | 114 | ||||
-rw-r--r-- | nscd/nscd_gethst_r.c | 159 | ||||
-rw-r--r-- | nscd/nscd_getpw_r.c | 74 | ||||
-rw-r--r-- | nscd/nscd_helper.c | 253 | ||||
-rw-r--r-- | nscd/nscd_initgroups.c | 77 | ||||
-rw-r--r-- | nscd/nscd_nischeck.c | 96 | ||||
-rw-r--r-- | nscd/nscd_setup_thread.c | 26 | ||||
-rw-r--r-- | nscd/nscd_stat.c | 26 | ||||
-rw-r--r-- | nscd/pwdcache.c | 77 | ||||
-rw-r--r-- | nscd/selinux.c | 154 | ||||
-rw-r--r-- | nscd/selinux.h | 12 |
34 files changed, 907 insertions, 1873 deletions
diff --git a/nscd/Makefile b/nscd/Makefile index 9c98018217..70a35198c2 100644 --- a/nscd/Makefile +++ b/nscd/Makefile @@ -1,5 +1,4 @@ -# Copyright (C) 1998,2000,2002,2003,2004,2005,2006 -# Free Software Foundation, Inc. +# Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -37,12 +36,13 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ ifeq ($(have-thread-library),yes) +others := nscd_nischeck ifneq (yesyes,$(have-fpie)$(build-shared)) others += nscd endif -install-sbin := nscd +install-sbin := nscd nscd_nischeck -extra-objs := $(nscd-modules:=.o) +extra-objs := $(nscd-modules:=.o) nscd_nischeck.o endif @@ -51,32 +51,15 @@ otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \ $(resolvobjdir)/libresolv.a endif -all-nscd-modules := $(nscd-modules) selinux ifeq (yes,$(have-selinux)) -ifeq (yes,$(have-libaudit)) -libaudit = -laudit -ifeq (yes,$(have-libcap)) -libcap = -lcap -endif -endif - nscd-modules += selinux -selinux-LIBS := -lselinux $(libaudit) $(libcap) - -# The configure.in check for libselinux and its headers did not use -# $SYSINCLUDES. The directory specified by --with-headers usually -# contains only the basic kernel interface headers, not something like -# libselinux. So the simplest thing is to presume that the standard -# system headers will be ok for this file. -$(objpfx)nscd_stat.o: sysincludes = # nothing -$(objpfx)selinux.o: sysincludes = # nothing +selinux-LIBS := -lselinux endif -LDLIBS-nscd = $(selinux-LIBS) - distribute := nscd.h nscd-client.h dbg_log.h \ - $(addsuffix .c, $(filter-out xmalloc,$(all-nscd-modules))) \ - nscd.conf nscd.init nscd_proto.h nscd-types.h + $(addsuffix .c, $(filter-out xmalloc, $(nscd-modules))) \ + nscd_nischeck.c nscd.conf nscd.init nscd_proto.h \ + nscd-types.h include ../Rules @@ -86,13 +69,10 @@ CFLAGS-nscd_gethst_r.c = -fexceptions CFLAGS-nscd_getai.c = -fexceptions CFLAGS-nscd_initgroups.c = -fexceptions -nscd-cflags = -DIS_IN_nscd=1 -D_FORTIFY_SOURCE=2 +nscd-cflags = -DIS_IN_nscd=1 ifeq (yesyes,$(have-fpie)$(build-shared)) nscd-cflags += -fpie endif -ifeq (yes,$(have-ssp)) -nscd-cflags += -fstack-protector -endif CFLAGS-nscd.c += $(nscd-cflags) CFLAGS-connections.c += $(nscd-cflags) @@ -124,13 +104,13 @@ relro-LDFLAGS += -Wl,-z,now endif $(objpfx)nscd: $(addprefix $(objpfx),$(nscd-modules:=.o)) - $(LINK.o) -pie -Wl,-O1 $(nscd-cflags) \ + $(LINK.o) -pie -Wl,-O1 \ $(sysdep-LDFLAGS) $(config-LDFLAGS) $(relro-LDFLAGS) \ $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ $(LDFLAGS) $(LDFLAGS-$(@F)) \ -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ - -o $@ $^ $(LDLIBS-nscd) $(common-objpfx)libc_nonshared.a + -o $@ $^ $(selinux-LIBS) $(common-objpfx)libc_nonshared.a endif # This makes sure -DNOT_IN_libc is passed for all these modules. @@ -139,11 +119,14 @@ lib := nonlib include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left)) $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o) +$(objpfx)nscd_nischeck: $(objpfx)nscd_nischeck.o ifeq ($(build-shared),yes) $(objpfx)nscd: $(common-objpfx)rt/librt.so $(shared-thread-library) \ $(common-objpfx)nis/libnsl.so +$(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.so else $(objpfx)nscd: $(common-objpfx)rt/librt.a $(static-thread-library) \ $(common-objpfx)nis/libnsl.a +$(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.a endif diff --git a/nscd/aicache.c b/nscd/aicache.c index 4640b4df94..4e0496ff44 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -1,20 +1,22 @@ /* Cache handling for host lookup. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <assert.h> #include <errno.h> @@ -24,12 +26,8 @@ #include <time.h> #include <unistd.h> #include <sys/mman.h> - -#include "dbg_log.h" -#include "nscd.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif +#include <dbg_log.h> +#include <nscd.h> typedef enum nss_status (*nss_gethostbyname3_r) @@ -312,7 +310,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, *family++ = th[j].h_addrtype; } - void *cp = family; + char *cp = family; if (canon != NULL) cp = mempcpy (cp, canon, canonlen); @@ -367,31 +365,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, wait. */ assert (fd != -1); -#ifdef HAVE_SENDFILE - if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); - assert ((char *) &dataset->resp - (char *) db->head - + total - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - ssize_t written; - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); -# ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - writeall (fd, &dataset->resp, total); + TEMP_FAILURE_RETRY (write (fd, &dataset->resp, total)); } goto out; @@ -425,7 +399,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, total = sizeof (notfound); if (fd != -1) - TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); + TEMP_FAILURE_RETRY (write (fd, ¬found, total)); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); /* If we cannot permanently store the result, so be it. */ diff --git a/nscd/cache.c b/nscd/cache.c index be9be2aa4f..efac4b3bcc 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -1,25 +1,26 @@ -/* Copyright (c) 1998, 1999, 2003-2005, 2006 Free Software Foundation, Inc. +/* Copyright (c) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <assert.h> #include <atomic.h> #include <errno.h> #include <error.h> -#include <inttypes.h> #include <limits.h> #include <stdlib.h> #include <string.h> @@ -168,12 +169,6 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, if (nentries > table->head->maxnentries) table->head->maxnentries = nentries; - if (table->persistent) - // XXX async OK? - msync ((void *) table->head, - (char *) &table->head->array[hash] - (char *) table->head - + sizeof (ref_t), MS_ASYNC); - return 0; } @@ -190,42 +185,21 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, free the data structures since some hash table entries share the same data. */ void -prune_cache (struct database_dyn *table, time_t now, int fd) +prune_cache (struct database_dyn *table, time_t now) { size_t cnt = table->head->module; /* If this table is not actually used don't do anything. */ if (cnt == 0) - { - if (fd != -1) - { - /* Reply to the INVALIDATE initiator. */ - int32_t resp = 0; - writeall (fd, &resp, sizeof (resp)); - } - return; - } - - /* This function can be called from the cleanup thread but also in - response to an invalidate command. Make sure only one thread is - running. When not serving INVALIDATE request, no need for the - second to wait around. */ - if (fd == -1) - { - if (pthread_mutex_trylock (&table->prunelock) != 0) - /* The work is already being done. */ - return; - } - else - pthread_mutex_lock (&table->prunelock); + return; /* If we check for the modification of the underlying file we invalidate the entries also in this case. */ if (table->check_file) { - struct stat64 st; + struct stat st; - if (stat64 (table->filename, &st) < 0) + if (stat (table->filename, &st) < 0) { char buf[128]; /* We cannot stat() the file, disable file checking if the @@ -258,10 +232,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd) char *const data = table->data; bool any = false; - if (__builtin_expect (debug_level > 2, 0)) - dbg_log (_("pruning %s cache; time %ld"), - dbnames[table - dbs], (long int) now); - do { ref_t run = table->head->array[--cnt]; @@ -271,25 +241,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd) struct hashentry *runp = (struct hashentry *) (data + run); struct datahead *dh = (struct datahead *) (data + runp->packet); - /* Some debug support. */ - if (__builtin_expect (debug_level > 2, 0)) - { - char buf[INET6_ADDRSTRLEN]; - const char *str; - - if (runp->type == GETHOSTBYADDR || runp->type == GETHOSTBYADDRv6) - { - inet_ntop (runp->type == GETHOSTBYADDR ? AF_INET : AF_INET6, - data + runp->key, buf, sizeof (buf)); - str = buf; - } - else - str = data + runp->key; - - dbg_log (_("considering %s entry \"%s\", timeout %" PRIu64), - serv2str[runp->type], str, dh->timeout); - } - /* Check whether the entry timed out. */ if (dh->timeout < now) { @@ -388,14 +339,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd) } while (cnt > 0); - if (fd != -1) - { - /* Reply to the INVALIDATE initiator that the cache has been - invalidated. */ - int32_t resp = 0; - writeall (fd, &resp, sizeof (resp)); - } - if (first <= last) { struct hashentry *head = NULL; @@ -452,7 +395,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd) /* Make sure the data is saved to disk. */ if (table->persistent) msync (table->head, - data + table->head->first_free - (char *) table->head, + table->data + table->head->first_free - (char *) table->head, MS_ASYNC); /* One extra pass if we do debugging. */ @@ -468,11 +411,11 @@ prune_cache (struct database_dyn *table, time_t now, int fd) if (runp->type == GETHOSTBYADDR || runp->type == GETHOSTBYADDRv6) { inet_ntop (runp->type == GETHOSTBYADDR ? AF_INET : AF_INET6, - data + runp->key, buf, sizeof (buf)); + table->data + runp->key, buf, sizeof (buf)); str = buf; } else - str = data + runp->key; + str = table->data + runp->key; dbg_log ("remove %s entry \"%s\"", serv2str[runp->type], str); @@ -484,6 +427,4 @@ prune_cache (struct database_dyn *table, time_t now, int fd) /* Run garbage collection if any entry has been removed or replaced. */ if (any) gc (table); - - pthread_mutex_unlock (&table->prunelock); } diff --git a/nscd/connections.c b/nscd/connections.c index 8f11421431..f22d72e265 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1,20 +1,22 @@ /* Inner loops of cache daemon. - Copyright (C) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <alloca.h> #include <assert.h> @@ -37,9 +39,6 @@ #include <sys/mman.h> #include <sys/param.h> #include <sys/poll.h> -#ifdef HAVE_SENDFILE -# include <sys/sendfile.h> -#endif #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> @@ -47,9 +46,10 @@ #include "nscd.h" #include "dbg_log.h" #include "selinux.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif + + +/* Number of bytes of data we initially reserve for each hash table bucket. */ +#define DEFAULT_DATASIZE_PER_BUCKET 1024 /* Wrapper functions with error checking for standard functions. */ @@ -68,7 +68,6 @@ static gid_t *server_groups; # define NGROUPS 32 #endif static int server_ngroups; -static volatile int sighup_pending; static pthread_attr_t attr; @@ -101,13 +100,10 @@ struct database_dyn dbs[lastdb] = { [pwddb] = { .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, - .prunelock = PTHREAD_MUTEX_INITIALIZER, .enabled = 0, .check_file = 1, .persistent = 0, - .propagate = 1, .shared = 0, - .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/passwd", .db_filename = _PATH_NSCD_PASSWD_DB, .disabled_iov = &pwd_iov_disabled, @@ -119,13 +115,10 @@ struct database_dyn dbs[lastdb] = }, [grpdb] = { .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, - .prunelock = PTHREAD_MUTEX_INITIALIZER, .enabled = 0, .check_file = 1, .persistent = 0, - .propagate = 1, .shared = 0, - .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/group", .db_filename = _PATH_NSCD_GROUP_DB, .disabled_iov = &grp_iov_disabled, @@ -137,13 +130,10 @@ struct database_dyn dbs[lastdb] = }, [hstdb] = { .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, - .prunelock = PTHREAD_MUTEX_INITIALIZER, .enabled = 0, .check_file = 1, .persistent = 0, - .propagate = 0, /* Not used. */ .shared = 0, - .max_db_size = DEFAULT_MAX_DB_SIZE, .filename = "/etc/hosts", .db_filename = _PATH_NSCD_HOSTS_DB, .disabled_iov = &hst_iov_disabled, @@ -191,252 +181,20 @@ static int sock; unsigned long int client_queued; -ssize_t -writeall (int fd, const void *buf, size_t len) -{ - size_t n = len; - ssize_t ret; - do - { - ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL)); - if (ret <= 0) - break; - buf = (const char *) buf + ret; - n -= ret; - } - while (n > 0); - return ret < 0 ? ret : len - n; -} - - -#ifdef HAVE_SENDFILE -ssize_t -sendfileall (int tofd, int fromfd, off_t off, size_t len) -{ - ssize_t n = len; - ssize_t ret; - - do - { - ret = TEMP_FAILURE_RETRY (sendfile (tofd, fromfd, &off, n)); - if (ret <= 0) - break; - n -= ret; - } - while (n > 0); - return ret < 0 ? ret : len - n; -} -#endif - - -enum usekey - { - use_not = 0, - /* The following three are not really used, they are symbolic constants. */ - use_first = 16, - use_begin = 32, - use_end = 64, - - use_he = 1, - use_he_begin = use_he | use_begin, - use_he_end = use_he | use_end, -#if SEPARATE_KEY - use_key = 2, - use_key_begin = use_key | use_begin, - use_key_end = use_key | use_end, - use_key_first = use_key_begin | use_first, -#endif - use_data = 3, - use_data_begin = use_data | use_begin, - use_data_end = use_data | use_end, - use_data_first = use_data_begin | use_first - }; - - -static int -check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap, - enum usekey use, ref_t start, size_t len) -{ - assert (len >= 2); - - if (start > first_free || start + len > first_free - || (start & BLOCK_ALIGN_M1)) - return 0; - - if (usemap[start] == use_not) - { - /* Add the start marker. */ - usemap[start] = use | use_begin; - use &= ~use_first; - - while (--len > 0) - if (usemap[++start] != use_not) - return 0; - else - usemap[start] = use; - - /* Add the end marker. */ - usemap[start] = use | use_end; - } - else if ((usemap[start] & ~use_first) == ((use | use_begin) & ~use_first)) - { - /* Hash entries can't be shared. */ - if (use == use_he) - return 0; - - usemap[start] |= (use & use_first); - use &= ~use_first; - - while (--len > 1) - if (usemap[++start] != use) - return 0; - - if (usemap[++start] != (use | use_end)) - return 0; - } - else - /* Points to a wrong object or somewhere in the middle. */ - return 0; - - return 1; -} - - -/* Verify data in persistent database. */ -static int -verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr) +/* Initialize database information structures. */ +void +nscd_init (void) { - assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb); - - time_t now = time (NULL); - - struct database_pers_head *head = mem; - struct database_pers_head head_copy = *head; - - /* Check that the header that was read matches the head in the database. */ - if (readhead != NULL && memcmp (head, readhead, sizeof (*head)) != 0) - return 0; - - /* First some easy tests: make sure the database header is sane. */ - if (head->version != DB_VERSION - || head->header_size != sizeof (*head) - /* We allow a timestamp to be one hour ahead of the current time. - This should cover daylight saving time changes. */ - || head->timestamp > now + 60 * 60 + 60 - || (head->gc_cycle & 1) - || (size_t) head->module > INT32_MAX / sizeof (ref_t) - || (size_t) head->data_size > INT32_MAX - head->module * sizeof (ref_t) - || head->first_free < 0 - || head->first_free > head->data_size - || (head->first_free & BLOCK_ALIGN_M1) != 0 - || head->maxnentries < 0 - || head->maxnsearched < 0) - return 0; - - uint8_t *usemap = calloc (head->first_free, 1); - if (usemap == NULL) - return 0; - - const char *data = (char *) &head->array[roundup (head->module, - ALIGN / sizeof (ref_t))]; - - nscd_ssize_t he_cnt = 0; - for (nscd_ssize_t cnt = 0; cnt < head->module; ++cnt) - { - ref_t work = head->array[cnt]; - - while (work != ENDREF) - { - if (! check_use (data, head->first_free, usemap, use_he, work, - sizeof (struct hashentry))) - goto fail; - - /* Now we know we can dereference the record. */ - struct hashentry *here = (struct hashentry *) (data + work); - - ++he_cnt; - - /* Make sure the record is for this type of service. */ - if (here->type >= LASTREQ - || serv2db[here->type] != &dbs[dbnr]) - goto fail; - - /* Validate boolean field value. */ - if (here->first != false && here->first != true) - goto fail; - - if (here->len < 0) - goto fail; - - /* Now the data. */ - if (here->packet < 0 - || here->packet > head->first_free - || here->packet + sizeof (struct datahead) > head->first_free) - goto fail; - - struct datahead *dh = (struct datahead *) (data + here->packet); - - if (! check_use (data, head->first_free, usemap, - use_data | (here->first ? use_first : 0), - here->packet, dh->allocsize)) - goto fail; - - if (dh->allocsize < sizeof (struct datahead) - || dh->recsize > dh->allocsize - || (dh->notfound != false && dh->notfound != true) - || (dh->usable != false && dh->usable != true)) - goto fail; - - if (here->key < here->packet + sizeof (struct datahead) - || here->key > here->packet + dh->allocsize - || here->key + here->len > here->packet + dh->allocsize) - { -#if SEPARATE_KEY - /* If keys can appear outside of data, this should be done - instead. But gc doesn't mark the data in that case. */ - if (! check_use (data, head->first_free, usemap, - use_key | (here->first ? use_first : 0), - here->key, here->len)) -#endif - goto fail; - } - - work = here->next; - } - } - - if (he_cnt != head->nentries) - goto fail; + struct sockaddr_un sock_addr; + size_t cnt; - /* See if all data and keys had at least one reference from - he->first == true hashentry. */ - for (ref_t idx = 0; idx < head->first_free; ++idx) + /* Secure mode and unprivileged mode are incompatible */ + if (server_user != NULL && secure_in_use) { -#if SEPARATE_KEY - if (usemap[idx] == use_key_begin) - goto fail; -#endif - if (usemap[idx] == use_data_begin) - goto fail; + dbg_log (_("Cannot run nscd in secure mode as unprivileged user")); + exit (1); } - /* Finally, make sure the database hasn't changed since the first test. */ - if (memcmp (mem, &head_copy, sizeof (*head)) != 0) - goto fail; - - free (usemap); - return 1; - -fail: - free (usemap); - return 0; -} - - -/* Initialize database information structures. */ -void -nscd_init (void) -{ /* Look up unprivileged uid/gid/groups before we start listening on the socket */ if (server_user != NULL) @@ -446,7 +204,7 @@ nscd_init (void) /* No configuration for this value, assume a default. */ nthreads = 2 * lastdb; - for (size_t cnt = 0; cnt < lastdb; ++cnt) + for (cnt = 0; cnt < lastdb; ++cnt) if (dbs[cnt].enabled) { pthread_rwlock_init (&dbs[cnt].lock, NULL); @@ -469,7 +227,7 @@ nscd_init (void) fail_db: dbg_log (_("invalid persistent database file \"%s\": %s"), dbs[cnt].db_filename, strerror (errno)); - unlink (dbs[cnt].db_filename); + dbs[cnt].persistent = 0; } else if (head.module == 0 && head.data_size == 0) { @@ -482,39 +240,22 @@ nscd_init (void) dbg_log (_("invalid persistent database file \"%s\": %s"), dbs[cnt].db_filename, _("header size does not match")); - unlink (dbs[cnt].db_filename); + dbs[cnt].persistent = 0; } else if ((total = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN) + head.data_size)) - > st.st_size - || total < sizeof (head)) + > st.st_size) { dbg_log (_("invalid persistent database file \"%s\": %s"), dbs[cnt].db_filename, _("file size does not match")); - unlink (dbs[cnt].db_filename); + dbs[cnt].persistent = 0; } - /* Note we map with the maximum size allowed for the - database. This is likely much larger than the - actual file size. This is OK on most OSes since - extensions of the underlying file will - automatically translate more pages available for - memory access. */ - else if ((mem = mmap (NULL, dbs[cnt].max_db_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0)) - == MAP_FAILED) + else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0)) == MAP_FAILED) goto fail_db; - else if (!verify_persistent_db (mem, &head, cnt)) - { - munmap (mem, total); - dbg_log (_("invalid persistent database file \"%s\": %s"), - dbs[cnt].db_filename, - _("verification failed")); - unlink (dbs[cnt].db_filename); - } else { /* Success. We have the database. */ @@ -637,23 +378,20 @@ cannot create read-only descriptor for \"%s\"; no mmap"), if (offset % ps != 0) { towrite = MIN (remaining, ps - (offset % ps)); - if (pwrite (fd, tmpbuf, towrite, offset) != towrite) - goto write_fail; + pwrite (fd, tmpbuf, towrite, offset); offset += towrite; remaining -= towrite; } while (remaining > ps) { - if (pwrite (fd, tmpbuf, ps, offset) == -1) - goto write_fail; + pwrite (fd, tmpbuf, ps, offset); offset += ps; remaining -= ps; } - if (remaining > 0 - && pwrite (fd, tmpbuf, remaining, offset) != remaining) - goto write_fail; + if (remaining > 0) + pwrite (fd, tmpbuf, remaining, offset); /* Create the header of the file. */ struct database_pers_head head = @@ -669,13 +407,10 @@ cannot create read-only descriptor for \"%s\"; no mmap"), if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head))) != sizeof (head)) - || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total)) - != 0) - || (mem = mmap (NULL, dbs[cnt].max_db_size, - PROT_READ | PROT_WRITE, + || ftruncate (fd, total) != 0 + || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { - write_fail: unlink (dbs[cnt].db_filename); dbg_log (_("cannot write to database file %s: %s"), dbs[cnt].db_filename, strerror (errno)); @@ -726,7 +461,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"), dbs[cnt].head = xmalloc (sizeof (struct database_pers_head) + (dbs[cnt].suggested_module * sizeof (ref_t))); - memset (dbs[cnt].head, '\0', sizeof (struct database_pers_head)); + memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head)); assert (~ENDREF == 0); memset (dbs[cnt].head->array, '\xff', dbs[cnt].suggested_module * sizeof (ref_t)); @@ -743,9 +478,9 @@ cannot set socket to close on exec: %s; disabling paranoia mode"), if (dbs[cnt].check_file) { /* We need the modification date of the file. */ - struct stat64 st; + struct stat st; - if (stat64 (dbs[cnt].filename, &st) < 0) + if (stat (dbs[cnt].filename, &st) < 0) { /* We cannot stat() the file, disable file checking. */ dbg_log (_("cannot stat() file `%s': %s"), @@ -762,16 +497,15 @@ cannot set socket to close on exec: %s; disabling paranoia mode"), if (sock < 0) { dbg_log (_("cannot open socket: %s"), strerror (errno)); - exit (errno == EACCES ? 4 : 1); + exit (1); } /* Bind a name to the socket. */ - struct sockaddr_un sock_addr; sock_addr.sun_family = AF_UNIX; strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET); if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0) { dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno)); - exit (errno == EACCES ? 4 : 1); + exit (1); } /* We don't want to get stuck on accept. */ @@ -817,10 +551,9 @@ close_sockets (void) static void -invalidate_cache (char *key, int fd) +invalidate_cache (char *key) { dbtype number; - int32_t resp; if (strcmp (key, "passwd") == 0) number = pwddb; @@ -834,19 +567,10 @@ invalidate_cache (char *key, int fd) res_init (); } else - { - resp = EINVAL; - writeall (fd, &resp, sizeof (resp)); - return; - } + return; if (dbs[number].enabled) - prune_cache (&dbs[number], LONG_MAX, fd); - else - { - resp = 0; - writeall (fd, &resp, sizeof (resp)); - } + prune_cache (&dbs[number], LONG_MAX); } @@ -864,14 +588,9 @@ send_ro_fd (struct database_dyn *db, char *key, int fd) iov[0].iov_len = strlen (key) + 1; /* Prepare the control message to transfer the descriptor. */ - union - { - struct cmsghdr hdr; - char bytes[CMSG_SPACE (sizeof (int))]; - } buf; + char buf[CMSG_SPACE (sizeof (int))]; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, - .msg_control = buf.bytes, - .msg_controllen = sizeof (buf) }; + .msg_control = buf, .msg_controllen = sizeof (buf) }; struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); cmsg->cmsg_level = SOL_SOCKET; @@ -884,10 +603,7 @@ send_ro_fd (struct database_dyn *db, char *key, int fd) /* Send the control message. We repeat when we are interrupted but everything else is ignored. */ -#ifndef MSG_NOSIGNAL -# define MSG_NOSIGNAL 0 -#endif - (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL)); + (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0)); if (__builtin_expect (debug_level > 0, 0)) dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key); @@ -944,9 +660,8 @@ cannot handle old request version %d; current version is %d"), if (!db->enabled) { /* No, sent the prepared record. */ - if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base, - db->disabled_iov->iov_len, - MSG_NOSIGNAL)) + if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base, + db->disabled_iov->iov_len)) != (ssize_t) db->disabled_iov->iov_len && __builtin_expect (debug_level, 0) > 0) { @@ -973,34 +688,8 @@ cannot handle old request version %d; current version is %d"), if (cached != NULL) { /* Hurray it's in the cache. */ - ssize_t nwritten; - -#ifdef HAVE_SENDFILE - if (db->mmap_used || !cached->notfound) - { - assert (db->wr_fd != -1); - assert ((char *) cached->data > (char *) db->data); - assert ((char *) cached->data - (char *) db->head - + cached->recsize - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - nwritten = sendfileall (fd, db->wr_fd, - (char *) cached->data - - (char *) db->head, cached->recsize); -# ifndef __ASSUME_SENDFILE - if (nwritten == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - nwritten = writeall (fd, cached->data, cached->recsize); - - if (nwritten != cached->recsize + if (TEMP_FAILURE_RETRY (write (fd, cached->data, cached->recsize)) + != cached->recsize && __builtin_expect (debug_level, 0) > 0) { /* We have problems sending the result. */ @@ -1070,28 +759,29 @@ cannot handle old request version %d; current version is %d"), case GETSTAT: case SHUTDOWN: case INVALIDATE: - { - /* Get the callers credentials. */ + if (! secure_in_use) + { + /* Get the callers credentials. */ #ifdef SO_PEERCRED - struct ucred caller; - socklen_t optlen = sizeof (caller); + struct ucred caller; + socklen_t optlen = sizeof (caller); - if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) - { - char buf[256]; + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) + { + char buf[256]; - dbg_log (_("error getting caller's id: %s"), - strerror_r (errno, buf, sizeof (buf))); - break; - } + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + break; + } - uid = caller.uid; + uid = caller.uid; #else - /* Some systems have no SO_PEERCRED implementation. They don't - care about security so we don't as well. */ - uid = 0; + /* Some systems have no SO_PEERCRED implementation. They don't + care about security so we don't as well. */ + uid = 0; #endif - } + } /* Accept shutdown, getstat and invalidate only from root. For the stat call also allow the user specified in the config file. */ @@ -1103,7 +793,7 @@ cannot handle old request version %d; current version is %d"), else if (uid == 0) { if (req->type == INVALIDATE) - invalidate_cache (key, fd); + invalidate_cache (key); else termination_handler (0); } @@ -1190,7 +880,7 @@ cannot open /proc/self/cmdline: %s; disabling paranoia mode"), /* Second, change back to the old user if we changed it. */ if (server_user != NULL) { - if (setresuid (old_uid, old_uid, old_uid) != 0) + if (setuid (old_uid) != 0) { dbg_log (_("\ cannot change to old UID: %s; disabling paranoia mode"), @@ -1200,7 +890,7 @@ cannot change to old UID: %s; disabling paranoia mode"), return; } - if (setresgid (old_gid, old_gid, old_gid) != 0) + if (setgid (old_gid) != 0) { dbg_log (_("\ cannot change to old GID: %s; disabling paranoia mode"), @@ -1251,9 +941,7 @@ cannot change to old working directory: %s; disabling paranoia mode"), setuid (server_uid); setgid (server_gid); } - if (chdir ("/") != 0) - dbg_log (_("cannot change current working directory to \"/\": %s"), - strerror (errno)); + chdir ("/"); paranoia = 0; } @@ -1330,10 +1018,6 @@ nscd_run (void *p) if (readylist == NULL && to == ETIMEDOUT) { --nready; - - if (sighup_pending) - goto sighup_prune; - pthread_mutex_unlock (&readylist_lock); goto only_prune; } @@ -1343,34 +1027,6 @@ nscd_run (void *p) pthread_cond_wait (&readylist_cond, &readylist_lock); } - if (sighup_pending) - { - --nready; - pthread_cond_signal (&readylist_cond); - sighup_prune: - sighup_pending = 0; - pthread_mutex_unlock (&readylist_lock); - - /* Prune the password database. */ - if (dbs[pwddb].enabled) - prune_cache (&dbs[pwddb], LONG_MAX, -1); - - /* Prune the group database. */ - if (dbs[grpdb].enabled) - prune_cache (&dbs[grpdb], LONG_MAX, -1); - - /* Prune the host database. */ - if (dbs[hstdb].enabled) - prune_cache (&dbs[hstdb], LONG_MAX, -1); - - /* Re-locking. */ - pthread_mutex_lock (&readylist_lock); - - /* One more thread available. */ - ++nready; - continue; - } - struct fdlist *it = readylist->next; if (readylist->next == readylist) /* Just one entry on the list. */ @@ -1417,7 +1073,25 @@ nscd_run (void *p) #ifdef SO_PEERCRED pid_t pid = 0; - if (__builtin_expect (debug_level > 0, 0)) + if (secure_in_use) + { + struct ucred caller; + socklen_t optlen = sizeof (caller); + + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) + { + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + goto close_and_out; + } + + if (req.type < GETPWBYNAME || req.type > LASTDBREQ + || serv2db[req.type]->secure) + uid = caller.uid; + + pid = caller.pid; + } + else if (__builtin_expect (debug_level > 0, 0)) { struct ucred caller; socklen_t optlen = sizeof (caller); @@ -1481,7 +1155,8 @@ handle_request: request received (Version = %d)"), req.version); /* The pthread_cond_timedwait() call timed out. It is time to clean up the cache. */ assert (my_number < lastdb); - prune_cache (&dbs[my_number], time (NULL), -1); + prune_cache (&dbs[my_number], + prune_ts.tv_sec + (prune_ts.tv_nsec >= 500000000)); if (clock_gettime (timeout_clock, &prune_ts) == -1) /* Should never happen. */ @@ -1542,7 +1217,7 @@ fd_ready (int fd) { /* We got another thread. */ ++nthreads; - /* The new thread might need a kick. */ + /* The new thread might new a kick. */ do_signal = true; } @@ -1605,24 +1280,18 @@ main_loop_poll (void) /* We have a new incoming connection. Accept the connection. */ int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL)); - /* Use the descriptor if we have not reached the limit. */ - if (fd >= 0) + /* use the descriptor if we have not reached the limit. */ + if (fd >= 0 && firstfree < nconns) { - if (firstfree < nconns) - { - conns[firstfree].fd = fd; - conns[firstfree].events = POLLRDNORM; - starttime[firstfree] = now; - if (firstfree >= nused) - nused = firstfree + 1; - - do - ++firstfree; - while (firstfree < nused && conns[firstfree].fd != -1); - } - else - /* We cannot use the connection so close it. */ - close (fd); + conns[firstfree].fd = fd; + conns[firstfree].events = POLLRDNORM; + starttime[firstfree] = now; + if (firstfree >= nused) + nused = firstfree + 1; + + do + ++firstfree; + while (firstfree < nused && conns[firstfree].fd != -1); } --n; @@ -1733,9 +1402,10 @@ main_loop_epoll (int efd) else { /* Remove the descriptor from the epoll descriptor. */ - (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, NULL); + struct epoll_event ev = { 0, }; + (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, &ev); - /* Get a worker to handle the request. */ + /* Get a worked to handle the request. */ fd_ready (revs[cnt].data.fd); /* Reset the time. */ @@ -1755,7 +1425,8 @@ main_loop_epoll (int efd) if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart) { /* We are waiting for this one for too long. Close it. */ - (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, NULL); + struct epoll_event ev = {0, }; + (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, &ev); (void) close (cnt); @@ -1908,49 +1579,23 @@ begin_drop_privileges (void) static void finish_drop_privileges (void) { -#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP - /* We need to preserve the capabilities to connect to the audit daemon. */ - cap_t new_caps = preserve_capabilities (); -#endif - if (setgroups (server_ngroups, server_groups) == -1) { dbg_log (_("Failed to run nscd as user '%s'"), server_user); error (EXIT_FAILURE, errno, _("setgroups failed")); } - int res; - if (paranoia) - res = setresgid (server_gid, server_gid, old_gid); - else - res = setgid (server_gid); - if (res == -1) + if (setgid (server_gid) == -1) { dbg_log (_("Failed to run nscd as user '%s'"), server_user); perror ("setgid"); - exit (4); + exit (1); } - if (paranoia) - res = setresuid (server_uid, server_uid, old_uid); - else - res = setuid (server_uid); - if (res == -1) + if (setuid (server_uid) == -1) { dbg_log (_("Failed to run nscd as user '%s'"), server_user); perror ("setuid"); - exit (4); + exit (1); } - -#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP - /* Remove the temporary capabilities. */ - install_real_capabilities (new_caps); -#endif -} - -/* Handle the HUP signal which will force a dump of the cache */ -void -sighup_handler (int signum) -{ - sighup_pending = 1; } diff --git a/nscd/dbg_log.c b/nscd/dbg_log.c index d64afc7e8d..afa06dcbe9 100644 --- a/nscd/dbg_log.c +++ b/nscd/dbg_log.c @@ -1,19 +1,21 @@ -/* Copyright (c) 1998, 2000, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (c) 1998, 2000, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <stdarg.h> #include <stdio.h> @@ -42,7 +44,7 @@ init_logfile (void) { if (logfilename) { - dbgout = fopen64 (logfilename, "a"); + dbgout = fopen (logfilename, "a"); return dbgout == NULL ? 0 : 1; } return 1; diff --git a/nscd/gai.c b/nscd/gai.c index 68719d876a..722c7e415d 100644 --- a/nscd/gai.c +++ b/nscd/gai.c @@ -1,21 +1,3 @@ -/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 2004. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include <alloca.h> /* This file uses the getaddrinfo code but it compiles it without NSCD support. We just need a few symbol renames. */ #define __getservbyname_r getservbyname_r @@ -26,9 +8,6 @@ #define __bind bind #define __sendto sendto #define __strchrnul strchrnul -#define __getline getline -/* nscd uses 1MB or 2MB thread stacks. */ -#define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF) #include <getaddrinfo.c> diff --git a/nscd/getgrgid_r.c b/nscd/getgrgid_r.c index 037509d8aa..d46fb0fcac 100644 --- a/nscd/getgrgid_r.c +++ b/nscd/getgrgid_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <grp.h> diff --git a/nscd/getgrnam_r.c b/nscd/getgrnam_r.c index 8fc74dcbaf..42daa16177 100644 --- a/nscd/getgrnam_r.c +++ b/nscd/getgrnam_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <grp.h> diff --git a/nscd/gethstbyad_r.c b/nscd/gethstbyad_r.c index 4c02492101..47ed3e22e7 100644 --- a/nscd/gethstbyad_r.c +++ b/nscd/gethstbyad_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996,1997,1998,1999,2000,2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <netdb.h> diff --git a/nscd/gethstbynm2_r.c b/nscd/gethstbynm2_r.c index 416b5ceafa..b0cc713a84 100644 --- a/nscd/gethstbynm2_r.c +++ b/nscd/gethstbynm2_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996, 1997, 1998, 2000, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <ctype.h> #include <errno.h> diff --git a/nscd/getpwnam_r.c b/nscd/getpwnam_r.c index c92209a0cf..df73b99e4a 100644 --- a/nscd/getpwnam_r.c +++ b/nscd/getpwnam_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <pwd.h> diff --git a/nscd/getpwuid_r.c b/nscd/getpwuid_r.c index f68951511e..015a521bbe 100644 --- a/nscd/getpwuid_r.c +++ b/nscd/getpwuid_r.c @@ -1,19 +1,21 @@ -/* Copyright (C) 1996, 1997, 1998, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <pwd.h> diff --git a/nscd/grpcache.c b/nscd/grpcache.c index c207492cc0..c565f5a682 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -1,20 +1,22 @@ /* Cache handling for group lookup. - Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <alloca.h> #include <assert.h> @@ -30,14 +32,10 @@ #include <string.h> #include <unistd.h> #include <sys/mman.h> -#include <sys/socket.h> #include <stackinfo.h> #include "nscd.h" #include "dbg_log.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif /* This is the standard reply in case the service is disabled. */ static const gr_response_header disabled = @@ -109,8 +107,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, case. */ total = sizeof (notfound); - written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, - MSG_NOSIGNAL)); + written = TEMP_FAILURE_RETRY (write (fd, ¬found, total)); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); /* If we cannot permanently store the result, so be it. */ @@ -170,7 +167,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, char *gr_name; char *cp; const size_t key_len = strlen (key); - const size_t buf_len = 3 * sizeof (grp->gr_gid) + key_len + 1; + const size_t buf_len = 3 + sizeof (grp->gr_gid) + key_len + 1; char *buf = alloca (buf_len); ssize_t n; size_t cnt; @@ -279,7 +276,6 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, /* Adjust pointers into the memory block. */ gr_name = (char *) newp + (gr_name - (char *) dataset); cp = (char *) newp + (cp - (char *) dataset); - key_copy = (char *) newp + (key_copy - (char *) dataset); dataset = memcpy (newp, dataset, total + n); alloca_used = false; @@ -296,30 +292,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, unnecessarily let the receiver wait. */ assert (fd != -1); -#ifdef HAVE_SENDFILE - if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); - assert ((char *) &dataset->resp - (char *) db->head - + total - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); -# ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - written = writeall (fd, &dataset->resp, total); + written = TEMP_FAILURE_RETRY (write (fd, &dataset->resp, total)); } /* Add the record to the database. But only if it has not been @@ -343,10 +316,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, marked with FIRST first. Otherwise we end up with dangling "pointers" in case a latter hash entry cannot be added. */ - bool first = true; + bool first = req->type == GETGRBYNAME; /* If the request was by GID, add that entry first. */ - if (req->type == GETGRBYGID) + if (req->type != GETGRBYNAME) { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, db, owner) < 0) @@ -356,14 +329,12 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, dataset->head.usable = false; goto out; } - - first = false; } /* If the key is different from the name add a separate entry. */ else if (strcmp (key_copy, gr_name) != 0) { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, first, db, owner) < 0) { /* Could not allocate memory. Make sure the data gets discarded. */ @@ -375,13 +346,11 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, } /* We have to add the value for both, byname and byuid. */ - if ((req->type == GETGRBYNAME || db->propagate) - && __builtin_expect (cache_add (GETGRBYNAME, gr_name, - gr_name_len, - &dataset->head, first, db, owner) - == 0, 1)) + if (__builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len, + &dataset->head, first, db, owner) + == 0, 1)) { - if (req->type == GETGRBYNAME && db->propagate) + if (req->type == GETGRBYNAME) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, req->type != GETGRBYNAME, db, owner); } @@ -460,10 +429,11 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, { char *old_buffer = buffer; errno = 0; +#define INCR 1024 if (__builtin_expect (buflen > 32768, 0)) { - buflen *= 2; + buflen += INCR; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) { @@ -484,7 +454,7 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, else /* Allocate a new buffer on the stack. If possible combine it with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); + buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR); } #if 0 diff --git a/nscd/hstcache.c b/nscd/hstcache.c index e27ece5bc6..99d2998f49 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -1,20 +1,22 @@ /* Cache handling for host lookup. - Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <alloca.h> #include <assert.h> @@ -36,9 +38,6 @@ #include "nscd.h" #include "dbg_log.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif /* This is the standard reply in case the service is disabled. */ @@ -116,8 +115,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, written = total = sizeof (notfound); if (fd != -1) - written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, - MSG_NOSIGNAL)); + written = TEMP_FAILURE_RETRY (write (fd, ¬found, total)); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); /* If we cannot permanently store the result, so be it. */ @@ -329,30 +327,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, unnecessarily keep the receiver waiting. */ assert (fd != -1); -#ifdef HAVE_SENDFILE - if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); - assert ((char *) &dataset->resp - (char *) db->head - + total - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); -# ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - written = writeall (fd, &dataset->resp, total); + written = TEMP_FAILURE_RETRY (write (fd, &dataset->resp, total)); } /* Add the record to the database. But only if it has not been @@ -478,10 +453,11 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, { char *old_buffer = buffer; errno = 0; +#define INCR 1024 if (__builtin_expect (buflen > 32768, 0)) { - buflen *= 2; + buflen += INCR; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) { @@ -502,7 +478,7 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, else /* Allocate a new buffer on the stack. If possible combine it with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); + buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR); } #if 0 diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c index f1f859c552..b46433716b 100644 --- a/nscd/initgrcache.c +++ b/nscd/initgrcache.c @@ -1,20 +1,22 @@ /* Cache handling for host lookup. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <assert.h> #include <errno.h> @@ -24,12 +26,8 @@ #include <time.h> #include <unistd.h> #include <sys/mman.h> - -#include "dbg_log.h" -#include "nscd.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif +#include <dbg_log.h> +#include <nscd.h> #include "../nss/nsswitch.h" @@ -107,7 +105,6 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, long int start = 0; bool all_tryagain = true; - bool any_success = false; /* This is temporary memory, we need not (ad must not) call mempool_alloc. */ @@ -159,8 +156,6 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) __libc_fatal ("illegal status in internal_getgrouplist"); - any_success |= status == NSS_STATUS_SUCCESS; - if (status != NSS_STATUS_SUCCESS && nss_next_action (nip, status) == NSS_ACTION_RETURN) break; @@ -174,7 +169,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, ssize_t total; ssize_t written; out: - if (!any_success) + if (start == 0) { /* Nothing found. Create a negative result record. */ written = total = sizeof (notfound); @@ -193,8 +188,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, /* We have no data. This means we send the standard reply for this case. */ if (fd != -1) - written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, - MSG_NOSIGNAL)); + written = TEMP_FAILURE_RETRY (write (fd, ¬found, total)); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); /* If we cannot permanently store the result, so be it. */ @@ -349,30 +343,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, unnecessarily let the receiver wait. */ assert (fd != -1); -#ifdef HAVE_SENDFILE - if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); - assert ((char *) &dataset->resp - (char *) db->head - + total - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); -# ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - written = writeall (fd, &dataset->resp, total); + written = TEMP_FAILURE_RETRY (write (fd, &dataset->resp, total)); } diff --git a/nscd/mem.c b/nscd/mem.c index 5206c5af38..c3a0f96702 100644 --- a/nscd/mem.c +++ b/nscd/mem.c @@ -1,25 +1,26 @@ /* Cache memory handling. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <assert.h> #include <errno.h> #include <error.h> -#include <fcntl.h> #include <inttypes.h> #include <libintl.h> #include <limits.h> @@ -33,6 +34,12 @@ #include "nscd.h" +/* Maximum alignment requirement we will encounter. */ +#define BLOCK_ALIGN_LOG 3 +#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG) +#define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1) + + static int sort_he (const void *p1, const void *p2) { @@ -187,7 +194,7 @@ gc (struct database_dyn *db) highref -= BLOCK_ALIGN; } - /* Now we can iterate over the MARK array and find bits which are not + /* No we can iterate over the MARK array and find bits which are not set. These represent memory which can be recovered. */ size_t byte = 0; /* Find the first gap. */ @@ -479,26 +486,17 @@ mempool_alloc (struct database_dyn *db, size_t len) if (! tried_resize) { /* Try to resize the database. Grow size of 1/8th. */ + size_t new_data_size = db->head->data_size + db->head->data_size / 8; size_t oldtotal = (sizeof (struct database_pers_head) - + roundup (db->head->module * sizeof (ref_t), ALIGN) + + db->head->module * sizeof (ref_t) + db->head->data_size); - size_t new_data_size = (db->head->data_size - + MAX (2 * len, db->head->data_size / 8)); size_t newtotal = (sizeof (struct database_pers_head) - + roundup (db->head->module * sizeof (ref_t), ALIGN) + + db->head->module * sizeof (ref_t) + new_data_size); - if (newtotal > db->max_db_size) - { - new_data_size -= newtotal - db->max_db_size; - newtotal = db->max_db_size; - } - if (db->mmap_used && newtotal > oldtotal - /* We only have to adjust the file size. The new pages - become magically available. */ - && TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd, oldtotal, - newtotal - - oldtotal)) == 0) + if ((!db->mmap_used || ftruncate (db->wr_fd, newtotal) != 0) + /* Try to resize the mapping. Note: no MREMAP_MAYMOVE. */ + && mremap (db->head, oldtotal, newtotal, 0) == 0) { db->head->data_size = new_data_size; tried_resize = true; diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index 8946b6315b..d49cb8136c 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -1,5 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. +/* Copyright (c) 1998, 1999, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -29,7 +28,6 @@ #include <sys/types.h> #include <atomic.h> #include <nscd-types.h> -#include <sys/uio.h> /* Version number of the daemon interface */ @@ -258,7 +256,6 @@ struct mapped_database const char *data; size_t mapsize; int counter; /* > 0 indicates it is usable. */ - size_t datasize; }; #define NO_MAPPING ((struct mapped_database *) -1l) @@ -278,7 +275,7 @@ extern int __nscd_open_socket (const char *key, size_t keylen, /* Get reference of mapping. */ extern struct mapped_database *__nscd_get_map_ref (request_type type, const char *name, - volatile struct locked_map_ptr *mapptr, + struct locked_map_ptr *mapptr, int *gc_cyclep); /* Unmap database. */ @@ -307,20 +304,9 @@ static inline int __nscd_drop_map_ref (struct mapped_database *map, /* Search the mapped database. */ -extern struct datahead *__nscd_cache_search (request_type type, - const char *key, - size_t keylen, - const struct mapped_database *mapped); - -/* Wrappers around read, readv and write that only read/write less than LEN - bytes on error or EOF. */ -extern ssize_t __readall (int fd, void *buf, size_t len) - attribute_hidden; -extern ssize_t __readvall (int fd, const struct iovec *iov, int iovcnt) - attribute_hidden; -extern ssize_t writeall (int fd, const void *buf, size_t len) - attribute_hidden; -extern ssize_t sendfileall (int tofd, int fromfd, off_t off, size_t len) - attribute_hidden; +extern const struct datahead *__nscd_cache_search (request_type type, + const char *key, + size_t keylen, + const struct mapped_database *mapped); #endif /* nscd.h */ diff --git a/nscd/nscd.c b/nscd/nscd.c index 588b09d4fb..0cc1818d9d 100644 --- a/nscd/nscd.c +++ b/nscd/nscd.c @@ -1,19 +1,21 @@ -/* Copyright (c) 1998-2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (c) 1998-2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ /* nscd - Name Service Cache Daemon. Caches passwd, group, and hosts. */ @@ -70,6 +72,7 @@ int disabled_passwd; int disabled_group; int go_background = 1; +int secure_in_use; static const char *conffile = _PATH_NSCDCONF; time_t start_time; @@ -119,9 +122,6 @@ static struct argp argp = options, parse_opt, NULL, doc, }; -/* The SIGHUP handler is extern to this file */ -extern void sighup_handler(int signum); - /* True if only statistics are requested. */ static bool get_stats; @@ -145,15 +145,17 @@ main (int argc, char **argv) { error (0, 0, gettext ("wrong number of arguments")); argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name); - exit (1); + exit (EXIT_FAILURE); } /* Read the configuration file. */ if (nscd_parse_file (conffile, dbs) != 0) - /* We couldn't read the configuration file. We don't start the - server. */ - error (EXIT_FAILURE, 0, - _("failure while reading configuration file; this is fatal")); + { + /* We couldn't read the configuration file. We don't start the + server. */ + dbg_log (_("cannot read configuration file; this is fatal")); + exit (1); + } /* Do we only get statistics? */ if (get_stats) @@ -238,9 +240,7 @@ main (int argc, char **argv) setsid (); - if (chdir ("/") != 0) - error (EXIT_FAILURE, errno, - _("cannot change current working directory to \"/\"")); + chdir ("/"); openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON); @@ -266,7 +266,6 @@ main (int argc, char **argv) signal (SIGINT, termination_handler); signal (SIGQUIT, termination_handler); signal (SIGTERM, termination_handler); - signal (SIGHUP, sighup_handler); signal (SIGPIPE, SIG_IGN); /* Cleanup files created by a previous 'bind'. */ @@ -302,7 +301,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'K': if (getuid () != 0) - error (4, 0, _("Only root is allowed to use this option!")); + error (EXIT_FAILURE, 0, _("Only root is allowed to use this option!")); { int sock = nscd_open_socket (); request_header req; @@ -314,9 +313,8 @@ parse_opt (int key, char *arg, struct argp_state *state) req.version = NSCD_VERSION; req.type = SHUTDOWN; req.key_len = 0; - nbytes = TEMP_FAILURE_RETRY (send (sock, &req, - sizeof (request_header), - MSG_NOSIGNAL)); + nbytes = TEMP_FAILURE_RETRY (write (sock, &req, + sizeof (request_header))); close (sock); exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -327,7 +325,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'i': if (getuid () != 0) - error (4, 0, _("Only root is allowed to use this option!")); + error (EXIT_FAILURE, 0, _("Only root is allowed to use this option!")); else { int sock = nscd_open_socket (); @@ -336,6 +334,9 @@ parse_opt (int key, char *arg, struct argp_state *state) exit (EXIT_FAILURE); request_header req; + ssize_t nbytes; + struct iovec iov[2]; + if (strcmp (arg, "passwd") == 0) req.key_len = sizeof "passwd"; else if (strcmp (arg, "group") == 0) @@ -348,38 +349,17 @@ parse_opt (int key, char *arg, struct argp_state *state) req.version = NSCD_VERSION; req.type = INVALIDATE; - struct iovec iov[2]; iov[0].iov_base = &req; iov[0].iov_len = sizeof (req); iov[1].iov_base = arg; iov[1].iov_len = req.key_len; - ssize_t nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2)); - - if (nbytes != iov[0].iov_len + iov[1].iov_len) - { - int err = errno; - close (sock); - error (EXIT_FAILURE, err, _("write incomplete")); - } - - /* Wait for ack. Older nscd just closed the socket when - prune_cache finished, silently ignore that. */ - int32_t resp = 0; - nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp))); - if (nbytes != 0 && nbytes != sizeof (resp)) - { - int err = errno; - close (sock); - error (EXIT_FAILURE, err, _("cannot read invalidate ACK")); - } + nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2)); close (sock); - if (resp != 0) - error (EXIT_FAILURE, resp, _("invalidation failed")); - - exit (0); + exit (nbytes != iov[0].iov_len + iov[1].iov_len + ? EXIT_FAILURE : EXIT_SUCCESS); } case 't': @@ -387,7 +367,16 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case 'S': +#if 0 + if (strcmp (arg, "passwd,yes") == 0) + secure_in_use = dbs[pwddb].secure = 1; + else if (strcmp (arg, "group,yes") == 0) + secure_in_use = dbs[grpdb].secure = 1; + else if (strcmp (arg, "hosts,yes") == 0) + secure_in_use = dbs[hstdb].secure = 1; +#else error (0, 0, _("secure services not implemented anymore")); +#endif break; default: @@ -406,7 +395,7 @@ print_version (FILE *stream, struct argp_state *state) Copyright (C) %s Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "2006"); +"), "2004"); fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk and Ulrich Drepper"); } @@ -453,9 +442,6 @@ termination_handler (int signum) /* Synchronize memory. */ for (int cnt = 0; cnt < lastdb; ++cnt) { - if (!dbs[cnt].enabled) - continue; - /* Make sure nobody keeps using the database. */ dbs[cnt].head->timestamp = 0; @@ -509,10 +495,10 @@ write_pid (const char *file) return -1; fprintf (fp, "%d\n", getpid ()); - - int result = fflush (fp) || ferror (fp) ? -1 : 0; + if (fflush (fp) || ferror (fp)) + return -1; fclose (fp); - return result; + return 0; } diff --git a/nscd/nscd.conf b/nscd/nscd.conf index 954eafd554..87e7a84487 100644 --- a/nscd/nscd.conf +++ b/nscd/nscd.conf @@ -23,8 +23,6 @@ # check-files <service> <yes|no> # persistent <service> <yes|no> # shared <service> <yes|no> -# max-db-size <service> <number bytes> -# auto-propagate <service> <yes|no> # # Currently supported cache names (services): passwd, group, hosts # @@ -33,8 +31,8 @@ # logfile /var/log/nscd.log # threads 6 # max-threads 128 - server-user nscd -# stat-user nocpulse +# server-user nobody +# stat-user somebody debug-level 0 # reload-count 5 paranoia no @@ -47,8 +45,6 @@ check-files passwd yes persistent passwd yes shared passwd yes - max-db-size passwd 33554432 - auto-propagate passwd yes enable-cache group yes positive-time-to-live group 3600 @@ -57,8 +53,6 @@ check-files group yes persistent group yes shared group yes - max-db-size group 33554432 - auto-propagate group yes enable-cache hosts yes positive-time-to-live hosts 3600 @@ -67,4 +61,3 @@ check-files hosts yes persistent hosts yes shared hosts yes - max-db-size hosts 33554432 diff --git a/nscd/nscd.h b/nscd/nscd.h index 5c2ff3a95b..d5dc613d22 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 +/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -58,18 +58,16 @@ typedef enum struct database_dyn { pthread_rwlock_t lock; - pthread_mutex_t prunelock; int enabled; int check_file; int persistent; int shared; - int propagate; - const char filename[12]; + const char *filename; const char *db_filename; time_t file_mtime; size_t suggested_module; - size_t max_db_size; + int secure; unsigned long int postimeout; /* In seconds. */ unsigned long int negtimeout; /* In seconds. */ @@ -96,17 +94,6 @@ struct database_dyn /* Path used when not using persistent storage. */ #define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX" -/* Maximum alignment requirement we will encounter. */ -#define BLOCK_ALIGN_LOG 3 -#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG) -#define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1) - -/* Default value for the maximum size of the database files. */ -#define DEFAULT_MAX_DB_SIZE (32 * 1024 * 1024) - -/* Number of bytes of data we initially reserve for each hash table bucket. */ -#define DEFAULT_DATASIZE_PER_BUCKET 1024 - /* Global variables. */ extern struct database_dyn dbs[lastdb]; @@ -123,6 +110,9 @@ extern int nthreads; /* Maximum number of threads to use. */ extern int max_nthreads; +/* Tables for which we cache data with uid. */ +extern int secure_in_use; /* Is one of the above 1? */ + /* User name to run server processes as. */ extern const char *server_user; @@ -185,7 +175,7 @@ extern struct datahead *cache_search (request_type, void *key, size_t len, extern int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, struct database_dyn *table, uid_t owner); -extern void prune_cache (struct database_dyn *table, time_t now, int fd); +extern void prune_cache (struct database_dyn *table, time_t now); /* pwdcache.c */ extern void addpwbyname (struct database_dyn *db, int fd, request_header *req, @@ -246,14 +236,4 @@ extern void gc (struct database_dyn *db); /* nscd_setup_thread.c */ extern void setup_thread (struct database_dyn *db); - -/* Special version of TEMP_FAILURE_RETRY for functions returning error - values. */ -#define TEMP_FAILURE_RETRY_VAL(expression) \ - (__extension__ \ - ({ long int __result; \ - do __result = (long int) (expression); \ - while (__result == EINTR); \ - __result; })) - #endif /* nscd.h */ diff --git a/nscd/nscd.init b/nscd/nscd.init index 1fba72f5c3..d5c1cb9ae3 100644 --- a/nscd/nscd.init +++ b/nscd/nscd.init @@ -9,18 +9,7 @@ # slow naming services like NIS, NIS+, LDAP, or hesiod. # processname: /usr/sbin/nscd # config: /etc/nscd.conf -# config: /etc/sysconfig/nscd # -### BEGIN INIT INFO -# Provides: nscd -# Required-Start: $syslog -# Default-Stop: 0 1 6 -# Short-Description: Starts the Name Switch Cache Daemon -# Description: This is a daemon which handles passwd and group lookups \ -# for running programs and cache the results for the next \ -# query. You should start this daemon if you use \ -# slow naming services like NIS, NIS+, LDAP, or hesiod. -### END INIT INFO # Sanity checks. [ -f /etc/nscd.conf ] || exit 0 @@ -29,8 +18,20 @@ # Source function library. . /etc/init.d/functions -# Source an auxiliary options file if we have one, and pick up NSCD_OPTIONS. -[ -r /etc/sysconfig/nscd ] && . /etc/sysconfig/nscd +# nscd does not run on any kernel lower than 2.2.0 because of threading +# problems, so we require that in first place. +case $(uname -r) in + 2.[2-9].*) + # this is okay + ;; + [3-9]*) + # these are of course also okay + ;; + *) + #this is not + exit 0 + ;; +esac RETVAL=0 prog=nscd @@ -46,7 +47,7 @@ start () { # fi # done echo -n $"Starting $prog: " - daemon /usr/sbin/nscd $secure $NSCD_OPTIONS + daemon /usr/sbin/nscd $secure RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/nscd @@ -87,23 +88,21 @@ case "$1" in RETVAL=$? ;; status) - status nscd + status nscd RETVAL=$? - ;; + ;; restart) restart RETVAL=$? ;; - try-restart | condrestart) + condrestart) [ -e /var/lock/subsys/nscd ] && restart RETVAL=$? ;; - force-reload | reload) - echo -n $"Reloading $prog: " - killproc /usr/sbin/nscd -HUP + reload) + killproc /usr/sbin/nscd -HUP RETVAL=$? - echo - ;; + ;; *) echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}" RETVAL=1 diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 2048eca886..d21f2fc501 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -1,23 +1,24 @@ -/* Copyright (c) 1998,2000,2003,2004,2005,2006 Free Software Foundation, Inc. +/* Copyright (c) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <ctype.h> #include <errno.h> -#include <error.h> #include <libintl.h> #include <malloc.h> #include <pwd.h> @@ -44,18 +45,6 @@ const char *dbnames[lastdb] = [hstdb] = "hosts" }; - -static int -find_db (const char *name) -{ - for (int cnt = 0; cnt < lastdb; ++cnt) - if (strcmp (name, dbnames[cnt]) == 0) - return cnt; - - error (0, 0, _("database %s is not supported\n"), name); - return -1; -} - int nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) { @@ -63,7 +52,6 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) char *line, *cp, *entry, *arg1, *arg2; size_t len; int cnt; - const unsigned int initial_error_message_count = error_message_count; /* Open the configuration file. */ fp = fopen (fname, "r"); @@ -103,7 +91,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) ++arg1; *cp = '\0'; if (strlen (entry) == 0) - error (0, 0, _("Parse error: %s"), line); + dbg_log (_("Parse error: %s"), line); while (isspace (*arg1) && *arg1 != '\0') ++arg1; cp = arg1; @@ -124,49 +112,64 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) if (strcmp (entry, "positive-time-to-live") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - dbs[idx].postimeout = atol (arg2); + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + dbs[cnt].postimeout = atol (arg2); + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "negative-time-to-live") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - dbs[idx].negtimeout = atol (arg2); + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + dbs[cnt].negtimeout = atol (arg2); + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "suggested-size") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - dbs[idx].suggested_module = atol (arg2); + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + dbs[cnt].suggested_module = atol (arg2); + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "enable-cache") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - { - if (strcmp (arg2, "no") == 0) - dbs[idx].enabled = 0; - else if (strcmp (arg2, "yes") == 0) - dbs[idx].enabled = 1; - } + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + if (strcmp (arg2, "no") == 0) + dbs[cnt].enabled = 0; + else if (strcmp (arg2, "yes") == 0) + dbs[cnt].enabled = 1; + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "check-files") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - { - if (strcmp (arg2, "no") == 0) - dbs[idx].check_file = 0; - else if (strcmp (arg2, "yes") == 0) - dbs[idx].check_file = 1; - } - } - else if (strcmp (entry, "max-db-size") == 0) - { - int idx = find_db (arg1); - if (idx >= 0) - dbs[idx].max_db_size = atol (arg2); + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + if (strcmp (arg2, "no") == 0) + dbs[cnt].check_file = 0; + else if (strcmp (arg2, "yes") == 0) + dbs[cnt].check_file = 1; + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "logfile") == 0) set_logfile (arg1); @@ -188,14 +191,14 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) else if (strcmp (entry, "server-user") == 0) { if (!arg1) - error (0, 0, _("Must specify user name for server-user option")); + dbg_log (_("Must specify user name for server-user option")); else server_user = xstrdup (arg1); } else if (strcmp (entry, "stat-user") == 0) { if (arg1 == NULL) - error (0, 0, _("Must specify user name for stat-user option")); + dbg_log (_("Must specify user name for stat-user option")); else { stat_user = xstrdup (arg1); @@ -207,25 +210,31 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) } else if (strcmp (entry, "persistent") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - { - if (strcmp (arg2, "no") == 0) - dbs[idx].persistent = 0; - else if (strcmp (arg2, "yes") == 0) - dbs[idx].persistent = 1; - } + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + if (strcmp (arg2, "no") == 0) + dbs[cnt].persistent = 0; + else if (strcmp (arg2, "yes") == 0) + dbs[cnt].persistent = 1; + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "shared") == 0) { - int idx = find_db (arg1); - if (idx >= 0) - { - if (strcmp (arg2, "no") == 0) - dbs[idx].shared = 0; - else if (strcmp (arg2, "yes") == 0) - dbs[idx].shared = 1; - } + for (cnt = 0; cnt < lastdb; ++cnt) + if (strcmp (arg1, dbnames[cnt]) == 0) + { + if (strcmp (arg2, "no") == 0) + dbs[cnt].shared = 0; + else if (strcmp (arg2, "yes") == 0) + dbs[cnt].shared = 1; + break; + } + if (cnt == lastdb) + dbg_log ("database %s is not supported\n", arg1); } else if (strcmp (entry, "reload-count") == 0) { @@ -239,7 +248,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) else if (count >= 0) reload_count = count; else - error (0, 0, _("invalid value for 'reload-count': %u"), count); + dbg_log (_("invalid value for 'reload-count': %u"), count); } } else if (strcmp (entry, "paranoia") == 0) @@ -254,21 +263,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) if (arg1 != NULL) restart_interval = atol (arg1); else - error (0, 0, _("Must specify value for restart-interval option")); - } - else if (strcmp (entry, "auto-propagate") == 0) - { - int idx = find_db (arg1); - if (idx >= 0) - { - if (strcmp (arg2, "no") == 0) - dbs[idx].propagate = 0; - else if (strcmp (arg2, "yes") == 0) - dbs[idx].propagate = 1; - } + dbg_log (_("Must specify value for restart-interval option")); } else - error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2); + dbg_log (_("Unknown option: %s %s %s"), entry, arg1, arg2); } while (!feof_unlocked (fp)); @@ -281,7 +279,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) oldcwd = get_current_dir_name (); if (oldcwd == NULL) { - error (0, 0, _("\ + dbg_log (_("\ cannot get current working directory: %s; disabling paranoia mode"), strerror (errno)); paranoia = 0; @@ -292,26 +290,10 @@ cannot get current working directory: %s; disabling paranoia mode"), if (max_nthreads < nthreads) max_nthreads = nthreads; - for (cnt = 0; cnt < lastdb; ++cnt) - { - size_t datasize = (sizeof (struct database_pers_head) - + roundup (dbs[cnt].suggested_module - * sizeof (ref_t), ALIGN) - + (dbs[cnt].suggested_module - * DEFAULT_DATASIZE_PER_BUCKET)); - if (datasize > dbs[cnt].max_db_size) - { - error (0, 0, _("maximum file size for %s database too small"), - dbnames[cnt]); - dbs[cnt].max_db_size = datasize; - } - - } - /* Free the buffer. */ free (line); /* Close configuration file. */ fclose (fp); - return error_message_count != initial_error_message_count; + return 0; } diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c index 5df32dc6dc..24b374b0dc 100644 --- a/nscd/nscd_getai.c +++ b/nscd/nscd_getai.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -34,7 +34,7 @@ extern int __nss_not_use_nscd_hosts; /* We use the mapping from nscd_gethst. */ -libc_locked_map_ptr (extern, __hst_map_handle) attribute_hidden; +libc_locked_map_ptr (extern, __hst_map_handle); int @@ -42,7 +42,6 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) { size_t keylen = strlen (key) + 1; int gc_cycle; - int nretries = 0; /* If the mapping is available, try to search there instead of communicating with the nscd. */ @@ -51,53 +50,49 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) &gc_cycle); retry:; + const ai_response_header *ai_resp = NULL; struct nscd_ai_result *resultbuf = NULL; const char *recend = (const char *) ~UINTMAX_C (0); char *respdata = NULL; int retval = -1; int sock = -1; - ai_response_header ai_resp; if (mapped != NO_MAPPING) { - struct datahead *found = __nscd_cache_search (GETAI, key, keylen, - mapped); + const struct datahead *found = __nscd_cache_search (GETAI, key, keylen, + mapped); if (found != NULL) { - respdata = (char *) (&found->data[0].aidata + 1); - ai_resp = found->data[0].aidata; + ai_resp = &found->data[0].aidata; + respdata = (char *) (ai_resp + 1); recend = (const char *) found->data + found->recsize; - /* Now check if we can trust ai_resp fields. If GC is - in progress, it can contain anything. */ - if (mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out; - } } } /* If we do not have the cache mapped, try to get the data over the socket. */ - if (respdata == NULL) + ai_response_header ai_resp_mem; + if (ai_resp == NULL) { - sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp, - sizeof (ai_resp)); + sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp_mem, + sizeof (ai_resp_mem)); if (sock == -1) { - /* nscd not running or wrong version. */ + /* nscd not running or wrong version or hosts caching disabled. */ __nss_not_use_nscd_hosts = 1; goto out; } + + ai_resp = &ai_resp_mem; } - if (ai_resp.found == 1) + if (ai_resp->found == 1) { - size_t datalen = ai_resp.naddrs + ai_resp.addrslen + ai_resp.canonlen; + size_t datalen = ai_resp->naddrs + ai_resp->addrslen + ai_resp->canonlen; - /* This check really only affects the case where the data + /* This check is really only affects the case where the data comes from the mapped cache. */ - if (respdata + datalen > recend) + if ((char *) (ai_resp + 1) + datalen > recend) { assert (sock == -1); goto out; @@ -113,10 +108,10 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) } /* Set up the data structure, including pointers. */ - resultbuf->naddrs = ai_resp.naddrs; + resultbuf->naddrs = ai_resp->naddrs; resultbuf->addrs = (char *) (resultbuf + 1); - resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp.addrslen); - if (ai_resp.canonlen != 0) + resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp->addrslen); + if (ai_resp->canonlen != 0) resultbuf->canon = (char *) (resultbuf->family + resultbuf->naddrs); else resultbuf->canon = NULL; @@ -124,7 +119,8 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) if (respdata == NULL) { /* Read the data from the socket. */ - if ((size_t) __readall (sock, resultbuf + 1, datalen) == datalen) + if ((size_t) TEMP_FAILURE_RETRY (__read (sock, resultbuf + 1, + datalen)) == datalen) { retval = 0; *result = resultbuf; @@ -142,13 +138,10 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) /* Try to detect corrupt databases. */ if (resultbuf->canon != NULL - && resultbuf->canon[ai_resp.canonlen - 1] != '\0') + && resultbuf->canon[ai_resp->canonlen - 1] != '\0') /* We cannot use the database. */ { - if (mapped->head->gc_cycle != gc_cycle) - retval = -2; - else - free (resultbuf); + free (resultbuf); goto out_close; } @@ -158,15 +151,8 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) } else { - if (__builtin_expect (ai_resp.found == -1, 0)) - { - /* The daemon does not cache this database. */ - __nss_not_use_nscd_hosts = 1; - goto out_close; - } - /* Store the error number. */ - *h_errnop = ai_resp.error; + *h_errnop = ai_resp->error; /* The `errno' to some value != ERANGE. */ __set_errno (ENOENT); @@ -178,25 +164,22 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) if (sock != -1) close_not_cancel_no_status (sock); out: - if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) { /* When we come here this means there has been a GC cycle while we were looking for the data. This means the data might have been inconsistent. Retry if possible. */ - if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) + if ((gc_cycle & 1) != 0) { /* nscd is just running gc now. Disable using the mapping. */ - if (atomic_decrement_val (&mapped->counter) == 0) - __nscd_unmap (mapped); + __nscd_unmap (mapped); mapped = NO_MAPPING; } - if (retval != -1) - { - *result = NULL; - free (resultbuf); - goto retry; - } + *result = NULL; + free (resultbuf); + + goto retry; } return retval; diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index fc036f2888..282912db3e 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, 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998. @@ -67,7 +67,7 @@ __nscd_getgrgid_r (gid_t gid, struct group *resultbuf, char *buffer, } -libc_locked_map_ptr (,__gr_map_handle) attribute_hidden; +libc_locked_map_ptr (,__gr_map_handle); /* Note that we only free the structure if necessary. The memory mapping is not removed since it is not visible to the malloc handling. */ @@ -89,7 +89,6 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, struct group **result) { int gc_cycle; - int nretries = 0; const uint32_t *len = NULL; size_t lensize = 0; @@ -99,59 +98,55 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, &__gr_map_handle, &gc_cycle); retry:; + const gr_response_header *gr_resp = NULL; const char *gr_name = NULL; size_t gr_name_len = 0; int retval = -1; const char *recend = (const char *) ~UINTMAX_C (0); - gr_response_header gr_resp; if (mapped != NO_MAPPING) { - struct datahead *found = __nscd_cache_search (type, key, keylen, mapped); + const struct datahead *found = __nscd_cache_search (type, key, keylen, + mapped); if (found != NULL) { - len = (const uint32_t *) (&found->data[0].grdata + 1); - gr_resp = found->data[0].grdata; + gr_resp = &found->data[0].grdata; + len = (const uint32_t *) (gr_resp + 1); + /* The alignment is always sufficient. */ + assert (((uintptr_t) len & (__alignof__ (*len) - 1)) == 0); gr_name = ((const char *) len - + gr_resp.gr_mem_cnt * sizeof (uint32_t)); - gr_name_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len; + + gr_resp->gr_mem_cnt * sizeof (uint32_t)); + gr_name_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len; recend = (const char *) found->data + found->recsize; - /* Now check if we can trust gr_resp fields. If GC is - in progress, it can contain anything. */ - if (mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out; - } - - /* The alignment is always sufficient, unless GC is in progress. */ - assert (((uintptr_t) len & (__alignof__ (*len) - 1)) == 0); } } + gr_response_header gr_resp_mem; int sock = -1; - if (gr_name == NULL) + if (gr_resp == NULL) { - sock = __nscd_open_socket (key, keylen, type, &gr_resp, - sizeof (gr_resp)); + sock = __nscd_open_socket (key, keylen, type, &gr_resp_mem, + sizeof (gr_resp_mem)); if (sock == -1) { __nss_not_use_nscd_group = 1; goto out; } + + gr_resp = &gr_resp_mem; } /* No value found so far. */ *result = NULL; - if (__builtin_expect (gr_resp.found == -1, 0)) + if (__builtin_expect (gr_resp->found == -1, 0)) { /* The daemon does not cache this database. */ __nss_not_use_nscd_group = 1; goto out_close; } - if (gr_resp.found == 1) + if (gr_resp->found == 1) { struct iovec vec[2]; char *p = buffer; @@ -163,8 +158,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, align the pointer. */ align = ((__alignof__ (char *) - (p - ((char *) 0))) & (__alignof__ (char *) - 1)); - total_len = (align + (1 + gr_resp.gr_mem_cnt) * sizeof (char *) - + gr_resp.gr_name_len + gr_resp.gr_passwd_len); + total_len = (align + (1 + gr_resp->gr_mem_cnt) * sizeof (char *) + + gr_resp->gr_name_len + gr_resp->gr_passwd_len); if (__builtin_expect (buflen < total_len, 0)) { no_room: @@ -176,16 +171,16 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, p += align; resultbuf->gr_mem = (char **) p; - p += (1 + gr_resp.gr_mem_cnt) * sizeof (char *); + p += (1 + gr_resp->gr_mem_cnt) * sizeof (char *); /* Set pointers for strings. */ resultbuf->gr_name = p; - p += gr_resp.gr_name_len; + p += gr_resp->gr_name_len; resultbuf->gr_passwd = p; - p += gr_resp.gr_passwd_len; + p += gr_resp->gr_passwd_len; /* Fill in what we know now. */ - resultbuf->gr_gid = gr_resp.gr_gid; + resultbuf->gr_gid = gr_resp->gr_gid; /* Read the length information, group name, and password. */ if (gr_name == NULL) @@ -193,21 +188,21 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* Allocate array to store lengths. */ if (lensize == 0) { - lensize = gr_resp.gr_mem_cnt * sizeof (uint32_t); + lensize = gr_resp->gr_mem_cnt * sizeof (uint32_t); len = (uint32_t *) alloca (lensize); } - else if (gr_resp.gr_mem_cnt * sizeof (uint32_t) > lensize) + else if (gr_resp->gr_mem_cnt * sizeof (uint32_t) > lensize) len = extend_alloca (len, lensize, - gr_resp.gr_mem_cnt * sizeof (uint32_t)); + gr_resp->gr_mem_cnt * sizeof (uint32_t)); vec[0].iov_base = (void *) len; - vec[0].iov_len = gr_resp.gr_mem_cnt * sizeof (uint32_t); + vec[0].iov_len = gr_resp->gr_mem_cnt * sizeof (uint32_t); vec[1].iov_base = resultbuf->gr_name; - vec[1].iov_len = gr_resp.gr_name_len + gr_resp.gr_passwd_len; + vec[1].iov_len = gr_resp->gr_name_len + gr_resp->gr_passwd_len; total_len = vec[0].iov_len + vec[1].iov_len; /* Get this data. */ - size_t n = __readvall (sock, vec, 2); + size_t n = TEMP_FAILURE_RETRY (__readv (sock, vec, 2)); if (__builtin_expect (n != total_len, 0)) goto out_close; } @@ -215,14 +210,14 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* We already have the data. Just copy the group name and password. */ memcpy (resultbuf->gr_name, gr_name, - gr_resp.gr_name_len + gr_resp.gr_passwd_len); + gr_resp->gr_name_len + gr_resp->gr_passwd_len); /* Clear the terminating entry. */ - resultbuf->gr_mem[gr_resp.gr_mem_cnt] = NULL; + resultbuf->gr_mem[gr_resp->gr_mem_cnt] = NULL; /* Prepare reading the group members. */ total_len = 0; - for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt) + for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt) { resultbuf->gr_mem[cnt] = p; total_len += len[cnt]; @@ -230,30 +225,15 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, } if (__builtin_expect (gr_name + gr_name_len + total_len > recend, 0)) - { - /* len array might contain garbage during nscd GC cycle, - retry rather than fail in that case. */ - if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle) - retval = -2; - goto out_close; - } + goto out_close; if (__builtin_expect (total_len > buflen, 0)) - { - /* len array might contain garbage during nscd GC cycle, - retry rather than fail in that case. */ - if (gr_name != NULL && mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out_close; - } - else - goto no_room; - } + goto no_room; retval = 0; if (gr_name == NULL) { - size_t n = __readall (sock, resultbuf->gr_mem[0], total_len); + size_t n = TEMP_FAILURE_RETRY (__read (sock, resultbuf->gr_mem[0], + total_len)); if (__builtin_expect (n != total_len, 0)) { /* The `errno' to some value != ERANGE. */ @@ -270,14 +250,14 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* Try to detect corrupt databases. */ if (resultbuf->gr_name[gr_name_len - 1] != '\0' - || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0' - || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt) + || resultbuf->gr_passwd[gr_resp->gr_passwd_len - 1] != '\0' + || ({for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt) if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0') break; - cnt < gr_resp.gr_mem_cnt; })) + cnt < gr_resp->gr_mem_cnt; })) { /* We cannot use the database. */ - retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1; + retval = -1; goto out_close; } @@ -296,21 +276,19 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, if (sock != -1) close_not_cancel_no_status (sock); out: - if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) { /* When we come here this means there has been a GC cycle while we were looking for the data. This means the data might have been inconsistent. Retry if possible. */ - if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) + if ((gc_cycle & 1) != 0) { /* nscd is just running gc now. Disable using the mapping. */ - if (atomic_decrement_val (&mapped->counter) == 0) - __nscd_unmap (mapped); + __nscd_unmap (mapped); mapped = NO_MAPPING; } - if (retval != -1) - goto retry; + goto retry; } return retval; diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index 90e1815bdd..5d9d569107 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -87,7 +87,7 @@ __nscd_gethostbyaddr_r (const void *addr, socklen_t len, int type, } -libc_locked_map_ptr (, __hst_map_handle) attribute_hidden; +libc_locked_map_ptr (, __hst_map_handle); /* Note that we only free the structure if necessary. The memory mapping is not removed since it is not visible to the malloc handling. */ @@ -118,6 +118,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, &gc_cycle); retry:; + const hst_response_header *hst_resp = NULL; const char *h_name = NULL; const uint32_t *aliases_len = NULL; const char *addr_list = NULL; @@ -125,27 +126,18 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, int retval = -1; const char *recend = (const char *) ~UINTMAX_C (0); int sock = -1; - hst_response_header hst_resp; if (mapped != NO_MAPPING) { - /* No const qualifier, as it can change during garbage collection. */ - struct datahead *found = __nscd_cache_search (type, key, keylen, mapped); + const struct datahead *found = __nscd_cache_search (type, key, keylen, + mapped); if (found != NULL) { - h_name = (char *) (&found->data[0].hstdata + 1); - hst_resp = found->data[0].hstdata; - aliases_len = (uint32_t *) (h_name + hst_resp.h_name_len); + hst_resp = &found->data[0].hstdata; + h_name = (char *) (hst_resp + 1); + aliases_len = (uint32_t *) (h_name + hst_resp->h_name_len); addr_list = ((char *) aliases_len - + hst_resp.h_aliases_cnt * sizeof (uint32_t)); - addr_list_len = hst_resp.h_addr_list_cnt * INADDRSZ; - recend = (const char *) found->data + found->recsize; - /* Now check if we can trust hst_resp fields. If GC is - in progress, it can contain anything. */ - if (mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out; - } + + hst_resp->h_aliases_cnt * sizeof (uint32_t)); + addr_list_len = hst_resp->h_addr_list_cnt * INADDRSZ; #ifndef _STRING_ARCH_unaligned /* The aliases_len array in the mapped database might very @@ -155,47 +147,51 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1)) != 0) { - uint32_t *tmp = alloca (hst_resp.h_aliases_cnt + uint32_t *tmp = alloca (hst_resp->h_aliases_cnt * sizeof (uint32_t)); aliases_len = memcpy (tmp, aliases_len, - hst_resp.h_aliases_cnt + hst_resp->h_aliases_cnt * sizeof (uint32_t)); } #endif if (type != GETHOSTBYADDR && type != GETHOSTBYNAME) { - if (hst_resp.h_length == INADDRSZ) + if (hst_resp->h_length == INADDRSZ) addr_list += addr_list_len; - addr_list_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ; + addr_list_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ; } + recend = (const char *) found->data + found->recsize; if (__builtin_expect ((const char *) addr_list + addr_list_len > recend, 0)) - goto out; + goto out_close; } } - if (h_name == NULL) + hst_response_header hst_resp_mem; + if (hst_resp == NULL) { - sock = __nscd_open_socket (key, keylen, type, &hst_resp, - sizeof (hst_resp)); + sock = __nscd_open_socket (key, keylen, type, &hst_resp_mem, + sizeof (hst_resp_mem)); if (sock == -1) { __nss_not_use_nscd_hosts = 1; - goto out; + goto out;; } + + hst_resp = &hst_resp_mem; } /* No value found so far. */ *result = NULL; - if (__builtin_expect (hst_resp.found == -1, 0)) + if (__builtin_expect (hst_resp->found == -1, 0)) { /* The daemon does not cache this database. */ __nss_not_use_nscd_hosts = 1; goto out_close; } - if (hst_resp.found == 1) + if (hst_resp->found == 1) { struct iovec vec[4]; char *cp = buffer; @@ -211,18 +207,17 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, align the pointer and the base of the h_addr_list pointers. */ align1 = ((__alignof__ (char *) - (cp - ((char *) 0))) & (__alignof__ (char *) - 1)); - align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp.h_name_len) + align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp->h_name_len) - ((char *) 0))) & (__alignof__ (char *) - 1)); - if (buflen < (align1 + hst_resp.h_name_len + align2 - + ((hst_resp.h_aliases_cnt + hst_resp.h_addr_list_cnt + if (buflen < (align1 + hst_resp->h_name_len + align2 + + ((hst_resp->h_aliases_cnt + hst_resp->h_addr_list_cnt + 2) * sizeof (char *)) - + hst_resp.h_addr_list_cnt * (type == AF_INET - ? INADDRSZ : IN6ADDRSZ))) + + hst_resp->h_addr_list_cnt * (type == AF_INET + ? INADDRSZ : IN6ADDRSZ))) { no_room: - *h_errnop = NETDB_INTERNAL; __set_errno (ERANGE); retval = ERANGE; goto out_close; @@ -231,12 +226,12 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, /* Prepare the result as far as we can. */ resultbuf->h_aliases = (char **) cp; - cp += (hst_resp.h_aliases_cnt + 1) * sizeof (char *); + cp += (hst_resp->h_aliases_cnt + 1) * sizeof (char *); resultbuf->h_addr_list = (char **) cp; - cp += (hst_resp.h_addr_list_cnt + 1) * sizeof (char *); + cp += (hst_resp->h_addr_list_cnt + 1) * sizeof (char *); resultbuf->h_name = cp; - cp += hst_resp.h_name_len + align2; + cp += hst_resp->h_name_len + align2; if (type == GETHOSTBYADDR || type == GETHOSTBYNAME) { @@ -248,7 +243,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, resultbuf->h_addrtype = AF_INET6; resultbuf->h_length = IN6ADDRSZ; } - for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt) + for (cnt = 0; cnt < hst_resp->h_addr_list_cnt; ++cnt) { resultbuf->h_addr_list[cnt] = cp; cp += resultbuf->h_length; @@ -258,63 +253,64 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (h_name == NULL) { vec[0].iov_base = resultbuf->h_name; - vec[0].iov_len = hst_resp.h_name_len; - total_len = hst_resp.h_name_len; + vec[0].iov_len = hst_resp->h_name_len; + total_len = hst_resp->h_name_len; n = 1; - if (hst_resp.h_aliases_cnt > 0) + if (hst_resp->h_aliases_cnt > 0) { - aliases_len = alloca (hst_resp.h_aliases_cnt + aliases_len = alloca (hst_resp->h_aliases_cnt * sizeof (uint32_t)); vec[n].iov_base = (void *) aliases_len; - vec[n].iov_len = hst_resp.h_aliases_cnt * sizeof (uint32_t); + vec[n].iov_len = hst_resp->h_aliases_cnt * sizeof (uint32_t); - total_len += hst_resp.h_aliases_cnt * sizeof (uint32_t); + total_len += hst_resp->h_aliases_cnt * sizeof (uint32_t); ++n; } if (type == GETHOSTBYADDR || type == GETHOSTBYNAME) { vec[n].iov_base = resultbuf->h_addr_list[0]; - vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ; + vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ; - total_len += hst_resp.h_addr_list_cnt * INADDRSZ; + total_len += hst_resp->h_addr_list_cnt * INADDRSZ; ++n; } else { - if (hst_resp.h_length == INADDRSZ) + if (hst_resp->h_length == INADDRSZ) { - ignore = alloca (hst_resp.h_addr_list_cnt * INADDRSZ); + ignore = alloca (hst_resp->h_addr_list_cnt * INADDRSZ); vec[n].iov_base = ignore; - vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ; + vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ; - total_len += hst_resp.h_addr_list_cnt * INADDRSZ; + total_len += hst_resp->h_addr_list_cnt * INADDRSZ; ++n; } vec[n].iov_base = resultbuf->h_addr_list[0]; - vec[n].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ; + vec[n].iov_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ; - total_len += hst_resp.h_addr_list_cnt * IN6ADDRSZ; + total_len += hst_resp->h_addr_list_cnt * IN6ADDRSZ; ++n; } - if ((size_t) __readvall (sock, vec, n) != total_len) + if ((size_t) TEMP_FAILURE_RETRY (__readv (sock, vec, n)) + != total_len) goto out_close; } else { - memcpy (resultbuf->h_name, h_name, hst_resp.h_name_len); + memcpy (resultbuf->h_name, h_name, hst_resp->h_name_len); memcpy (resultbuf->h_addr_list[0], addr_list, addr_list_len); } /* Now we also can read the aliases. */ total_len = 0; - for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt) + for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt) { resultbuf->h_aliases[cnt] = cp; cp += aliases_len[cnt]; @@ -324,32 +320,17 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (__builtin_expect ((const char *) addr_list + addr_list_len + total_len > recend, 0)) - { - /* aliases_len array might contain garbage during nscd GC cycle, - retry rather than fail in that case. */ - if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle) - retval = -2; - goto out_close; - } + goto out_close; /* See whether this would exceed the buffer capacity. */ if (__builtin_expect (cp > buffer + buflen, 0)) - { - /* aliases_len array might contain garbage during nscd GC cycle, - retry rather than fail in that case. */ - if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out_close; - } - goto no_room; - } + goto no_room; /* And finally read the aliases. */ if (addr_list == NULL) { - if (total_len == 0 - || ((size_t) __readall (sock, resultbuf->h_aliases[0], total_len) - == total_len)) + if ((size_t) TEMP_FAILURE_RETRY (__read (sock, + resultbuf->h_aliases[0], + total_len)) == total_len) { retval = 0; *result = resultbuf; @@ -361,18 +342,14 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, (const char *) addr_list + addr_list_len, total_len); /* Try to detect corrupt databases. */ - if (resultbuf->h_name[hst_resp.h_name_len - 1] != '\0' - || ({for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt) + if (resultbuf->h_name[hst_resp->h_name_len - 1] != '\0' + || ({for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt) if (resultbuf->h_aliases[cnt][aliases_len[cnt] - 1] != '\0') break; - cnt < hst_resp.h_aliases_cnt; })) - { - /* We cannot use the database. */ - if (mapped->head->gc_cycle != gc_cycle) - retval = -2; - goto out_close; - } + cnt < hst_resp->h_aliases_cnt; })) + /* We cannot use the database. */ + goto out_close; retval = 0; *result = resultbuf; @@ -381,7 +358,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, else { /* Store the error number. */ - *h_errnop = hst_resp.error; + *h_errnop = hst_resp->error; /* The `errno' to some value != ERANGE. */ __set_errno (ENOENT); @@ -393,21 +370,19 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, if (sock != -1) close_not_cancel_no_status (sock); out: - if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) { /* When we come here this means there has been a GC cycle while we were looking for the data. This means the data might have been inconsistent. Retry if possible. */ - if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) + if ((gc_cycle & 1) != 0 || ++nretries == 5) { /* nscd is just running gc now. Disable using the mapping. */ - if (atomic_decrement_val (&mapped->counter) == 0) - __nscd_unmap (mapped); + __nscd_unmap (mapped); mapped = NO_MAPPING; } - if (retval != -1) - goto retry; + goto retry; } return retval; diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index b84baa1a66..fe5fb43ca1 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1998, 1999, 2003, 2004, 2005, 2007 - Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1998. @@ -89,81 +88,76 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, struct passwd **result) { int gc_cycle; - int nretries = 0; - /* If the mapping is available, try to search there instead of communicating with the nscd. */ struct mapped_database *mapped; mapped = __nscd_get_map_ref (GETFDPW, "passwd", &map_handle, &gc_cycle); retry:; + const pw_response_header *pw_resp = NULL; const char *pw_name = NULL; int retval = -1; const char *recend = (const char *) ~UINTMAX_C (0); - pw_response_header pw_resp; if (mapped != NO_MAPPING) { - struct datahead *found = __nscd_cache_search (type, key, keylen, mapped); + const struct datahead *found = __nscd_cache_search (type, key, keylen, + mapped); if (found != NULL) { - pw_name = (const char *) (&found->data[0].pwdata + 1); - pw_resp = found->data[0].pwdata; + pw_resp = &found->data[0].pwdata; + pw_name = (const char *) (pw_resp + 1); recend = (const char *) found->data + found->recsize; - /* Now check if we can trust pw_resp fields. If GC is - in progress, it can contain anything. */ - if (mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out; - } } } + pw_response_header pw_resp_mem; int sock = -1; - if (pw_name == NULL) + if (pw_resp == NULL) { - sock = __nscd_open_socket (key, keylen, type, &pw_resp, - sizeof (pw_resp)); + sock = __nscd_open_socket (key, keylen, type, &pw_resp_mem, + sizeof (pw_resp_mem)); if (sock == -1) { __nss_not_use_nscd_passwd = 1; goto out; } + + pw_resp = &pw_resp_mem; } /* No value found so far. */ *result = NULL; - if (__builtin_expect (pw_resp.found == -1, 0)) + if (__builtin_expect (pw_resp->found == -1, 0)) { /* The daemon does not cache this database. */ __nss_not_use_nscd_passwd = 1; goto out_close; } - if (pw_resp.found == 1) + if (pw_resp->found == 1) { /* Set the information we already have. */ - resultbuf->pw_uid = pw_resp.pw_uid; - resultbuf->pw_gid = pw_resp.pw_gid; + resultbuf->pw_uid = pw_resp->pw_uid; + resultbuf->pw_gid = pw_resp->pw_gid; char *p = buffer; /* get pw_name */ resultbuf->pw_name = p; - p += pw_resp.pw_name_len; + p += pw_resp->pw_name_len; /* get pw_passwd */ resultbuf->pw_passwd = p; - p += pw_resp.pw_passwd_len; + p += pw_resp->pw_passwd_len; /* get pw_gecos */ resultbuf->pw_gecos = p; - p += pw_resp.pw_gecos_len; + p += pw_resp->pw_gecos_len; /* get pw_dir */ resultbuf->pw_dir = p; - p += pw_resp.pw_dir_len; + p += pw_resp->pw_dir_len; /* get pw_pshell */ resultbuf->pw_shell = p; - p += pw_resp.pw_shell_len; + p += pw_resp->pw_shell_len; ssize_t total = p - buffer; if (__builtin_expect (pw_name + total > recend, 0)) @@ -178,7 +172,7 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, retval = 0; if (pw_name == NULL) { - ssize_t nbytes = __readall (sock, buffer, total); + ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, buffer, total)); if (__builtin_expect (nbytes != total, 0)) { @@ -195,14 +189,14 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, memcpy (resultbuf->pw_name, pw_name, total); /* Try to detect corrupt databases. */ - if (resultbuf->pw_name[pw_resp.pw_name_len - 1] != '\0' - || resultbuf->pw_passwd[pw_resp.pw_passwd_len - 1] != '\0' - || resultbuf->pw_gecos[pw_resp.pw_gecos_len - 1] != '\0' - || resultbuf->pw_dir[pw_resp.pw_dir_len - 1] != '\0' - || resultbuf->pw_shell[pw_resp.pw_shell_len - 1] != '\0') + if (resultbuf->pw_name[pw_resp->pw_name_len - 1] != '\0' + || resultbuf->pw_passwd[pw_resp->pw_passwd_len - 1] != '\0' + || resultbuf->pw_gecos[pw_resp->pw_gecos_len - 1] != '\0' + || resultbuf->pw_dir[pw_resp->pw_dir_len - 1] != '\0' + || resultbuf->pw_shell[pw_resp->pw_shell_len - 1] != '\0') { /* We cannot use the database. */ - retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1; + retval = -1; goto out_close; } @@ -221,21 +215,21 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, if (sock != -1) close_not_cancel_no_status (sock); out: - if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) { /* When we come here this means there has been a GC cycle while we were looking for the data. This means the data might have been inconsistent. Retry if possible. */ - if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) + if ((gc_cycle & 1) != 0) { /* nscd is just running gc now. Disable using the mapping. */ - if (atomic_decrement_val (&mapped->counter) == 0) - __nscd_unmap (mapped); + __nscd_unmap (mapped); mapped = NO_MAPPING; } - if (retval != -1) - goto retry; + free (resultbuf); + + goto retry; } return retval; diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index 71ea53e19d..0e16cb8aeb 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1998-2002,2003,2004,2005,2006,2007 - Free Software Foundation, Inc. +/* Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -22,14 +21,11 @@ #include <errno.h> #include <fcntl.h> #include <stdbool.h> -#include <string.h> -#include <time.h> #include <unistd.h> #include <sys/mman.h> #include <sys/poll.h> #include <sys/socket.h> #include <sys/stat.h> -#include <sys/time.h> #include <sys/uio.h> #include <sys/un.h> #include <not-cancel.h> @@ -38,64 +34,6 @@ #include "nscd-client.h" -ssize_t -__readall (int fd, void *buf, size_t len) -{ - size_t n = len; - ssize_t ret; - do - { - ret = TEMP_FAILURE_RETRY (__read (fd, buf, n)); - if (ret <= 0) - break; - buf = (char *) buf + ret; - n -= ret; - } - while (n > 0); - return ret < 0 ? ret : len - n; -} - - -ssize_t -__readvall (int fd, const struct iovec *iov, int iovcnt) -{ - ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt)); - if (ret <= 0) - return ret; - - size_t total = 0; - for (int i = 0; i < iovcnt; ++i) - total += iov[i].iov_len; - - if (ret < total) - { - struct iovec iov_buf[iovcnt]; - ssize_t r = ret; - - struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov)); - do - { - while (iovp->iov_len <= r) - { - r -= iovp->iov_len; - --iovcnt; - ++iovp; - } - iovp->iov_base = (char *) iovp->iov_base + r; - iovp->iov_len -= r; - r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt)); - if (r <= 0) - break; - ret += r; - } - while (ret < total); - if (r < 0) - ret = r; - } - return ret; -} - - static int open_socket (void) { @@ -139,36 +77,6 @@ __nscd_unmap (struct mapped_database *mapped) } -static int -wait_on_socket (int sock) -{ - struct pollfd fds[1]; - fds[0].fd = sock; - fds[0].events = POLLIN | POLLERR | POLLHUP; - int n = __poll (fds, 1, 5 * 1000); - if (n == -1 && __builtin_expect (errno == EINTR, 0)) - { - /* Handle the case where the poll() call is interrupted by a - signal. We cannot just use TEMP_FAILURE_RETRY since it might - lead to infinite loops. */ - struct timeval now; - (void) __gettimeofday (&now, NULL); - long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000; - while (1) - { - long int timeout = end - (now.tv_sec * 1000 - + (now.tv_usec + 500) / 1000); - n = __poll (fds, 1, timeout); - if (n != -1 || errno != EINTR) - break; - (void) __gettimeofday (&now, NULL); - } - } - - return n; -} - - /* Try to get a file descriptor for the shared meory segment containing the database. */ static struct mapped_database * @@ -178,115 +86,102 @@ get_mapping (request_type type, const char *key, struct mapped_database *result = NO_MAPPING; #ifdef SCM_RIGHTS const size_t keylen = strlen (key) + 1; + char resdata[keylen]; int saved_errno = errno; int mapfd = -1; /* Send the request. */ - struct - { - request_header req; - char key[keylen]; - } reqdata; - size_t real_sizeof_reqdata = sizeof (request_header) + keylen; + struct iovec iov[2]; + request_header req; int sock = open_socket (); if (sock < 0) goto out; - reqdata.req.version = NSCD_VERSION; - reqdata.req.type = type; - reqdata.req.key_len = keylen; - memcpy (reqdata.key, key, keylen); - -# ifndef MSG_NOSIGNAL -# define MSG_NOSIGNAL 0 -# endif - if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata, - real_sizeof_reqdata, - MSG_NOSIGNAL)) - != real_sizeof_reqdata, 0)) + req.version = NSCD_VERSION; + req.type = type; + req.key_len = keylen; + + iov[0].iov_base = &req; + iov[0].iov_len = sizeof (req); + iov[1].iov_base = (void *) key; + iov[1].iov_len = keylen; + + if (TEMP_FAILURE_RETRY (__writev (sock, iov, 2)) + != iov[0].iov_len + iov[1].iov_len) /* We cannot even write the request. */ goto out_close2; /* Room for the data sent along with the file descriptor. We expect the key name back. */ -# define resdata reqdata.key - struct iovec iov[1]; iov[0].iov_base = resdata; iov[0].iov_len = keylen; - union - { - struct cmsghdr hdr; - char bytes[CMSG_SPACE (sizeof (int))]; - } buf; + char buf[CMSG_SPACE (sizeof (int))]; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, - .msg_control = buf.bytes, - .msg_controllen = sizeof (buf) }; + .msg_control = buf, .msg_controllen = sizeof (buf) }; struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN (sizeof (int)); - /* This access is well-aligned since BUF is correctly aligned for an - int and CMSG_DATA preserves this alignment. */ *(int *) CMSG_DATA (cmsg) = -1; msg.msg_controllen = cmsg->cmsg_len; - if (wait_on_socket (sock) <= 0) - goto out_close2; - - if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0)) - != keylen, 0)) + struct pollfd fds[1]; + fds[0].fd = sock; + fds[0].events = POLLIN | POLLERR | POLLHUP; + if (__poll (fds, 1, 5 * 1000) <= 0) + /* Failure or timeout. */ goto out_close2; - if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL - || (CMSG_FIRSTHDR (&msg)->cmsg_len - != CMSG_LEN (sizeof (int))), 0)) + if (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0)) != keylen) goto out_close2; mapfd = *(int *) CMSG_DATA (cmsg); + if (CMSG_FIRSTHDR (&msg)->cmsg_len != CMSG_LEN (sizeof (int))) + goto out_close; + struct stat64 st; - if (__builtin_expect (strcmp (resdata, key) != 0, 0) - || __builtin_expect (fstat64 (mapfd, &st) != 0, 0) - || __builtin_expect (st.st_size < sizeof (struct database_pers_head), 0)) + if (strcmp (resdata, key) != 0 + || fstat64 (mapfd, &st) != 0 + || st.st_size < sizeof (struct database_pers_head)) goto out_close; struct database_pers_head head; - if (__builtin_expect (TEMP_FAILURE_RETRY (__pread (mapfd, &head, - sizeof (head), 0)) - != sizeof (head), 0)) + if (TEMP_FAILURE_RETRY (__pread (mapfd, &head, sizeof (head), 0)) + != sizeof (head)) goto out_close; - if (__builtin_expect (head.version != DB_VERSION, 0) - || __builtin_expect (head.header_size != sizeof (head), 0) + if (head.version != DB_VERSION || head.header_size != sizeof (head) /* This really should not happen but who knows, maybe the update thread got stuck. */ - || __builtin_expect (! head.nscd_certainly_running - && head.timestamp + MAPPING_TIMEOUT < time (NULL), - 0)) + || (! head.nscd_certainly_running + && head.timestamp + MAPPING_TIMEOUT < time (NULL))) goto out_close; size_t size = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN) + head.data_size); - if (__builtin_expect (st.st_size < size, 0)) + if (st.st_size < size) goto out_close; /* The file is large enough, map it now. */ void *mapping = __mmap (NULL, size, PROT_READ, MAP_SHARED, mapfd, 0); - if (__builtin_expect (mapping != MAP_FAILED, 1)) + if (mapping != MAP_FAILED) { /* Allocate a record for the mapping. */ - struct mapped_database *newp = malloc (sizeof (*newp)); + struct mapped_database *newp; + + newp = malloc (sizeof (*newp)); if (newp == NULL) { /* Ugh, after all we went through the memory allocation failed. */ - __munmap (mapping, size); + __munmap (result, size); goto out_close; } @@ -294,7 +189,6 @@ get_mapping (request_type type, const char *key, newp->data = ((char *) mapping + head.header_size + roundup (head.module * sizeof (ref_t), ALIGN)); newp->mapsize = size; - newp->datasize = head.data_size; /* Set counter to 1 to show it is usable. */ newp->counter = 1; @@ -321,18 +215,17 @@ get_mapping (request_type type, const char *key, struct mapped_database * __nscd_get_map_ref (request_type type, const char *name, - volatile struct locked_map_ptr *mapptr, int *gc_cyclep) + struct locked_map_ptr *mapptr, int *gc_cyclep) { struct mapped_database *cur = mapptr->mapped; if (cur == NO_MAPPING) return cur; int cnt = 0; - while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock, - 1, 0) != 0, 0)) + while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0) { // XXX Best number of rounds? - if (__builtin_expect (++cnt > 5, 0)) + if (++cnt > 5) return NO_MAPPING; atomic_delay (); @@ -345,10 +238,8 @@ __nscd_get_map_ref (request_type type, const char *name, /* If not mapped or timestamp not updated, request new map. */ if (cur == NULL || (cur->head->nscd_certainly_running == 0 - && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL)) - || cur->head->data_size > cur->datasize) - cur = get_mapping (type, name, - (struct mapped_database **) &mapptr->mapped); + && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))) + cur = get_mapping (type, name, &mapptr->mapped); if (__builtin_expect (cur != NO_MAPPING, 1)) { @@ -366,50 +257,28 @@ __nscd_get_map_ref (request_type type, const char *name, } -/* Don't return const struct datahead *, as eventhough the record - is normally constant, it can change arbitrarily during nscd - garbage collection. */ -struct datahead * +const struct datahead * __nscd_cache_search (request_type type, const char *key, size_t keylen, const struct mapped_database *mapped) { unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module; - size_t datasize = mapped->datasize; ref_t work = mapped->head->array[hash]; - while (work != ENDREF && work + sizeof (struct hashentry) <= datasize) + while (work != ENDREF) { 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 + keylen <= datasize - && memcmp (key, mapped->data + here->key, keylen) == 0 - && here->packet + sizeof (struct datahead) <= datasize) + if (type == here->type && keylen == here->len + && memcmp (key, mapped->data + here->key, keylen) == 0) { /* We found the entry. Increment the appropriate counter. */ - struct datahead *dh + const 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) + if (dh->usable && ((char *) dh + dh->allocsize + <= (char *) mapped->head + mapped->mapsize)) return dh; } @@ -442,13 +311,19 @@ __nscd_open_socket (const char *key, size_t keylen, request_type type, vec[1].iov_len = keylen; ssize_t nbytes = TEMP_FAILURE_RETRY (__writev (sock, vec, 2)); - if (nbytes == (ssize_t) (sizeof (request_header) + keylen) - /* Wait for data. */ - && wait_on_socket (sock) > 0) + if (nbytes == (ssize_t) (sizeof (request_header) + keylen)) { - nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen)); - if (nbytes == (ssize_t) responselen) - return sock; + /* Wait for data. */ + struct pollfd fds[1]; + fds[0].fd = sock; + fds[0].events = POLLIN | POLLERR | POLLHUP; + if (__poll (fds, 1, 5 * 1000) > 0) + { + nbytes = TEMP_FAILURE_RETRY (__read (sock, response, + responselen)); + if (nbytes == (ssize_t) responselen) + return sock; + } } close_not_cancel_no_status (sock); diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c index 866455a96c..2ea9e7f862 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 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -30,7 +30,7 @@ /* We use the same mapping as in nscd_getgr. */ -libc_locked_map_ptr (extern, __gr_map_handle) attribute_hidden; +libc_locked_map_ptr (extern, __gr_map_handle); int @@ -39,7 +39,6 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size, { size_t userlen = strlen (user) + 1; int gc_cycle; - int nretries = 0; /* If the mapping is available, try to search there instead of communicating with the nscd. */ @@ -47,49 +46,44 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size, mapped = __nscd_get_map_ref (GETFDGR, "group", &__gr_map_handle, &gc_cycle); retry:; + const initgr_response_header *initgr_resp = NULL; char *respdata = NULL; int retval = -1; int sock = -1; - initgr_response_header initgr_resp; if (mapped != NO_MAPPING) { - struct datahead *found = __nscd_cache_search (INITGROUPS, user, - userlen, mapped); + const struct datahead *found = __nscd_cache_search (INITGROUPS, user, + userlen, mapped); if (found != NULL) { - respdata = (char *) (&found->data[0].initgrdata + 1); - initgr_resp = found->data[0].initgrdata; + initgr_resp = &found->data[0].initgrdata; + respdata = (char *) (initgr_resp + 1); char *recend = (char *) found->data + found->recsize; - /* Now check if we can trust initgr_resp fields. If GC is - in progress, it can contain anything. */ - if (mapped->head->gc_cycle != gc_cycle) - { - retval = -2; - goto out; - } - - if (respdata + initgr_resp.ngrps * sizeof (int32_t) > recend) + if (respdata + initgr_resp->ngrps * sizeof (int32_t) > recend) goto out; } } /* If we do not have the cache mapped, try to get the data over the socket. */ - if (respdata == NULL) + initgr_response_header initgr_resp_mem; + if (initgr_resp == NULL) { - sock = __nscd_open_socket (user, userlen, INITGROUPS, &initgr_resp, - sizeof (initgr_resp)); + sock = __nscd_open_socket (user, userlen, INITGROUPS, &initgr_resp_mem, + sizeof (initgr_resp_mem)); if (sock == -1) { - /* nscd not running or wrong version. */ + /* nscd not running or wrong version or hosts caching disabled. */ __nss_not_use_nscd_group = 1; goto out; } + + initgr_resp = &initgr_resp_mem; } - if (initgr_resp.found == 1) + if (initgr_resp->found == 1) { /* The following code assumes that gid_t and int32_t are the same size. This is the case for al existing implementation. @@ -97,46 +91,40 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size, doesn't use memcpy but instead copies each array element one by one. */ assert (sizeof (int32_t) == sizeof (gid_t)); - assert (initgr_resp.ngrps >= 0); + assert (initgr_resp->ngrps > 0); /* Make sure we have enough room. We always count GROUP in even though we might not end up adding it. */ - if (*size < initgr_resp.ngrps + 1) + if (*size < initgr_resp->ngrps + 1) { gid_t *newp = realloc (*groupsp, - (initgr_resp.ngrps + 1) * sizeof (gid_t)); + (initgr_resp->ngrps + 1) * sizeof (gid_t)); if (newp == NULL) /* We cannot increase the buffer size. */ - goto out_close; + goto out; *groupsp = newp; - *size = initgr_resp.ngrps + 1; + *size = initgr_resp->ngrps + 1; } if (respdata == NULL) { /* Read the data from the socket. */ - if ((size_t) __readall (sock, *groupsp, initgr_resp.ngrps - * sizeof (gid_t)) - == initgr_resp.ngrps * sizeof (gid_t)) - retval = initgr_resp.ngrps; + if ((size_t) TEMP_FAILURE_RETRY (__read (sock, *groupsp, + initgr_resp->ngrps + * sizeof (gid_t))) + == initgr_resp->ngrps * sizeof (gid_t)) + retval = initgr_resp->ngrps; } else { /* Just copy the data. */ - retval = initgr_resp.ngrps; + retval = initgr_resp->ngrps; memcpy (*groupsp, respdata, retval * sizeof (gid_t)); } } else { - if (__builtin_expect (initgr_resp.found == -1, 0)) - { - /* The daemon does not cache this database. */ - __nss_not_use_nscd_group = 1; - goto out_close; - } - /* No group found yet. */ retval = 0; @@ -155,25 +143,22 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size, (*groupsp)[retval++] = group; } - out_close: if (sock != -1) close_not_cancel_no_status (sock); out: - if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) + if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1) { /* When we come here this means there has been a GC cycle while we were looking for the data. This means the data might have been inconsistent. Retry if possible. */ - if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) + if ((gc_cycle & 1) != 0) { /* nscd is just running gc now. Disable using the mapping. */ - if (atomic_decrement_val (&mapped->counter) == 0) - __nscd_unmap (mapped); + __nscd_unmap (mapped); mapped = NO_MAPPING; } - if (retval != -1) - goto retry; + goto retry; } return retval; diff --git a/nscd/nscd_nischeck.c b/nscd/nscd_nischeck.c new file mode 100644 index 0000000000..a6817cf79e --- /dev/null +++ b/nscd/nscd_nischeck.c @@ -0,0 +1,96 @@ +/* Copyright (c) 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* nscd_nischeck: Check, if everybody has read permissions for NIS+ table. + Return value: + 0: Everybody can read the NIS+ table + 1: Only authenticated users could read the NIS+ table */ + +#include <argp.h> +#include <error.h> +#include <stdlib.h> +#include <libintl.h> +#include <locale.h> +#include <rpcsvc/nis.h> + +/* Get libc version number. */ +#include <version.h> + +#define PACKAGE _libc_intl_domainname + +/* Name and version of program. */ +static void print_version (FILE *stream, struct argp_state *state); +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Data structure to communicate with argp functions. */ +static struct argp argp = +{ + NULL, NULL, NULL, NULL, +}; + +int +main (int argc, char **argv) +{ + int remaining; + nis_result *res; + char *tablename, *cp; + + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); + /* Set the text message domain. */ + textdomain (PACKAGE); + + /* Parse and process arguments. */ + argp_parse (&argp, argc, argv, 0, &remaining, NULL); + + if (remaining + 1 != argc) + { + error (0, 0, gettext ("wrong number of arguments")); + argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name); + exit (EXIT_FAILURE); + } + + tablename = alloca (strlen (argv[1]) + 10); + cp = stpcpy (tablename, argv[1]); + strcpy (cp, ".org_dir"); + + res = nis_lookup (tablename, EXPAND_NAME|FOLLOW_LINKS); + + if (res == NULL || + (res->status != NIS_SUCCESS && res->status != NIS_S_SUCCESS)) + return 0; + + if (NIS_NOBODY(NIS_RES_OBJECT(res)->zo_access, NIS_READ_ACC)) + return 0; + else + return 1; +} + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "nscd_nischeck (GNU %s) %s\n", PACKAGE, VERSION); + fprintf (stream, gettext ("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), "2004"); + fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk"); +} diff --git a/nscd/nscd_setup_thread.c b/nscd/nscd_setup_thread.c deleted file mode 100644 index 32bfe07000..0000000000 --- a/nscd/nscd_setup_thread.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Setup of nscd worker threads. Stub verison. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include <nscd.h> - - -void -setup_thread (struct database_dyn *db) -{ - /* Nothing. */ -} diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c index 7f6bd1c83e..9231642278 100644 --- a/nscd/nscd_stat.c +++ b/nscd/nscd_stat.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (c) 1998, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998. @@ -24,7 +24,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/socket.h> #include <unistd.h> #include <libintl.h> @@ -76,10 +75,6 @@ struct statdata int debug_level; time_t runtime; unsigned long int client_queued; - int nthreads; - int max_nthreads; - int paranoia; - time_t restart_interval; int ndbs; struct dbstat dbs[lastdb]; #ifdef HAVE_SELINUX @@ -98,10 +93,6 @@ send_stats (int fd, struct database_dyn dbs[lastdb]) data.debug_level = debug_level; data.runtime = time (NULL) - start_time; data.client_queued = client_queued; - data.nthreads = nthreads; - data.max_nthreads = max_nthreads; - data.paranoia = paranoia; - data.restart_interval = restart_interval; data.ndbs = lastdb; for (cnt = 0; cnt < lastdb; ++cnt) @@ -134,8 +125,7 @@ send_stats (int fd, struct database_dyn dbs[lastdb]) if (selinux_enabled) nscd_avc_cache_stats (&data.cstats); - if (TEMP_FAILURE_RETRY (send (fd, &data, sizeof (data), MSG_NOSIGNAL)) - != sizeof (data)) + if (TEMP_FAILURE_RETRY (write (fd, &data, sizeof (data))) != sizeof (data)) { char buf[256]; dbg_log (_("cannot write statistics: %s"), @@ -153,8 +143,8 @@ receive_print_stats (void) int fd; int i; uid_t uid = getuid (); - const char *yesstr = _("yes"); - const char *nostr = _("no"); + const char *yesstr = nl_langinfo (YESSTR); + const char *nostr = nl_langinfo (NOSTR); /* Find out whether there is another user but root allowed to request statistics. */ @@ -182,8 +172,7 @@ receive_print_stats (void) req.version = NSCD_VERSION; req.type = GETSTAT; req.key_len = 0; - nbytes = TEMP_FAILURE_RETRY (send (fd, &req, sizeof (request_header), - MSG_NOSIGNAL)); + nbytes = TEMP_FAILURE_RETRY (write (fd, &req, sizeof (request_header))); if (nbytes != sizeof (request_header)) { int err = errno; @@ -241,9 +230,8 @@ receive_print_stats (void) "%15lu number of times clients had to wait\n" "%15s paranoia mode enabled\n" "%15lu restart internal\n"), - data.nthreads, data.max_nthreads, data.client_queued, - data.paranoia ? yesstr : nostr, - (unsigned long int) data.restart_interval); + nthreads, max_nthreads, data.client_queued, + paranoia ? yesstr : nostr, (unsigned long int) restart_interval); for (i = 0; i < lastdb; ++i) { diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index ae579df510..e8b9578778 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -1,20 +1,22 @@ /* Cache handling for passwd lookup. - Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <alloca.h> #include <assert.h> @@ -30,14 +32,10 @@ #include <time.h> #include <unistd.h> #include <sys/mman.h> -#include <sys/socket.h> #include <stackinfo.h> #include "nscd.h" #include "dbg_log.h" -#ifdef HAVE_SENDFILE -# include <kernel-features.h> -#endif /* This is the standard reply in case the service is disabled. */ static const pw_response_header disabled = @@ -116,8 +114,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, written = total = sizeof (notfound); if (fd != -1) - written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, - MSG_NOSIGNAL)); + written = TEMP_FAILURE_RETRY (write (fd, ¬found, total)); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); /* If we cannot permanently store the result, so be it. */ @@ -274,7 +271,6 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, { /* Adjust pointer into the memory block. */ cp = (char *) newp + (cp - (char *) dataset); - key_copy = (char *) newp + (key_copy - (char *) dataset); dataset = memcpy (newp, dataset, total + n); alloca_used = false; @@ -291,30 +287,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, unnecessarily let the receiver wait. */ assert (fd != -1); -#ifdef HAVE_SENDFILE - if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); - assert ((char *) &dataset->resp - (char *) db->head - + total - <= (sizeof (struct database_pers_head) - + db->head->module * sizeof (ref_t) - + db->head->data_size)); - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); -# ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; -# endif - } - else -# ifndef __ASSUME_SENDFILE - use_write: -# endif -#endif - written = writeall (fd, &dataset->resp, total); + written = TEMP_FAILURE_RETRY (write (fd, &dataset->resp, total)); } @@ -339,10 +312,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, marked with FIRST first. Otherwise we end up with dangling "pointers" in case a latter hash entry cannot be added. */ - bool first = true; + bool first = req->type == GETPWBYNAME; /* If the request was by UID, add that entry first. */ - if (req->type == GETPWBYUID) + if (req->type != GETPWBYNAME) { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, db, owner) < 0) @@ -352,14 +325,12 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, dataset->head.usable = false; goto out; } - - first = false; } /* If the key is different from the name add a separate entry. */ else if (strcmp (key_copy, dataset->strdata) != 0) { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, first, db, owner) < 0) { /* Could not allocate memory. Make sure the data gets discarded. */ @@ -371,12 +342,11 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, } /* We have to add the value for both, byname and byuid. */ - if ((req->type == GETPWBYNAME || db->propagate) - && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, - pw_name_len, &dataset->head, - first, db, owner) == 0, 1)) + if (__builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, + pw_name_len, &dataset->head, first, + db, owner) == 0, 1)) { - if (req->type == GETPWBYNAME && db->propagate) + if (req->type == GETPWBYNAME) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, req->type != GETPWBYNAME, db, owner); } @@ -455,10 +425,11 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, { char *old_buffer = buffer; errno = 0; +#define INCR 1024 if (__builtin_expect (buflen > 32768, 0)) { - buflen *= 2; + buflen += INCR; buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen); if (buffer == NULL) { @@ -479,7 +450,7 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, else /* Allocate a new buffer on the stack. If possible combine it with the previously allocated buffer. */ - buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen); + buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR); } #if 0 diff --git a/nscd/selinux.c b/nscd/selinux.c index b826031150..f57f0920ae 100644 --- a/nscd/selinux.c +++ b/nscd/selinux.c @@ -1,5 +1,5 @@ /* SELinux access controls for nscd. - Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Matthew Rickard <mjricka@epoch.ncsc.mil>, 2004. @@ -18,7 +18,6 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "config.h" #include <error.h> #include <errno.h> #include <libintl.h> @@ -27,15 +26,10 @@ #include <stdio.h> #include <stdlib.h> #include <syslog.h> -#include <unistd.h> -#include <sys/prctl.h> #include <selinux/av_permissions.h> #include <selinux/avc.h> #include <selinux/flask.h> #include <selinux/selinux.h> -#ifdef HAVE_LIBAUDIT -# include <libaudit.h> -#endif #include "dbg_log.h" #include "selinux.h" @@ -72,11 +66,6 @@ static struct avc_entry_ref aeref; /* Thread to listen for SELinux status changes via netlink. */ static pthread_t avc_notify_thread; -#ifdef HAVE_LIBAUDIT -/* Prototype for supporting the audit daemon */ -static void log_callback (const char *fmt, ...); -#endif - /* Prototypes for AVC callback functions. */ static void *avc_create_thread (void (*run) (void)); static void avc_stop_thread (void *thread); @@ -88,11 +77,7 @@ static void avc_free_lock (void *lock); /* AVC callback structures for use in avc_init. */ static const struct avc_log_callback log_cb = { -#ifdef HAVE_LIBAUDIT - .func_log = log_callback, -#else .func_log = dbg_log, -#endif .func_audit = NULL }; static const struct avc_thread_callback thread_cb = @@ -108,137 +93,6 @@ static const struct avc_lock_callback lock_cb = .func_free_lock = avc_free_lock }; -#ifdef HAVE_LIBAUDIT -/* The audit system's netlink socket descriptor */ -static int audit_fd = -1; - -/* When an avc denial occurs, log it to audit system */ -static void -log_callback (const char *fmt, ...) -{ - if (audit_fd >= 0) - { - va_list ap; - va_start (ap, fmt); - - char *buf; - int e = vasprintf (&buf, fmt, ap); - if (e < 0) - { - buf = alloca (BUFSIZ); - vsnprintf (buf, BUFSIZ, fmt, ap); - } - - /* FIXME: need to attribute this to real user, using getuid for now */ - audit_log_user_avc_message (audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, - NULL, getuid ()); - - if (e >= 0) - free (buf); - - va_end (ap); - } -} - -/* Initialize the connection to the audit system */ -static void -audit_init (void) -{ - audit_fd = audit_open (); - if (audit_fd < 0 - /* If kernel doesn't support audit, bail out */ - && errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) - dbg_log (_("Failed opening connection to the audit subsystem: %m")); -} - - -# ifdef HAVE_LIBCAP -static const cap_value_t new_cap_list[] = - { CAP_AUDIT_WRITE }; -# define nnew_cap_list (sizeof (new_cap_list) / sizeof (new_cap_list[0])) -static const cap_value_t tmp_cap_list[] = - { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID }; -# define ntmp_cap_list (sizeof (tmp_cap_list) / sizeof (tmp_cap_list[0])) - -cap_t -preserve_capabilities (void) -{ - if (getuid () != 0) - /* Not root, then we cannot preserve anything. */ - return NULL; - - if (prctl (PR_SET_KEEPCAPS, 1) == -1) - { - dbg_log (_("Failed to set keep-capabilities")); - error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed")); - /* NOTREACHED */ - } - - cap_t tmp_caps = cap_init (); - cap_t new_caps; - if (tmp_caps != NULL) - new_caps = cap_init (); - - if (tmp_caps == NULL || new_caps == NULL) - { - if (tmp_caps != NULL) - cap_free (tmp_caps); - - dbg_log (_("Failed to initialize drop of capabilities")); - error (EXIT_FAILURE, 0, _("cap_init failed")); - } - - /* There is no reason why these should not work. */ - cap_set_flag (new_caps, CAP_PERMITTED, nnew_cap_list, - (cap_value_t *) new_cap_list, CAP_SET); - cap_set_flag (new_caps, CAP_EFFECTIVE, nnew_cap_list, - (cap_value_t *) new_cap_list, CAP_SET); - - cap_set_flag (tmp_caps, CAP_PERMITTED, ntmp_cap_list, - (cap_value_t *) tmp_cap_list, CAP_SET); - cap_set_flag (tmp_caps, CAP_EFFECTIVE, ntmp_cap_list, - (cap_value_t *) tmp_cap_list, CAP_SET); - - int res = cap_set_proc (tmp_caps); - - cap_free (tmp_caps); - - if (__builtin_expect (res != 0, 0)) - { - cap_free (new_caps); - dbg_log (_("Failed to drop capabilities\n")); - error (EXIT_FAILURE, 0, _("cap_set_proc failed")); - } - - return new_caps; -} - -void -install_real_capabilities (cap_t new_caps) -{ - /* If we have no capabilities there is nothing to do here. */ - if (new_caps == NULL) - return; - - if (cap_set_proc (new_caps)) - { - cap_free (new_caps); - dbg_log (_("Failed to drop capabilities")); - error (EXIT_FAILURE, 0, _("cap_set_proc failed")); - /* NOTREACHED */ - } - - cap_free (new_caps); - - if (prctl (PR_SET_KEEPCAPS, 0) == -1) - { - dbg_log (_("Failed to unset keep-capabilities")); - error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed")); - /* NOTREACHED */ - } -} -# endif /* HAVE_LIBCAP */ -#endif /* HAVE_LIBAUDIT */ /* Determine if we are running on an SELinux kernel. Set selinux_enabled to the result. */ @@ -328,9 +182,6 @@ nscd_avc_init (void) error (EXIT_FAILURE, errno, _("Failed to start AVC")); else dbg_log (_("Access Vector Cache (AVC) started")); -#ifdef HAVE_LIBAUDIT - audit_init (); -#endif } @@ -411,9 +262,6 @@ void nscd_avc_destroy (void) { avc_destroy (); -#ifdef HAVE_LIBAUDIT - audit_close (audit_fd); -#endif } #endif /* HAVE_SELINUX */ diff --git a/nscd/selinux.h b/nscd/selinux.h index 27afcd6e86..b9eb053aa0 100644 --- a/nscd/selinux.h +++ b/nscd/selinux.h @@ -1,5 +1,5 @@ /* Header for nscd SELinux access controls. - Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Matthew Rickard <mjricka@epoch.ncsc.mil>, 2004. @@ -22,9 +22,6 @@ #define _SELINUX_H 1 #include "nscd.h" -#ifdef HAVE_LIBCAP -# include <sys/capability.h> -#endif #ifdef HAVE_SELINUX /* Global variable to tell if the kernel has SELinux support. */ @@ -45,13 +42,6 @@ extern int nscd_request_avc_has_perm (int fd, request_type req); extern void nscd_avc_cache_stats (struct avc_cache_stats *cstats); /* Display statistics on AVC usage. */ extern void nscd_avc_print_stats (struct avc_cache_stats *cstats); - -# ifdef HAVE_LIBCAP -/* Preserve capabilities to connect to connnect to the audit daemon. */ -extern cap_t preserve_capabilities (void); -/* Install final capabilities. */ -extern void install_real_capabilities (cap_t new_caps); -# endif #else # define selinux_enabled 0 # define nscd_avc_init() (void) 0 |