This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug stdio/20632] New: Buffer overflow in wchar IO (_IO_wfile_overflow)
- From: "corydoras at ridiculousfish dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Sun, 25 Sep 2016 01:42:55 +0000
- Subject: [Bug stdio/20632] New: Buffer overflow in wchar IO (_IO_wfile_overflow)
- Auto-submitted: auto-generated
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.