|
|
ce426f |
commit af37a8a3496327a6e5617a2c76f17aa1e8db835e
|
|
|
ce426f |
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
|
ce426f |
Date: Mon Jan 27 11:32:44 2014 +0530
|
|
|
ce426f |
|
|
|
ce426f |
Avoid undefined behaviour in netgroupcache
|
|
|
ce426f |
|
|
|
ce426f |
Using a buffer after it has been reallocated is undefined behaviour,
|
|
|
ce426f |
so get offsets of the triplets in the old buffer before reallocating
|
|
|
ce426f |
it.
|
|
|
ce426f |
|
|
|
ce426f |
commit 5d41dadf31bc8a2f9c34c40d52a442d3794e405c
|
|
|
ce426f |
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
|
ce426f |
Date: Fri Jan 24 13:51:15 2014 +0530
|
|
|
ce426f |
|
|
|
ce426f |
Adjust pointers to triplets in netgroup query data (BZ #16474)
|
|
|
ce426f |
|
|
|
ce426f |
The _nss_*_getnetgrent_r query populates the netgroup results in the
|
|
|
ce426f |
allocated buffer and then sets the result triplet to point to strings
|
|
|
ce426f |
in the buffer. This is a problem when the buffer is reallocated since
|
|
|
ce426f |
the pointers to the triplet strings are no longer valid. The pointers
|
|
|
ce426f |
need to be adjusted so that they now point to strings in the
|
|
|
ce426f |
reallocated buffer.
|
|
|
ce426f |
|
|
|
ce426f |
commit 980cb5180e1b71224a57ca52b995c959b7148c09
|
|
|
ce426f |
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
|
ce426f |
Date: Thu Jan 16 10:20:22 2014 +0530
|
|
|
ce426f |
|
|
|
ce426f |
Don't use alloca in addgetnetgrentX (BZ #16453)
|
|
|
ce426f |
|
|
|
ce426f |
addgetnetgrentX has a buffer which is grown as per the needs of the
|
|
|
ce426f |
requested size either by using alloca or by falling back to malloc if
|
|
|
ce426f |
the size is larger than 1K. There are two problems with the alloca
|
|
|
ce426f |
bits: firstly, it doesn't really extend the buffer since it does not
|
|
|
ce426f |
use the return value of the extend_alloca macro, which is the location
|
|
|
ce426f |
of the reallocated buffer. Due to this the buffer does not actually
|
|
|
ce426f |
extend itself and hence a subsequent write may overwrite stuff on the
|
|
|
ce426f |
stack.
|
|
|
ce426f |
|
|
|
ce426f |
The second problem is more subtle - the buffer growth on the stack is
|
|
|
ce426f |
discontinuous due to block scope local variables. Combine that with
|
|
|
ce426f |
the fact that unlike realloc, extend_alloca does not copy over old
|
|
|
ce426f |
content and you have a situation where the buffer just has garbage in
|
|
|
ce426f |
the space where it should have had data.
|
|
|
ce426f |
|
|
|
ce426f |
This could have been fixed by adding code to copy over old data
|
|
|
ce426f |
whenever we call extend_alloca, but it seems unnecessarily
|
|
|
ce426f |
complicated. This code is not exactly a performance hotspot (it's
|
|
|
ce426f |
called when there is a cache miss, so factors like network lookup or
|
|
|
ce426f |
file reads will dominate over memory allocation/reallocation), so this
|
|
|
ce426f |
premature optimization is unnecessary.
|
|
|
ce426f |
|
|
|
ce426f |
Thanks Brad Hubbard <bhubbard@redhat.com> for his help with debugging
|
|
|
ce426f |
the problem.
|
|
|
ce426f |
|
|
|
ce426f |
diff -pruN glibc-2.17-c758a686/nscd/netgroupcache.c glibc-2.17-c758a686/nscd/netgroupcache.c
|
|
|
ce426f |
--- glibc-2.17-c758a686/nscd/netgroupcache.c 2014-04-09 12:13:58.618582111 +0530
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nscd/netgroupcache.c 2014-04-09 12:07:21.486598665 +0530
|
|
|
ce426f |
@@ -93,7 +93,6 @@ addgetnetgrentX (struct database_dyn *db
|
|
|
ce426f |
size_t buffilled = sizeof (*dataset);
|
|
|
ce426f |
char *buffer = NULL;
|
|
|
ce426f |
size_t nentries = 0;
|
|
|
ce426f |
- bool use_malloc = false;
|
|
|
ce426f |
size_t group_len = strlen (key) + 1;
|
|
|
ce426f |
union
|
|
|
ce426f |
{
|
|
|
ce426f |
@@ -138,7 +137,7 @@ addgetnetgrentX (struct database_dyn *db
|
|
|
ce426f |
}
|
|
|
ce426f |
|
|
|
ce426f |
memset (&data, '\0', sizeof (data));
|
|
|
ce426f |
- buffer = alloca (buflen);
|
|
|
ce426f |
+ buffer = xmalloc (buflen);
|
|
|
ce426f |
first_needed.elem.next = &first_needed.elem;
|
|
|
ce426f |
memcpy (first_needed.elem.name, key, group_len);
|
|
|
ce426f |
data.needed_groups = &first_needed.elem;
|
|
|
ce426f |
@@ -218,21 +217,24 @@ addgetnetgrentX (struct database_dyn *db
|
|
|
ce426f |
|
|
|
ce426f |
if (buflen - req->key_len - bufused < needed)
|
|
|
ce426f |
{
|
|
|
ce426f |
- size_t newsize = MAX (2 * buflen,
|
|
|
ce426f |
- buflen + 2 * needed);
|
|
|
ce426f |
- if (use_malloc || newsize > 1024 * 1024)
|
|
|
ce426f |
- {
|
|
|
ce426f |
- buflen = newsize;
|
|
|
ce426f |
- char *newbuf = xrealloc (use_malloc
|
|
|
ce426f |
- ? buffer
|
|
|
ce426f |
- : NULL,
|
|
|
ce426f |
- buflen);
|
|
|
ce426f |
-
|
|
|
ce426f |
- buffer = newbuf;
|
|
|
ce426f |
- use_malloc = true;
|
|
|
ce426f |
- }
|
|
|
ce426f |
- else
|
|
|
ce426f |
- extend_alloca (buffer, buflen, newsize);
|
|
|
ce426f |
+ buflen += MAX (buflen, 2 * needed);
|
|
|
ce426f |
+ /* Save offset in the old buffer. We don't
|
|
|
ce426f |
+ bother with the NULL check here since
|
|
|
ce426f |
+ we'll do that later anyway. */
|
|
|
ce426f |
+ size_t nhostdiff = nhost - buffer;
|
|
|
ce426f |
+ size_t nuserdiff = nuser - buffer;
|
|
|
ce426f |
+ size_t ndomaindiff = ndomain - buffer;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ char *newbuf = xrealloc (buffer, buflen);
|
|
|
ce426f |
+ /* Fix up the triplet pointers into the new
|
|
|
ce426f |
+ buffer. */
|
|
|
ce426f |
+ nhost = (nhost ? newbuf + nhostdiff
|
|
|
ce426f |
+ : NULL);
|
|
|
ce426f |
+ nuser = (nuser ? newbuf + nuserdiff
|
|
|
ce426f |
+ : NULL);
|
|
|
ce426f |
+ ndomain = (ndomain ? newbuf + ndomaindiff
|
|
|
ce426f |
+ : NULL);
|
|
|
ce426f |
+ buffer = newbuf;
|
|
|
ce426f |
}
|
|
|
ce426f |
|
|
|
ce426f |
nhost = memcpy (buffer + bufused,
|
|
|
ce426f |
@@ -299,18 +301,8 @@ addgetnetgrentX (struct database_dyn *db
|
|
|
ce426f |
}
|
|
|
ce426f |
else if (status == NSS_STATUS_UNAVAIL && e == ERANGE)
|
|
|
ce426f |
{
|
|
|
ce426f |
- size_t newsize = 2 * buflen;
|
|
|
ce426f |
- if (use_malloc || newsize > 1024 * 1024)
|
|
|
ce426f |
- {
|
|
|
ce426f |
- buflen = newsize;
|
|
|
ce426f |
- char *newbuf = xrealloc (use_malloc
|
|
|
ce426f |
- ? buffer : NULL, buflen);
|
|
|
ce426f |
-
|
|
|
ce426f |
- buffer = newbuf;
|
|
|
ce426f |
- use_malloc = true;
|
|
|
ce426f |
- }
|
|
|
ce426f |
- else
|
|
|
ce426f |
- extend_alloca (buffer, buflen, newsize);
|
|
|
ce426f |
+ buflen *= 2;
|
|
|
ce426f |
+ buffer = xrealloc (buffer, buflen);
|
|
|
ce426f |
}
|
|
|
ce426f |
}
|
|
|
ce426f |
|
|
|
ce426f |
@@ -446,8 +438,7 @@ addgetnetgrentX (struct database_dyn *db
|
|
|
ce426f |
}
|
|
|
ce426f |
|
|
|
ce426f |
out:
|
|
|
ce426f |
- if (use_malloc)
|
|
|
ce426f |
- free (buffer);
|
|
|
ce426f |
+ free (buffer);
|
|
|
ce426f |
|
|
|
ce426f |
*resultp = dataset;
|
|
|
ce426f |
|