From 21032d9230e840a1f8b89d43e1e8d63ccf7c6eae Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sun, 18 May 2008 10:56:45 +0000 Subject: Updated to fedora-glibc-20080518T1017 --- ChangeLog | 30 ++++++++++++++++++++++++- fedora/branch.mk | 4 ++-- fedora/glibc.spec.in | 10 ++++++--- nscd/aicache.c | 37 ++++++++++++++++--------------- nscd/mem.c | 53 ++++++++++++++++++++++++++++++--------------- nscd/nscd.h | 2 +- resolv/nss_dns/dns-host.c | 16 +++++++++----- sysdeps/posix/getaddrinfo.c | 5 ++++- 8 files changed, 108 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index abca0a60d2..671ec52f3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2008-05-17 Ulrich Drepper + + * nscd/mem.c (gc): Avoid stack overflow when allocating move list. + + * nscd/mem.c (gc): Correctly determine highest used array element + in mark. + + * nscd/mem.c (markrange): Add assert to check entries are all + aligned. Small cleanup in bitmap use. + + * nscd/nscd.h (mem_in_flight): Replace blockaddr field with + blockoff of type nscd_ssize_t. + * nscd/mem.c (gc): Simplify markrange call for on-flight blocks. + (mempoll_alloc): Record block offset and not address. + + * nscd/mem.c (gc): Fix test for stack overuse. + + * nscd/aicache.c (addhstaiX): Fix a few small problems, cleanups, + more asserts. + + * sysdeps/posix/getaddrinfo.c (gaih_inet): If nscd reports no + entry is available, believe it. + + * resolv/nss_dns/dns-host.c (gaih_getanswer_slice): If there are + no answers return NSS_STATUS_NOTFOUND. + (gaih_getanswer): Don't call gaih_getanswer_slice if the answer + buffer does not have any content. + 2008-05-16 Ulrich Drepper * string/strcasestr.c (CMP_FUNC): Use __strncasecmp, not strncasecmp. @@ -174,7 +202,7 @@ * nscd/hstcache.c: Likewise. * nscd/initgrcache.c: Likewise. * nscd/pwdcache.c: Likewise. - * nscd/servicecache.c: Likewise. + * nscd/servicescache.c: Likewise. 2008-05-10 Roland McGrath diff --git a/fedora/branch.mk b/fedora/branch.mk index ba57c390b3..c88650ca1d 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-f8 -fedora-sync-date := 2008-05-16 21:52 UTC -fedora-sync-tag := fedora-glibc-20080516T2152 +fedora-sync-date := 2008-05-18 10:17 UTC +fedora-sync-tag := fedora-glibc-20080518T1017 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index b46ffdb70d..648e8eba09 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -19,7 +19,7 @@ Summary: The GNU libc libraries Name: glibc Version: @glibcversion@ -Release: 2 +Release: 3 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -281,8 +281,8 @@ GCC="gcc -m64" GXX="g++ -m64" %endif -BuildFlags="$BuildFlags -DNDEBUG=1 -fasynchronous-unwind-tables" -#BuildFlags="$BuildFlags -fasynchronous-unwind-tables" +#BuildFlags="$BuildFlags -DNDEBUG=1 -fasynchronous-unwind-tables" +BuildFlags="$BuildFlags -fasynchronous-unwind-tables" EnableKernel="--enable-kernel=%{enablekernel}" echo "$GCC" > Gcc AddOns=`echo */configure | sed -e 's!/configure!!g;s!\(linuxthreads\|nptl\|rtkaio\|powerpc-cpu\)\( \|$\)!!g;s! \+$!!;s! !,!g;s!^!,!;/^,\*$/d'` @@ -976,6 +976,10 @@ rm -f *.filelist* %endif %changelog +* Sun May 18 2008 Jakub Jelinek 2.8.90-3 +- getaddrinfo and nscd fixes +- reenable assertion checking in rawhide + * Fri May 16 2008 Jakub Jelinek 2.8.90-2 - fix getaddrinfo (#446801, #446808) diff --git a/nscd/aicache.c b/nscd/aicache.c index 918efc9f39..7ae5a1645c 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -114,7 +114,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, char *tmpbuf6 = alloca (tmpbuf6len); size_t tmpbuf4len = 0; char *tmpbuf4 = NULL; - char *canon = NULL; int32_t ttl = INT32_MAX; ssize_t total = 0; char *key_copy = NULL; @@ -126,6 +125,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL }; int naddrs = 0; size_t addrslen = 0; + char *canon = NULL; size_t canonlen; nss_gethostbyname4_r fct4 = __nss_lookup_function (nip, @@ -136,9 +136,11 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, while (1) { rc6 = 0; - status[0] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len, + herrno = 0; + status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len, &rc6, &herrno, &ttl)); - if (rc6 != ERANGE || herrno != NETDB_INTERNAL) + if (rc6 != ERANGE || (herrno != NETDB_INTERNAL + && herrno != TRY_AGAIN)) break; tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); } @@ -146,22 +148,21 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, if (rc6 != 0 && herrno == NETDB_INTERNAL) goto out; - if (status[0] != NSS_STATUS_SUCCESS) + if (status[1] != NSS_STATUS_SUCCESS) goto next_nip; /* We found the data. Count the addresses and the size. */ - for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next) + for (const struct gaih_addrtuple *at2 = at; at2 != NULL; + at2 = at2->next) { ++naddrs; - /* We handle unknown types here the best we can: assume - the maximum size for the address. */ + /* We do not handle anything other than IPv4 and IPv6 + addresses. The getaddrinfo implementation does not + either so it is not worth trying to do more. */ if (at2->family == AF_INET) addrslen += INADDRSZ; - else if (at2->family == AF_INET6 - && IN6ADDRSZ != sizeof (at2->addr)) + else if (at2->family == AF_INET6) addrslen += IN6ADDRSZ; - else - addrslen += sizeof (at2->addr); } canon = at->name; canonlen = strlen (canon) + 1; @@ -191,19 +192,17 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, } /* Fill in the address and address families. */ - char *addrs = (char *) (&dataset->resp + 1); + char *addrs = dataset->strdata; uint8_t *family = (uint8_t *) (addrs + addrslen); - for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next) + for (const struct gaih_addrtuple *at2 = at; at2 != NULL; + at2 = at2->next) { *family++ = at2->family; if (at2->family == AF_INET) addrs = mempcpy (addrs, at2->addr, INADDRSZ); - else if (at2->family == AF_INET6 - && IN6ADDRSZ != sizeof (at2->addr)) + else if (at2->family == AF_INET6) addrs = mempcpy (addrs, at2->addr, IN6ADDRSZ); - else - addrs = mempcpy (addrs, at2->addr, sizeof (at2->addr)); } cp = family; @@ -373,7 +372,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, } /* Fill in the address and address families. */ - char *addrs = (char *) (&dataset->resp + 1); + char *addrs = dataset->strdata; uint8_t *family = (uint8_t *) (addrs + addrslen); for (int j = 0; j < 2; ++j) @@ -411,6 +410,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, key_copy = memcpy (cp, key, req->key_len); + assert (cp == (char *) dataset + total); + /* Now we can determine whether on refill we have to create a new record or not. */ if (he != NULL) diff --git a/nscd/mem.c b/nscd/mem.c index 14928d633c..96ff03f0df 100644 --- a/nscd/mem.c +++ b/nscd/mem.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,7 @@ static void markrange (BITMAP_T *mark, ref_t start, size_t len) { /* Adjust parameters for block alignment. */ + assert ((start & BLOCK_ALIGN_M1) == 0); start /= BLOCK_ALIGN; len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN; @@ -93,7 +95,7 @@ markrange (BITMAP_T *mark, ref_t start, size_t len) return; } - mark[elem++] |= 0xff << (start % BITS); + mark[elem++] |= ALLBITS << (start % BITS); len -= BITS - (start % BITS); } @@ -130,14 +132,14 @@ gc (struct database_dyn *db) size_t stack_used = sizeof (bool) * db->head->module; if (__builtin_expect (stack_used > MAX_STACK_USE, 0)) stack_used = 0; - size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1) - / BITS) * sizeof (BITMAP_T); - if (memory_needed <= MAX_STACK_USE) + size_t nmark = (db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS; + size_t memory_needed = nmark * sizeof (BITMAP_T); + if (stack_used + memory_needed <= MAX_STACK_USE) { mark = (BITMAP_T *) alloca (memory_needed); mark_use_malloc = false; memset (mark, '\0', memory_needed); - stack_used = memory_needed; + stack_used += memory_needed; } else { @@ -156,6 +158,7 @@ gc (struct database_dyn *db) he = alloca (db->head->nentries * sizeof (struct hashentry *)); he_data = alloca (db->head->nentries * sizeof (struct hashentry *)); he_use_malloc = false; + stack_used += memory_needed; } else { @@ -212,11 +215,12 @@ gc (struct database_dyn *db) for (enum in_flight idx = IDX_result_data; idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx) { - assert ((char *) mrunp->block[idx].blockaddr > db->data); - assert ((char *) mrunp->block[idx].blockaddr - + mrunp->block[0].blocklen <= db->data + db->memsize); - markrange (mark, (char *) mrunp->block[idx].blockaddr - db->data, - mrunp->block[idx].blocklen); + assert (mrunp->block[idx].blockoff >= 0); + assert (mrunp->block[idx].blocklen < db->memsize); + assert (mrunp->block[idx].blockoff + + mrunp->block[0].blocklen <= db->memsize); + markrange (mark, mrunp->block[idx].blockoff, + mrunp->block[idx].blocklen); } mrunp = mrunp->next; @@ -232,7 +236,7 @@ gc (struct database_dyn *db) qsort (he, cnt, sizeof (struct hashentry *), sort_he); /* Determine the highest used address. */ - size_t high = sizeof (mark); + size_t high = nmark; while (high > 0 && mark[high - 1] == 0) --high; @@ -303,6 +307,10 @@ gc (struct database_dyn *db) size_t size; struct moveinfo *next; } *moves = NULL; +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + struct obstack ob; + obstack_init (&ob); while (byte < high) { @@ -363,8 +371,14 @@ gc (struct database_dyn *db) displacement. */ ref_t disp = off_alloc - off_free; - struct moveinfo *new_move - = (struct moveinfo *) alloca (sizeof (*new_move)); + struct moveinfo *new_move; + if (stack_used + sizeof (*new_move) <= MAX_STACK_USE) + { + new_move = alloca (sizeof (*new_move)); + stack_used += sizeof (*new_move); + } + else + new_move = obstack_alloc (&ob, sizeof (*new_move)); new_move->from = db->data + off_alloc; new_move->to = db->data + off_free; new_move->size = off_allocend - off_alloc; @@ -524,6 +538,8 @@ gc (struct database_dyn *db) free (he); if (mark_use_malloc) free (mark); + + obstack_free (&ob, NULL); } @@ -589,15 +605,16 @@ mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx) } else { - db->head->first_free += len; - - db->last_alloc_failed = false; - /* Remember that we have allocated this memory. */ assert (idx >= 0 && idx < IDX_last); mem_in_flight.block[idx].dbidx = db - dbs; mem_in_flight.block[idx].blocklen = len; - mem_in_flight.block[idx].blockaddr = res; + mem_in_flight.block[idx].blockoff = db->head->first_free; + + db->head->first_free += len; + + db->last_alloc_failed = false; + } pthread_mutex_unlock (&db->memlock); diff --git a/nscd/nscd.h b/nscd/nscd.h index 66813e7480..b024017fd4 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -197,7 +197,7 @@ extern __thread struct mem_in_flight { int dbidx; nscd_ssize_t blocklen; - void *blockaddr; + nscd_ssize_t blockoff; } block[IDX_last]; struct mem_in_flight *next; diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index c52f9f7f84..d998ebf4f5 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -990,6 +990,9 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, char *h_name = NULL; int h_namelen = 0; + if (ancount == 0) + return NSS_STATUS_NOTFOUND; + while (ancount-- > 0 && cp < end_of_message && had_error == 0) { n = __ns_name_unpack (answer->buf, end_of_message, cp, @@ -1164,12 +1167,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, { int first = 1; - enum nss_status status = gaih_getanswer_slice(answer1, anslen1, qname, - &pat, &buffer, &buflen, - errnop, h_errnop, ttlp, - &first); + enum nss_status status = NSS_STATUS_NOTFOUND; + + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND) - && answer2 != NULL) + && answer2 != NULL && anslen2 > 0) status = gaih_getanswer_slice(answer2, anslen2, qname, &pat, &buffer, &buflen, errnop, h_errnop, ttlp, &first); diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 2515d23c26..5c82b5274a 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -660,7 +660,10 @@ gaih_inet (const char *name, const struct gaih_service *service, goto process_list; } - else if (err != 0 && __nss_not_use_nscd_hosts == 0) + else if (err == 0) + /* The database contains a negative entry. */ + return 0; + else if (__nss_not_use_nscd_hosts == 0) { if (herrno == NETDB_INTERNAL && errno == ENOMEM) return -EAI_MEMORY; -- cgit v1.2.3