This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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];


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]