Denys,
I have released an updated version of the CERT Triage Tools that includes the workaround
described in the previous message along with new test cases that clear up some licensing
issues that were preventing the Tools from being packaged with Fedora. It can be found
here:
http://www.cert.org/download/triage/
Outside of this release, I have also done some preliminary investigation into adding
proper support for core files to the tools. I was able to work around the si_addr issue
(with degraded performance, as discussed below), but I ran into another issue. I am
unaware of a GDB interface that allows the tool to access the full process address space
mapping info (along the lines of "info proc map" in a live session). The tool
can call "maint info sections," which I believe I can use to determine what
addresses and mapped and perhaps their permissions, but the original mapped shared object
names are absent. I plan to do further investigation here.
If the shared object names are not available, again, it may be possible to work around
this lack of info and degrade the performance of the tool further, but I wanted to ask --
would it be plausible to integrate the CERT Triage Tools with ABRT in a manner where the
'exploitable' plugin could run in a GDB session with a live target? Adding proper
support for core files to the CERT Triage Tools is still possible, but it seems like ABRT
might get more mileage from the 'exploitable' plugin if it can operate on a live
target.
Thanks,
Jon
-----Original Message-----
From: Jonathan M. Foote
Sent: Friday, May 25, 2012 11:40 AM
To: 'Denys Vlasenko'; Jan Kratochvil; Jan Kratochvil
Cc: crash-catcher(a)lists.fedorahosted.org; Steve Grubb (sgrubb(a)redhat.com); cert(a)cert.org;
Josh Bressers
Subject: RE: CERT Triage Tools 1.0 (INFO#208126) (re-send)
Denys, Jan,
I prematurely posted a related question to the gdb(a)sourceware.org mailing before I saw
your response, and Pedro Alves replied with a similar analysis:
'''
I don't think the whole siginfo object is stored on core files.
See /usr/include/linux/elfcore.h . The elf_prstatus and elf_prpsinfo
structures is what is put in the core. We can retrieve some info, but
unfortunately, it doesn't look like si_addr is anywhere to be found.
'''
The reason exploitable was failing awkwardly when running on a core file is due to a
nuance (a bug, perhaps) in the GDB Python API: the only reliable way I've found to
cause GDB to raise a Python Exception when $_siginfo is not available is to call __str__
on the gdb.Value returned from the errant gdb.parse_and_eval call. Doing anything else,
such as casting the gdb.Value to another type, may cause GDB to abruptly print an error
message ("Unalbe to read siginfo") and exit, without obeying Python Exception
conventions. Here an example:
[exploitable-test@dog ~]$ gdb --core=testStackBufferOverflow.test.core
GNU gdb (GDB) Fedora (7.3.50.20110722-13.fc16) Copyright (C) 2011 Free Software
Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<
http://www.gnu.org/software/gdb/bugs/>.
Missing separate debuginfo for the main executable file
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install
/usr/lib/debug/.build-id/96/925d2eb70246cc2f4e31db5a36fe54567ec49e
[New LWP 45186]
Core was generated by
`/home/exploitable-test/exploitable/exploitable/tests/bin/testStackBufferOverflow'.
Program terminated with signal 11, Segmentation fault.
#0 0x000000000040050c in ?? ()
(gdb) python
try:
print bool(gdb.parse_and_eval("$_siginfo.si_signo"))
print "bool(..) returned"
except Exception as e:
print "Exception handled. %s %s" % (type(e), e)
print "done" <--- (CTRL+D pressed)
Unable to read siginfo <--- GDB Python exits abruptly
(gdb)
python
try:
print gdb.parse_and_eval("$_siginfo.si_signo").__str__()
print "...__str__() returned"
except Exception as e:
print "Exception handled. %s %s" % (type(e), e)
print "done"
<--- (CTRL+D pressed)
Exception handled. <class 'gdb.error'> Unable to read siginfo <--- GDB
Python raises an Exception, gracefully
So, I came up with a workaround to facilitate graceful degradation. Here is an example:
@memoized
def si_addr(self):
str(gdb.parse_and_eval("$_siginfo._sifields._sigfault.si_addr")) #
<--- will raise an exception if $_siginfo is not available
return gdb.parse_and_eval("$_siginfo._sifields._sigfault.si_addr")
It's not pretty, but it works.
All that being said, I should be able to branch on "info target" to pro-actively
determine if the target is a core file, then write a parser for "target core
<corefile>" to grab the si_signo and proceed without si_addr. While the plugin
will still be useful, not including si_addr will degrade it's performance
significantly: roughly 5 of the 21 tags in rules.py rely on si_addr, and 4 of the 9
"EXPLOITABLE" (i.e. most interesting) tags rely on it.
I look forward to hearing from you and Jan. In the meantime I plan to code and test
workarounds as time permits.
Jon
-----Original Message-----
From: Denys Vlasenko [mailto:dvlasenk@redhat.com]
Sent: Friday, May 25, 2012 5:29 AM
To: Jonathan M. Foote; Jan Kratochvil; Jan Kratochvil
Cc: crash-catcher(a)lists.fedorahosted.org; Steve Grubb (sgrubb(a)redhat.com); cert(a)cert.org;
Josh Bressers
Subject: Re: CERT Triage Tools 1.0 (INFO#208126) (re-send)
Hi Jonatan, Jan,
On 05/24/2012 07:55 PM, Jonathan M. Foote wrote:
IIRC copying a python script into /usr/share/gdb/python and using the
'import' command did not work properly on all versions of GDB 7.2+ that I tried it
on -- I'm glad to see it works in 7.3 on Fedora.
I have not tried using the extension with a core dump-- in our fuzz testing campaigns we
run it on a live process just after it crashes. However, I believe your analysis is
correct. $_siginfo is used in many of the heuristics that the plugin applies to the
crashed application. As it is implemented, if $_siginfo is not available in the coredump
you are testing on, the plugin will not function correctly. That being said, I would like
the plugin to work on core dumps if possible. Do you happen to know if your coredumps
include siginfo, and if so, how it can be accessed via GDB? Regardless, you have found a
bug here -- the "exploitable" extension is essentially failing silently and
should give the user a more explicit failure message when $_siginfo is not available. I
plan to address this.
Please let me know about accessing siginfo in your coredumps if you get a chance.
I confirm that $_siginfo can't be read from coredump:
(gdb) core-file core.2466
Missing separate debuginfo for the main executable file
Try: yum --disablerepo='*' --enablerepo='*-debuginfo' install
/usr/lib/debug/.build-id/1a/2a693f2bd59ac5e2d18b77bd1e84415cba0b43
[New LWP 2466]
Core was generated by `md5sum'.
Program terminated with signal 6, Aborted.
#0 0x0804b756 in ?? ()
(gdb) print $_siginfo.si_signo
Unable to read siginfo
(gdb) print $_siginfo._sifields._sigfault.si_addr
Unable to read siginfo
Your gdb_wrapper.py code wants to know two values:
$_siginfo.si_signo
$_siginfo._sifields._sigfault.si_addr
First one, the signal number, is present in coredump, here:
$ readelf -aW core.2466
...
Notes at offset 0x00000274 with length 0x00000814:
Owner Data size Description
CORE 0x00000090 NT_PRSTATUS (prstatus structure)
^^^^^^^^^^^^^^^^^^^^^
CORE 0x0000007c NT_PRPSINFO (prpsinfo structure)
CORE 0x000000a0 NT_AUXV (auxiliary vector)
CORE 0x0000006c NT_FPREGSET (floating point registers)
LINUX 0x00000200 NT_PRXFPREG (user_xfpregs structure)
LINUX 0x00000340 NT_X86_XSTATE (x86 XSAVE extended state)
LINUX 0x00000030 Unknown note type: (0x00000200)
NT_PRSTATUS is:
struct elf_siginfo
{
int si_signo; /* Signal number. */
int si_code; /* Extra code. */
int si_errno; /* Errno. */
};
struct elf_prstatus
{
struct elf_siginfo pr_info; /* Info associated with signal. */
short int pr_cursig; /* Current signal. */
unsigned long int pr_sigpend; /* Set of pending signals. */
unsigned long int pr_sighold; /* Set of held signals. */
__pid_t pr_pid;
__pid_t pr_ppid;
__pid_t pr_pgrp;
__pid_t pr_sid;
struct timeval pr_utime; /* User time. */
struct timeval pr_stime; /* System time. */
struct timeval pr_cutime; /* Cumulative user time. */
struct timeval pr_cstime; /* Cumulative system time. */
elf_gregset_t pr_reg; /* GP registers. */
int pr_fpvalid; /* True if math copro being used. */
};
Therefore, we probably can teach gdb to provide it on coredumps.
However, second value, $_siginfo._sifields._sigfault.si_addr,
is not available anywhere in coredump, as far as I can see.
Jan, what do you know about this?
How big this problem is for you, Jonathan?
--
vda