crash handlers and PTRACE in Ubuntu 10.10

Jonathan Thomas echidnaman at gmail.com
Wed Jun 23 16:50:10 BST 2010


What I've been considering doing is to write a small Polkit helper that, right before Dr Konqi starts getting the backtrace, echos "0" to /proc/sys/kernel/ptrace_scope, setting it back as it finishes. The default policy would be to allow any user to run this action. This approach would limit time spent allowing all ptraces, since running GDB normally won't take more than a minute. Since its a Polkit action, sysadmins concerned about even this possibility could change the policy to be less permissive.

I do not know how well this approach would work for Chromium, however, since it does require a Polkit implementation as a dependency...


On Wed 23 Jun 2010 02:06:00 am Kees Cook wrote:
> Hi,
> 
> (Jonathan, Philip, I've added you to CC explicitly so we're all in the
> same thread here instead of splitting between here and the KDE bug.)
> 
> On Mon, Jun 21, 2010 at 08:14:46PM +0800, John McCabe-Dansted wrote:
> > On Mon, May 31, 2010 at 1:03 PM, Kees Cook <kees at ubuntu.com> wrote:
> > >  a) Using "strace -p PID" and gdb's "attach" command will NOT work
> > >    unless you are the root user (i.e. use "sudo strace -p PID ...")
> > >    Running stuff with "strace" and "gdb" directly will work normally.
> > ...
> > >  a) /proc/sys/kernel/ptrace_scope: "0" allows original ptrace behavior
> > ...
> > > I expect that the PTRACE changes will cause the greatest surprise.  Since
> > > PTRACE is rarely needed by normal users, this change makes sense for the
> > 
> > I imagine that this will break software that does something like
> > 
> > onAssert() {
> >    echo bt | gdb -q $0 getpid()
> >    Alert ("Please report this backtrace", "Continue?") || die
> > }
> > 
> > Am I correct, if so what preferred technique should we replace this with?
> > 
> > The best simple solution I can see is something like
> > 
> > if (child_pid=fork()) {
> >    //parent
> >    wait(child_pid,...);
> >    //process core file here
> > } else {
> >    abort();
> > }
> > 
> > However this doesn't seem as nice, we have to unblock core dumps using
> > ulimit, we have to actually have to have space for the core dumps.
> > Also we have to assume that the core file generated matches "core*"
> > which theoretically may not be the case. If this is the best we can do
> > it is probably still better than automatically setting setting system
> > wide security configurations such as  ``/proc/sys/kernel/ptrace_scope:
> > "0"'' in the installer.
> 
> So we have a problem here that we need to find a solution to.  Both KDE[1]
> in general, and Chromium[2] in particular have their own crash handlers
> that currently depend on being able to spawn a debugger against the
> crashing process (as a sibling or cousin of the crashing process).
> 
> I see at least a few ways to handle this:
> 
> 1) "pre-spawn"
>    Have applications reworked to pre-spawn a process that is the crash
>    handler.  This does not work for KDE, though, since it it spawns gdb
>    for a series of commands instead of doing its own PTRACE-based
>    manipulation.
> 
> 2) "manual sysctl"
>    Have anyone interested in native application crash handlers set
>    0 to /proc/sys/kernel/ptrace_scope manually.  This means that crashes
>    from non-developers are not reported.
> 
> 3) "packaged sysctl"
>    When KDE or Chromium are installed, ship a file in /etc/sysctl.d/
>    that sets 0 to /proc/sys/kernel/ptrace_scope.  This weakens the
>    system over all, and isn't much better than just changing the default
>    everywhere.
> 
> 4) "Apport hooks"
>    Recognize that the goal is to have _crash_ handlers.  There doesn't
>    appear to be a need to actually be running PTRACE on the crashed
>    process -- it's just a report of the state of the process and access
>    to its memory -- all possible through the coredump.  So, have
>    applications register a hook with Apport to handle coredumps since
>    Apport already has all the built-in logic to handle core dumps without
>    messing with ulimits, etc.  This becomes useless if Apport is not
>    running, and Apport does not run during the stable release.  (Though
>    maybe Apport could be improved to handle this more gracefully?)
> 
> 5) "declared PTRACEing"
>    Recognize that the PTRACEing we want to allow is in very specific
>    declared situations (i.e. the PID of the debugger is always known by
>    the debugee, so have the debugee "declare" that it wishes to be
>    debugged).  This interface does not exist.  It would require the
>    creation of something like:
>         ptrace(PTRACE_TRACEDBY, debugger_pid, NULL, NULL);
>    This would be, at least for now, an Ubuntu-specific extension.  For
>    KDE applications, this is a trivial change, since the KDE crash
>    handler stays in a while loop, calling sleep() until the debugger
>    process quits.  Chromium would likely need to pass the debugger pid
>    back through the segfault handler in the sandbox -- I got lost reading
>    the syscall emulation-through-seccomp, so maybe it's as easy as KDE's.
> 
> 6) "new kernel heuristic"
>    Find a different heuristic that could apply in these crash cases that
>    would not be vulnerable to the process-hijacking attacks that the
>    PTRACE restrictions are seeking to block.  This is tricky since the
>    crashed processes are usually blocked (but not dead) in their segv
>    handler, so the process isn't strictly _dead_, so I haven't been able
>    to think up ways that such a process is distinguishable from a normal
>    process by the kernel.
> 
> 7) "disable by default"
>    Leave the ability to restrict PTRACE, but leave it set to "0".  This
>    leaves Ubuntu users at large vulnerable to a class of process-hijacking
>    attacks that worms could use, except for those that want to set it to
>    "1", like can be done with the module-loading blocker[3].
> 
> 
> I prefer 4 (Apport hooks), as it would leverage existing code and actually
> eliminates PTRACE completely.  Option 5 (declared PTRACEing) is second,
> but puts Ubuntu is a weird spot with regard to the upstream kernel which
> hasn't been too happy about the idea of mucking with existing PTRACE
> interfaces.  Option 6 (new kernel heuristic) would be really great,
> but it doesn't current have an implementation and I worry it would be
> fragile.  I'd go for 3 ("packaged sysctl settings") before 7 ("disable
> by default"), though it seems poor since lots of system will end up in
> the more vulnerable state.  I don't think 1 ("pre-spawn") is workable,
> but I may just lack imagination (maybe some combination/variation of 1
> and 6 that worked out).  And 2 ("manual sysctl") doesn't really address
> the larger desire of upstreams wanting crash feedback.
> 
> Thoughts?
> 
> -Kees
> 
> [1] https://launchpad.net/bugs/589841
> [2] http://code.google.com/p/chromium/issues/detail?id=46368
> [3] http://www.outflux.net/blog/archives/2009/07/31/blocking-module-loading/
> 
> 
> 



More information about the ubuntu-devel mailing list