getgrent_next_nss (compat-initgroups): Remove alloca fallback [BZ #18023]

If the caller-supplied buffer is not large enough, fall back directly
malloc.

The previous __libc_use_alloca check was incorrect because it did not
take into account that extend_alloca may fail to merge allocations, so
it would underestimate the stack space being used by roughly a factor
of two.
This commit is contained in:
Florian Weimer 2018-06-25 18:56:42 +02:00
parent 6b7b2abac7
commit 90d9d9ce2f
2 changed files with 27 additions and 25 deletions

View File

@ -1,3 +1,9 @@
2018-06-25 Florian Weimer <fweimer@redhat.com>
[BZ #18023]
* nss/nss_compat/compat-initgroups.c (getgrent_next_nss): Fall
back to malloc directly, without stack allocations.
2018-06-25 Florian Weimer <fweimer@redhat.com> 2018-06-25 Florian Weimer <fweimer@redhat.com>
[BZ #18023] [BZ #18023]

View File

@ -261,7 +261,6 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
overwrite the pointer with one to a bigger buffer. */ overwrite the pointer with one to a bigger buffer. */
char *tmpbuf = buffer; char *tmpbuf = buffer;
size_t tmplen = buflen; size_t tmplen = buflen;
bool use_malloc = false;
for (int i = 0; i < mystart; i++) for (int i = 0; i < mystart; i++)
{ {
@ -270,29 +269,26 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
== NSS_STATUS_TRYAGAIN == NSS_STATUS_TRYAGAIN
&& *errnop == ERANGE) && *errnop == ERANGE)
{ {
if (__libc_use_alloca (tmplen * 2)) /* Check for overflow. */
{ if (__glibc_unlikely (tmplen * 2 < tmplen))
if (tmpbuf == buffer) {
{ __set_errno (ENOMEM);
tmplen *= 2; status = NSS_STATUS_TRYAGAIN;
tmpbuf = __alloca (tmplen); goto done;
} }
else /* Increase the size. Make sure that we retry
tmpbuf = extend_alloca (tmpbuf, tmplen, tmplen * 2); with a reasonable size. */
} tmplen *= 2;
else if (tmplen < 1024)
{ tmplen = 1024;
tmplen *= 2; if (tmpbuf != buffer)
char *newbuf = realloc (use_malloc ? tmpbuf : NULL, tmplen); free (tmpbuf);
tmpbuf = malloc (tmplen);
if (newbuf == NULL) if (__glibc_unlikely (tmpbuf == NULL))
{ {
status = NSS_STATUS_TRYAGAIN; status = NSS_STATUS_TRYAGAIN;
goto done; goto done;
} }
use_malloc = true;
tmpbuf = newbuf;
}
} }
if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1)) if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1))
@ -320,7 +316,7 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
status = NSS_STATUS_NOTFOUND; status = NSS_STATUS_NOTFOUND;
done: done:
if (use_malloc) if (tmpbuf != buffer)
free (tmpbuf); free (tmpbuf);
} }