Re: inconsistent behavior with ptrace(TRACEME) and fork/exec

From: Mike Frysinger
Date: Wed Oct 29 2008 - 06:27:16 EST


On Tue, Oct 28, 2008 at 10:58, Jan Kratochvil wrote:
> On Mon, 27 Oct 2008 18:38:16 +0100, Mike Frysinger wrote:
>> On Mon, Oct 27, 2008 at 10:56, Jan Kratochvil wrote:
>> > On Wed, 19 Jul 2006 21:18:29 +0200, Mike Frysinger wrote:
>> >> my understanding is that if a parent forks and the child does
>> >> a ptrace(TRACEME) right before doing an exec(), the kernel should always
>> >> halt it and wait indefinitely for the parent to start ptracing it.
>> >
>> > Yes, just the parent must process the event (signal). In your testcase the
>> > parent finished before the signal could be delivered. If the tracer exits the
>> > tracee's tracing is finished and it continues freely.
>>
>> no signal should have been generated. the child should have gone
>> straight to the exec and waited for the parent to process it.
>
> Every ptrace event generates SIGCHLD. vfork() frees the parent at the moment
> the child calls exec() or _exit(). Here the child calls exec() which both
> frees the parent to continue the execution AND delivers SIGCHLD with the
> status WIFSTOPPED WSTOPSIG(SIGTRAP) to it. I do not see a problem here.

sorry, the only info ive gathered about the ptrace interface is the
man page, strace, and some of the ptrace code in the kernel ... not
that strace/kernel is really documented at all. nowhere did i see
mention of the child generating a signal due to ptrace. but in this
case, it sounds like the initial SIGCHLD with stop info is implied
rather than explicitly mentioned. every time the child is halted at a
trace point (like syscall entry/exit or signal), the parent is
notified by a SIGCHLD with the stop bit set. and then it's up to the
parent to interrogate the child's signal info via like
PTRACE_GETSIGINFO.

>> >> unfortunately, this behavior seems to be unreliable.
>> >
>> > Fixed the races in your code and I do not see there any problem, do you?
>> > The ptrace problems/testsuite is being maintained at:
>> > http://sourceware.org/systemtap/wiki/utrace/tests
>>
>> there is no race condition ... it's using vfork here remember ?
>
> Yes but you said that you see the same problem even with fork():

true, so in that case you are right that there is a race condition.
but lets ignore that to keep things simple. in the vfork() case, it
is impossible for the parent to execute before the child executes
PTRACE_TRACEME. if we also ignore the signal() aspect by setting
SIGCHLD to SIG_IGN, then how can the child not get stopped properly ?

> You must not rely on the vfork() specifics as vfork() can be just fork():

i'm testing the Linux interface. how anyone else handles vfork()
doesnt matter here. the assumption is that the expected behavior is
respected: the parent is halted until the child calls _exit() or an
exec() function. this appears to be the case on every Linux port i
know of, and can be checked on my system by inserting a sleep() right
after the vfork() for the child. the parent never runs until the
child hits exec().

> I hope there is no problem with the kernel at this moment, the attached
> testcase works even with vfork() reliably.

your code goes through a lot of trouble to avoid issues. i'm pushing
the acceptable limits on purpose. then again, the acceptable limits
arent terribly well documented. you're saying that the child exec()
will first release the parent, and then start creating the child
image/etc... before the child is placed into a stopped state ? and
until that stopped state is reached, any attempt to ptrace() the child
is not allowed ? in other words, ptrace() only works on a stopped
child, not an actively running one.

that is why the parent can sometimes get:
FAIL:62: ptrace(PTRACE_PEEKUSER, 18762) = -1: No such process
FAIL:38: kernel should have halted me...
even though (1) the child has clearly enabled tracing on itself and
(2) the pid clearly exists ?

which means if a child does something like mask all signals and then execute:
while (1) ;
a process tracing it will not be able to ptrace() it at all anymore ?

thanks for that utrace URL ... some good info there. i'm guessing
that there is no real ptrace() documentation (like a spec) and it's
largely an orphaned interface nowadays.
-mike
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/