Ptrace segfault

Gunnar Hinriksson tomtinn at gmail.com
Thu Apr 29 23:36:48 UTC 2010


2010/4/29 Gunnar Hinriksson <tomtinn at gmail.com>:
> 2010/4/29 Bob Bishop <rb at gid.co.uk>:
>> Hi,
>>
>> On 29 Apr 2010, at 22:37, Garrett Cooper wrote:
>>
>>> On Thu, Apr 29, 2010 at 12:06 PM, Gunnar Hinriksson <tomtinn at gmail.com> wrote:
>>>> Hello
>>>>
>>>> Im having a little problem using ptrace on my system.
>>>> If I use ptrace to attach to another process the child process
>>>> segfaults once I detach.
>>>> For example using this simple program.
>>>>
>>>> #include <stdio.h>
>>>> #include <stdlib.h>
>>>> #include <sys/types.h>
>>>> #include <sys/ptrace.h>
>>>> #include <sys/wait.h>
>>>>
>>>> int main(int argc, char *argv[])
>>>> {
>>>>        int pid = atoi(argv[1]);
>>>>        ptrace(PT_ATTACH, pid, 0, 0);
>>>>        wait(NULL);
>>>>        ptrace(PT_DETACH, pid, 0, 0);
>>>>        return 0;
>>>> }
>>>>
>>>> Am I using ptrace incorrectly or is there perhaps a bug in ptrace that
>>>> causes the child to always segfault ?
>>>
>>>    Nope -- it's a bug in your code. From ptrace(2):
>>>
>>>     PT_CONTINUE   The traced process continues execution.  The addr argument
>>>                   is an address specifying the place where execution is to be
>>>                   resumed (a new value for the program counter), or
>>>                   (caddr_t)1 to indicate that execution is to pick up where
>>>                   it left off.  The data argument provides a signal number to
>>>                   be delivered to the traced process as it resumes execution,
>>>                   or 0 if no signal is to be sent.
>>>
>>> [...]
>>>
>>>     PT_DETACH     This request is like PT_CONTINUE, except that it does not
>>                                                                 ^^^^^^^^^^^
>>>                   allow specifying an alternate place to continue execution,
>>                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>                   and after it succeeds, the traced process is no longer
>>>                   traced and continues execution normally.
>>>
>>>    Note very carefully the fact that PT_DETACH is like PT_CONTINUE,
>>> and that PT_CONTINUE says that addr references the memory where the
>>> execution is going to be resumed.
>>
>> Looks to me like a bug in ptrace(PT_DETACH,...) which to agree with ptrace(2) ought either to
>> (a) fail (EINVAL?) if addr != (caddr_t)1, or
>> (b) ignore addr entirely; it's not clear which.
>>
>> OP inferred (b) which is reasonable.
>>
>>> HTH,
>>> -Garrett
>>> _______________________________________________
>>> freebsd-hackers at freebsd.org mailing list
>>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"
>>>
>>>
>>
>>
>> --
>> Bob Bishop          +44 (0)118 940 1243
>> rb at gid.co.uk    fax +44 (0)118 940 1295
>>             mobile +44 (0)783 626 4518
>>
>>
>>
>>
>>
>>
>
> Hello
>
> I didn't want to make the code to big so I omitted any tests.
> About wait(), you are supposed to use wait to check if the child
> process has stopped successfully.
> I guess the correct usage would be something like this if im
> understanding the documentation correctly.
> if ( wait(WIFSTOPPED(SIGSTOP)) == pid )
> Im not sure if there is any posix way of describing how ptrace should
> be implemented but I know linux ptrace ignores the addr on DETACH.
> So my vote would be that ptrace ignores addr on detach to make it
> compatible with code for linux.
>
> With Regards
>
> Gunnar
>

Hello

I started looking around in the kernel sources and I think i've found
out how it is implemented.
in /usr/src/sys/kern/sys_process.c line 744 the following code is found.

if (addr != (void *)1) {
                        error = ptrace_set_pc(td2, (u_long)(uintfptr_t)addr);
                        if (error)
                                break;
                }

So it is changing the address if the addr is anything but 1.
I tested my program by passing 1 as an argument in the addr field and
the segfaults stopped.

So the question is if this code should be removed so that PT_DETACH
ignores addr or leave it be and perhaps update the documentation to
reflect that it allows the addr to the changed.

With Regards

Gunnar


More information about the freebsd-hackers mailing list