[Bug 386791] Re: libc getaddrinfo crashes if /etc/hosts has very long lines
Bug Watch Updater
386791 at bugs.launchpad.net
Thu May 26 05:33:37 UTC 2011
Launchpad has imported 6 comments from the remote bug at
http://sourceware.org/bugzilla/show_bug.cgi?id=10484.
If you reply to an imported comment from within Launchpad, your comment
will be sent to the remote bug automatically. Read more about
Launchpad's inter-bugtracker facilities at
https://help.launchpad.net/InterBugTracking.
------------------------------------------------------------------------
On 2009-08-05T15:22:27+00:00 Lars Wirzenius wrote:
If /etc/hosts contains a long line (thousands of bytes), getaddrinfo causes a
segmentation fault. A small program to test:
-- 8< ---
#include <stddef.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main(void)
{
struct addrinfo *result;
getaddrinfo("localhost", NULL, NULL, &result);
return 0;
}
--- 8< ---
On a system with short lines in /etc/hosts, the above program exits normally. If
/etc/hosts has a very long line (5500 bytes is sufficiently long), it
segmentation faults.
I think this is due to using alloca and extend_alloca to hold the line when
parsing the file, which leads to a stack overflow, which then results in the
kernel sending a SIGSEGV to the program. The parsing code is not set up to
handle that. Unfortunately, I am too stupid to provide a patch to fix this.
My test /etc/hosts file has IPv6 addresses commented out, so the segmentation
fault happens in sysdeps/posix/getaddrinfo.c, function gaih_inet, around line
531, on this line:
rc = __gethostbyname2_r (name, family, &th, tmpbuf,
tmpbuflen, &h, &herrno);
My stack limit is 8 megabytes.
This was originally filed as a bug in Ubuntu, and applies to both versions 2.9
and 2.10 in that distribution. I have compared the source file against the
current version in git, and it has no relevant changes. (I was unable to set up
a chroot to actually test the current git version, sorry.)
Original bug:
https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/386791
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/11
------------------------------------------------------------------------
On 2009-08-05T19:28:48+00:00 Fibonacci wrote:
This also happens on plain x86 processors. The original bug was found on
a PIV.
Perhaps it shouldn't be marked as x86_64.
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/13
------------------------------------------------------------------------
On 2009-10-30T05:38:19+00:00 Drepper-fsp wrote:
You have to be much more precise. I cannot reproduce any problem and your
description doesn't say where the stack overflow is supposed to happen.
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/16
------------------------------------------------------------------------
On 2009-10-30T13:49:45+00:00 Fibonacci wrote:
Try a longer line. I've gotten 100k+ lines just by using a hosts file for
adblock and then running network-admin.
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/17
------------------------------------------------------------------------
On 2011-01-07T17:40:48+00:00 agl wrote:
The following program will blow its stack and crash if I have an
/etc/hosts line longer than 4Kish.
---
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main() {
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
getaddrinfo("www.google.com", "http", &hints, &res);
return 0;
}
---
Setting the ai_family in the hints is required in order to reproduce the
crash.
(File and line references in the following are relative to git
16c2895feabae0962e0eba2b9164c6a83014bfe4)
In sysdeps/posix/getaddrinfo.c:531 we have a loop in gaih_inet which
allocas a buffer and doubles the size of that buffer each time
__gethostbyname2_r returns with ERANGE.
The __gethostbyname2_r ends up in nss/nss_files/files-hosts.c:128:
if (status == NSS_STATUS_SUCCESS»·»·······»·······»·······»······· \
»······· && _res_hconf.flags & HCONF_FLAG_MULTI)»······»·······»······· \
»·······{»······»·······»·······»·······»·······»·······»·······»······· \
»······· /* We have to get all host entries from the file. */»»······· \
»······· const size_t tmp_buflen = MIN (buflen, 4096);»»·······»······· \
»······· char tmp_buffer[tmp_buflen]»··»·······»·······»·······»······· \
»······· __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));\
Here, if HCONF_FLAG_MULTI is set then a secondary buffer is created on
the stack for the use of internal_getent. This buffer is limited to 4K
in size.
internal_getent will try to read lines from /etc/hosts and it will
return ERANGE if the line (plus an internal structure) doesn't fit into
|tmp_buffer|. When this happens the loop in getaddrinfo.c will try
doubling the size of its buffer. However, |tmp_buffer| was limited to 4K
so __gethostbyname2_r repeatedly returns ERANGE and gaih_inet uselessly
expands the buffer on the stack until the program crashes.
I believe that the best solution is to replace:
const size_t tmp_buflen = MIN (buflen, 4096);
with:
const size_t tmp_buflen = buflen;
I can confirm that this fixes the crash for me.
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/18
------------------------------------------------------------------------
On 2011-01-13T16:29:25+00:00 Drepper-fsp wrote:
I've checked in a patch.
Reply at: https://bugs.launchpad.net/glibc/+bug/386791/comments/19
** Changed in: glibc
Status: In Progress => Fix Released
** Changed in: glibc
Importance: Unknown => Low
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to eglibc in Ubuntu.
https://bugs.launchpad.net/bugs/386791
Title:
libc getaddrinfo crashes if /etc/hosts has very long lines
Status in The GNU C Library:
Fix Released
Status in “eglibc” package in Ubuntu:
Triaged
Bug description:
I'm using the latest SVN version of aMSN, compiled directly from source. When running it once, all is fine and dandy; but if I run it again whenever another instance of the program is running, it will segfault.
I reported it to the aMSN team (see http://www.amsn-project.net/forums/viewtopic.php?t=6662), and they claim the error is not within their code - apparently the culprit is a buggy version of libc. So I'm reporting it here without specifying the package.
I've attached a full backtrace obtained on GDB.
More information about the foundations-bugs
mailing list