From: | Aleksander Alekseev <a(dot)alekseev(at)postgrespro(dot)ru> |
---|---|
To: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | PROPOSAL: make PostgreSQL sanitizers-friendly (and prevent information disclosure) |
Date: | 2016-03-21 10:08:50 |
Message-ID: | 20160321130850.6ed6f598@fujitsu |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hello
I was playing with CLang sanitizers[1][2][3][4] recently and discovered
something disturbing regarding how PostgreSQL works. Here is an example.
Lets create a breakpoint right before filling a CheckPoint structure:
(gdb) b xlog.c:4772
Breakpoint 1 at 0x7ffbad0556d4: file xlog.c, line 4772.
(gdb) c
Continuing.
Fill checkpoint with some random data:
(gdb) p memset(&checkPoint, 0xEA, sizeof(checkPoint))
$1 = 1110817376
(gdb) x/80xb &checkPoint
0x7ffc4235ba60: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba68: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba70: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba78: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba80: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba88: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba90: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235ba98: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235baa0: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
0x7ffc4235baa8: 0xea 0xea 0xea 0xea 0xea 0xea 0xea 0xea
Wait until checkPoint will be initialized:
4805 checkPoint.redo = XLogSegSize + SizeOfXLogLongPHD;
(gdb)
4806 checkPoint.ThisTimeLineID = ThisTimeLineID;
(gdb)
4807 checkPoint.PrevTimeLineID = ThisTimeLineID;
(gdb)
...
Lets see what's in memory:
(gdb) x/80xb &checkPoint
0x7ffc4235ba60: 0x28 0x00 0x00 0x01 0x00 0x00 0x00 0x00
0x7ffc4235ba68: 0x01 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x7ffc4235ba70: 0x01 0xea 0xea 0xea 0x00 0x00 0x00 0x00
0x7ffc4235ba78: 0x03 0x00 0x00 0x00 0x10 0x27 0x00 0x00
0x7ffc4235ba80: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffc4235ba88: 0x03 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x7ffc4235ba90: 0x01 0x00 0x00 0x00 0x01 0x00 0x00 0x00
0x7ffc4235ba98: 0x3d 0x0a 0xec 0x56 0x00 0x00 0x00 0x00
0x7ffc4235baa0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffc4235baa8: 0x00 0x00 0x00 0x00 0xea 0xea 0xea 0xea
As you may see there are "holes" that were in fact not filled. Under
normal conditions they will be filled with data previously stored on
stack which could be anything including passwords and other private
data. Afterwards this structure is written to disk where potentially
someone who not supposed to see this data may see it.
I realize this is not a big problem in practice. But from security
nerd's point o few this is a pretty severe security issue. I think we
should fix this and all other cases where MemorySanitizer reports
"use-of-uninitialized-value" error.
Also I suggest we make PostgreSQL pass _all_ sanitizers checks. They
are able to find quite nasty bugs including but not limited to memory
leaks, array out of bound accesses, data races, etc. Imagine we could
find all these bugs during regression tests run on buildfarms.
What do you think?
[1] http://clang.llvm.org/docs/MemorySanitizer.html
[2] http://clang.llvm.org/docs/AddressSanitizer.html
[3] http://clang.llvm.org/docs/LeakSanitizer.html
[4] http://clang.llvm.org/docs/ThreadSanitizer.html
--
Best regards,
Aleksander Alekseev
http://eax.me/
From | Date | Subject | |
---|---|---|---|
Next Message | Andres Freund | 2016-03-21 10:10:57 | Re: Performance degradation in commit ac1d794 |
Previous Message | Tomas Vondra | 2016-03-21 10:08:32 | Re: multivariate statistics v14 |