diff options
author | Florian Weimer <fweimer@redhat.com> | 2015-03-01 18:59:48 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2016-04-25 06:19:30 +0200 |
commit | 4e10cf98c38e471f1c0637150c51fa2935b271fa (patch) | |
tree | a544092d359154150e288955ebba9fdd776df154 | |
parent | 4e0898ab1bd8502cf4acbbe82c1755127b561ae8 (diff) | |
download | glibc-4e10cf98c38e471f1c0637150c51fa2935b271fa.tar.gz |
nscd: Switch to struct scratch_buffer in adhstaiX
The pre-allocation of the three scratch buffers increased the initial
stack size somewhat, but if retries are needed, the previous version
used more stack space if extend_alloca could not merge allocations.
Lack of alloca accounting also means could be problematic with
extremely large NSS responses, too.
[BZ #18023]
* nscd/aicache.c (addhstaiX): Use struct scratch_buffer instead
of extend_alloca.
-rw-r--r-- | nscd/aicache.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/nscd/aicache.c b/nscd/aicache.c index a2e6cf8475..e181fdc5c3 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -26,6 +26,7 @@ #include <unistd.h> #include <sys/mman.h> #include <resolv/res_hconf.h> +#include <scratch_buffer.h> #include "dbg_log.h" #include "nscd.h" @@ -113,10 +114,13 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, int old_res_options = _res.options; _res.options &= ~RES_USE_INET6; - size_t tmpbuf6len = 1024; - char *tmpbuf6 = alloca (tmpbuf6len); - size_t tmpbuf4len = 0; - char *tmpbuf4 = NULL; + struct scratch_buffer tmpbuf6; + scratch_buffer_init (&tmpbuf6); + struct scratch_buffer tmpbuf4; + scratch_buffer_init (&tmpbuf4); + struct scratch_buffer canonbuf; + scratch_buffer_init (&canonbuf); + int32_t ttl = INT32_MAX; ssize_t total = 0; char *key_copy = NULL; @@ -129,6 +133,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; @@ -143,12 +148,17 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, at = &atmem; rc6 = 0; herrno = 0; - status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len, + status[1] = DL_CALL_FCT (fct4, (key, &at, + tmpbuf6.data, tmpbuf6.length, &rc6, &herrno, &ttl)); if (rc6 != ERANGE || (herrno != NETDB_INTERNAL && herrno != TRY_AGAIN)) break; - tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); + if (!scratch_buffer_grow (&tmpbuf6)) + { + rc6 = ENOMEM; + break; + } } if (rc6 != 0 && herrno == NETDB_INTERNAL) @@ -226,41 +236,38 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, while (1) { rc6 = 0; - status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6, - tmpbuf6len, &rc6, &herrno, &ttl, + status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], + tmpbuf6.data, tmpbuf6.length, + &rc6, &herrno, &ttl, &canon)); if (rc6 != ERANGE || herrno != NETDB_INTERNAL) break; - tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); + if (!scratch_buffer_grow (&tmpbuf6)) + { + rc6 = ENOMEM; + break; + } } if (rc6 != 0 && herrno == NETDB_INTERNAL) goto out; - /* If the IPv6 lookup has been successful do not use the - buffer used in that lookup, use a new one. */ - if (status[0] == NSS_STATUS_SUCCESS && rc6 == 0) - { - tmpbuf4len = 512; - tmpbuf4 = alloca (tmpbuf4len); - } - else - { - tmpbuf4len = tmpbuf6len; - tmpbuf4 = tmpbuf6; - } - /* Next collect IPv4 information. */ while (1) { rc4 = 0; - status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4, - tmpbuf4len, &rc4, &herrno, + status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], + tmpbuf4.data, tmpbuf4.length, + &rc4, &herrno, ttl == INT32_MAX ? &ttl : NULL, canon == NULL ? &canon : NULL)); if (rc4 != ERANGE || herrno != NETDB_INTERNAL) break; - tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len); + if (!scratch_buffer_grow (&tmpbuf4)) + { + rc4 = ENOMEM; + break; + } } if (rc4 != 0 && herrno == NETDB_INTERNAL) @@ -286,13 +293,11 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, cfct = __nss_lookup_function (nip, "getcanonname_r"); if (cfct != NULL) { - const size_t max_fqdn_len = 256; - char *buf = alloca (max_fqdn_len); char *s; int rc; - if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s, - &rc, &herrno)) + if (DL_CALL_FCT (cfct, (key, canonbuf.data, canonbuf.length, + &s, &rc, &herrno)) == NSS_STATUS_SUCCESS) canon = s; else @@ -321,18 +326,20 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, addrfamily = AF_INET6; } - size_t tmpbuflen = 512; - char *tmpbuf = alloca (tmpbuflen); int rc; while (1) { rc = __gethostbyaddr2_r (addr, addrlen, addrfamily, - &hstent_mem, tmpbuf, tmpbuflen, + &hstent_mem, + canonbuf.data, canonbuf.length, &hstent, &herrno, NULL); if (rc != ERANGE || herrno != NETDB_INTERNAL) break; - tmpbuf = extend_alloca (tmpbuf, tmpbuflen, - tmpbuflen * 2); + if (!scratch_buffer_grow (&canonbuf)) + { + rc = ENOMEM; + break; + } } if (rc == 0) @@ -560,6 +567,10 @@ next_nip: dh->usable = false; } + scratch_buffer_free (&tmpbuf6); + scratch_buffer_free (&tmpbuf4); + scratch_buffer_free (&canonbuf); + return timeout; } |