From: Michal Privoznik <mprivozn(a)redhat.com>
While we were trying to decrease stack usage of some functions,
in v9.8.0-rc1~217 we introduced a couple of internal blocks to
the aiforaf() and declared some variables inside those blocks
hoping the compiler will reuse the stack for each block. While in
general this might be a good strategy, specifically in case of
NSS_NAME(gethostbyname2) this is a terrible thing to do.
Problem is, NSS_NAME(gethostbyname2) is given a caller allocated
buffer and an address of a pointer where the resolved address is
stored. And you've probably guessed it already: upon successful
return, the pointer is set to point somewhere inside the buffer.
Now, if the buffer doesn't live long enough, which in our case it
does not (since it was left in the previous block), we should
refrain from dereferencing the resolved pointer.
Just allocate the buffer on the heap.
Fixes: 9e5f2fe4021ada74adbe34ca03be60812c91f334
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
tools/nss/libvirt_nss.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/tools/nss/libvirt_nss.c b/tools/nss/libvirt_nss.c
index c1e51441b2..6ee328a8df 100644
--- a/tools/nss/libvirt_nss.c
+++ b/tools/nss/libvirt_nss.c
@@ -464,18 +464,17 @@ aiforaf(const char *name,
struct hostent resolved;
int err;
char **addrList;
+ g_autofree char *buf = NULL;
+ const size_t buf_size = 1024;
+ int herr;
- /* Note: The do-while blocks in this function are used to scope off large
- * stack allocated buffers, which are not needed at the same time */
- do {
- char buf[1024] = { 0 };
- int herr;
+ if (!(buf = calloc(buf_size, sizeof(*buf))))
+ return;
- if (NSS_NAME(gethostbyname2)(name, af, &resolved,
- buf, sizeof(buf),
- &err, &herr) != NS_SUCCESS)
- return;
- } while (false);
+ if (NSS_NAME(gethostbyname2)(name, af, &resolved,
+ buf, buf_size,
+ &err, &herr) != NS_SUCCESS)
+ return;
addrList = resolved.h_addr_list;
while (*addrList) {
--
2.49.0