Subject: Re: ptrace() vs. SIGKILL?
To: NetBSD Security Technical Discussion List <tech-security@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: tech-kern
Date: 12/07/2002 15:41:05
[ On Friday, December 6, 2002 at 23:05:32 (+0100), der Mouse wrote: ]
> Subject: Re: ptrace() vs. SIGKILL?
>
> >> Heh, I was pondering this the other day after the realisation that
> >> ptrace() could prevent SIGKILL from killing a process.
> 
> > Hmmm....  If ptrace() could prevent SIGKILL from taking effect for
> > anyone but the superuser then that would be a very serious security
> > bug, not just on un-hardened boxes.
> 
> Greg, meet Reality.
> 
> I've never seen a system with ptrace that _didn't_ work this way.  (Not
> that I've looked very hard.)

I'm talking about something a little different than what I think you're
referring to.  I think you're referring to the fact that a ptrace'd
process will stop and signal the tracer when it receives SIGKILL.

However I mean very literally "if ptrace() can _prevent_ SIGKILL from
ultimately taking effect" then it's a security bug waiting to happen.

I.e. if there's any way using ptrace() to actually restart a process
executing from its text segment (or any other executable part of the
process image) that's been sent a SIGKILL, then that's a VERY serious
security problem.

The process _must_only_ continue inside the kernel in _exit(2).

I.e. SIGKILL _must_ eventually cause the unconditional termination of a
process regardless of whether it is being traced or not.

I don't have any problem with ptrace() catching the process as it dies
and allowing a debugger or similar tool to record the state of the
process just before the signal is delivered, but the signal must
eventually be delivered and the process must ultimately exit.

I.e. PT_CONTINUE must not allow a new program counter value to be given
if the reason the process stopped was an imminent SIGKILL -- or rather I
guess it must ignore 'addr' and simply allow the process to continue in
_exit(2) where it will finally die.

I notice on reading the ptrace(2) manual that there may be another case
where ptrace() might be used by an attacker to DoS the system too, such
as with a fork-bomb-like process that uses PT_TRACE_ME in say half it's
children, but without the parent ever using PT_ATTACH.  Any initial
attempt to clean up such a mess will leave a bunch of not-quite-zombie
processes waiting for a PT_CONTINUE or PT_KILL.  The manual warns that
such child processes cannot be made to continue without using ptrace(),
which if true would make it much harder to clean up after such an attack.

However if it works as it must for a really secure implementation then a
second SIGKILL should have the same effect as PT_KILL.

This idea of having to send two signals to a process to kill it does
raise the hair on the back of my neck a bit, especially when SIGKILL is
involved, but I guess except when the first signal was a SIGKILL it
doesn't really change the behaviour of the system much since the first
signal could have been caught and normally 'init' and other programs
that try hard to kill processes will send a SIGTERM and then a SIGKILL
anyway in case the SIGTERM was caught.

Before I look at the code can anyone confirm whether or not PT_CONTINUE
with an addr > 1 works on a SIGKILL'ed process and whetehr or not a
second SIGKILL to a process waiting for ptrace() will simulate PT_KILL?

-- 
								Greg A. Woods

+1 416 218-0098;            <g.a.woods@ieee.org>;           <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>