This is the mail archive of the glibc-bugs@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]

[Bug stdio/20632] New: Buffer overflow in wchar IO (_IO_wfile_overflow)


https://sourceware.org/bugzilla/show_bug.cgi?id=20632

            Bug ID: 20632
           Summary: Buffer overflow in wchar IO (_IO_wfile_overflow)
           Product: glibc
           Version: 2.23
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: stdio
          Assignee: unassigned at sourceware dot org
          Reporter: corydoras at ridiculousfish dot com
  Target Milestone: ---

Wide character IO will write past the end of an internal buffer in some cases.
In this case, it manifests as stomping the __malloc_hook function pointer.

Reproduced with glibc 2.23 on Linux x86-64 (Ubuntu MATE 16.04.1 LTS)

Reduced test case:

#include <stdio.h>
#include <wchar.h>
#include <unistd.h>
#include <stdlib.h>

int main(void) {
   /* Close stderr */
   close(2);

   /* Output long string */
   const int sz = 4096;
   wchar_t *buff = calloc(sz+1, sizeof *buff);
   for (int i=0; i < sz; i++) buff[i] = L'x';
   fputws(buff, stderr);

   /* Output shorter string */
   for (int i=0; i < 1024; i++) {
     fputws(L"0123456789ABCDEF", stderr);

     /* Call malloc, which should not crash.
        However it will if malloc's function pointers
        have been stomped. */
     free(malloc(1));
   }
   return 0;
}

compile and run as `gcc test.c; ./a.out`.

Results: this SIGSEGVs in the call to malloc, because the __malloc_hook
function pointer has been overwritten.

Analysis:

There's some discussion in
https://github.com/fish-shell/fish-shell/issues/3401#issuecomment-249394369

My diagnosis:

1. The initial large write calls into `_IO_wfile_overflow`. This has a bug that
results in a FILE* that has _IO_write_ptr exceeding _IO_write_end by exactly 1

2. This bug is typically masked by the call to _IO_do_flush(), however this
call doesn't successfully flush because stderr has been closed

3. The subsequent shorter writes call into `_IO_wfile_xsputn`. This calculates
the available space in the buffer as `_IO_write_end - _IO_write_ptr` (a
negative value) and stores the result in an unsigned value (i.e. huge). Since
it determines it has enough space, it writes arbitrarily much into
_IO_write_ptr

This seems quite exploitable to me: we end up overwriting a function pointer
that malloc invokes. If an attacker can invoke the process with stderr closed
(easy to do from a shell), and can control what text the process outputs to
stderr, the attacker can execute arbitrary code.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

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