This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
blow the stack with arbitrarily-extendible VLAs
- From: Jim Meyering <jim at meyering dot net>
- To: libc-alpha at sourceware dot org
- Date: Sat, 05 May 2007 22:27:56 +0200
- Subject: blow the stack with arbitrarily-extendible VLAs
After seeing the recently-fixed user-extendible VLA in vfprintf.c,
I wondered if there were others.
Here's the result of a quick survey:
------------------------
from lio_listio.c:
Calling lio_listio with NENT too large blows the stack:
lio_listio_internal (int mode, struct aiocb *const list[], int nent,
struct sigevent *sig)
{
struct sigevent defsigev;
struct requestlist *requests[nent];
...
struct waitlist waitlist[nent];
Here's sample code:
#include <aio.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
return lio_listio (0, NULL, atoi(argv[1]), NULL);
}
Of course, with all the 0 arguments, it'll segfault for most positive
arguments, but if you give it a value larger than about 8MB (and smaller
than INT_MAX), it'll trigger the bug:
$ gcc -Wall -O k.c -lrt && ./a.out 9999999
zsh: segmentation fault ./a.out 9999999
[Exit 139 (SEGV)]
E.g., valgrind reports this:
...
==13681== Warning: client switching stacks? SP change: 0x7FF000050 --> 0x7FA3B4C40
==13681== to suppress, use: --max-stackframe=80000016 or greater
==13681== Invalid write of size 8
==13681== at 0x4B2667B: lio_listio_internal (lio_listio.c:76)
==13681== Address 0x7FA3B4C38 is on thread 1's stack
============================================================================
sysdeps/mach/hurd/poll.c(__poll) calls _hurd_select with "nfds",
which is the 2nd param to poll. If it's too big, that blows
the stack (from hurd/hurdselect.c):
[ hurd/hurdselect.c does the same thing ]
struct
{
struct hurd_userlink ulink;
struct hurd_fd *cell;
mach_port_t io_port;
int type;
mach_port_t reply_port;
} d[nfds];
============================================================================
Similarly, for getaddrinfo_a's 3rd parameter:
int
getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
{
struct sigevent defsigev;
struct requestlist *requests[ent];
============================================================================
Blow the stack by printing in fwide mode using a format string longer than
fits on the stack:
int
__fxprintf (FILE *fp, const char *fmt, ...)
{
if (fp == NULL)
fp = stderr;
va_list ap;
va_start (ap, fmt);
int res;
if (_IO_fwide (fp, 0) > 0)
{
size_t len = strlen (fmt) + 1;
wchar_t wfmt[len];