Date: Thu, 29 Apr 2010 23:36:40 +0000 From: Gunnar Hinriksson <tomtinn@gmail.com> To: freebsd-hackers@freebsd.org Subject: Re: Ptrace segfault Message-ID: <m2wcbb19c781004291636rd7d5709dr81563f4ce6f4bf25@mail.gmail.com> In-Reply-To: <v2mcbb19c781004291600p4ac8840bhcac182f8d62667ee@mail.gmail.com> References: <q2vcbb19c781004291206sc54fdb6ag53c3a763ad364e8e@mail.gmail.com> <p2i7d6fde3d1004291437y9b789015ybf8153b41e034d9f@mail.gmail.com> <9EF83DA6-B2D3-456E-B0AF-0B4F5F458A1F@gid.co.uk> <v2mcbb19c781004291600p4ac8840bhcac182f8d62667ee@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
2010/4/29 Gunnar Hinriksson <tomtinn@gmail.com>: > 2010/4/29 Bob Bishop <rb@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@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[]) >>>> { >>>> =A0 =A0 =A0 =A0int pid =3D atoi(argv[1]); >>>> =A0 =A0 =A0 =A0ptrace(PT_ATTACH, pid, 0, 0); >>>> =A0 =A0 =A0 =A0wait(NULL); >>>> =A0 =A0 =A0 =A0ptrace(PT_DETACH, pid, 0, 0); >>>> =A0 =A0 =A0 =A0return 0; >>>> } >>>> >>>> Am I using ptrace incorrectly or is there perhaps a bug in ptrace that >>>> causes the child to always segfault ? >>> >>> =A0 =A0Nope -- it's a bug in your code. From ptrace(2): >>> >>> =A0 =A0 PT_CONTINUE =A0 The traced process continues execution. =A0The = addr argument >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 is an address specifying the place = where execution is to be >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 resumed (a new value for the progra= m counter), or >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (caddr_t)1 to indicate that executi= on is to pick up where >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 it left off. =A0The data argument p= rovides a signal number to >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 be delivered to the traced process = as it resumes execution, >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 or 0 if no signal is to be sent. >>> >>> [...] >>> >>> =A0 =A0 PT_DETACH =A0 =A0 This request is like PT_CONTINUE, except that= it does not >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ^^^^^^^^^^^ >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 allow specifying an alternate place= to continue execution, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^= ^^^^^^^^^^^^^^^^^^^^^ >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 and after it succeeds, the traced p= rocess is no longer >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 traced and continues execution norm= ally. >>> >>> =A0 =A0Note 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 ptra= ce(2) ought either to >> (a) fail (EINVAL?) if addr !=3D (caddr_t)1, or >> (b) ignore addr entirely; it's not clear which. >> >> OP inferred (b) which is reasonable. >> >>> HTH, >>> -Garrett >>> _______________________________________________ >>> freebsd-hackers@freebsd.org mailing list >>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.o= rg" >>> >>> >> >> >> -- >> Bob Bishop =A0 =A0 =A0 =A0 =A0+44 (0)118 940 1243 >> rb@gid.co.uk =A0 =A0fax +44 (0)118 940 1295 >> =A0 =A0 =A0 =A0 =A0 =A0 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)) =3D=3D 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 !=3D (void *)1) { error =3D ptrace_set_pc(td2, (u_long)(uintfptr_t)ad= dr); 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m2wcbb19c781004291636rd7d5709dr81563f4ce6f4bf25>