Date: Thu, 29 Apr 2010 23:49:26 +0000 From: Gunnar Hinriksson <tomtinn@gmail.com> To: freebsd-hackers@freebsd.org Subject: Re: Ptrace segfault Message-ID: <w2lcbb19c781004291649p96fb1c68scef0bce53ea253b3@mail.gmail.com> In-Reply-To: <m2wcbb19c781004291636rd7d5709dr81563f4ce6f4bf25@mail.gmail.com> References: <q2vcbb19c781004291206sc54fdb6ag53c3a763ad364e8e@mail.gmail.com> <p2i7d6fde3d1004291437y9b789015ybf8153b41e034d9f@mail.gmail.com> <9EF83DA6-B2D3-456E-B0AF-0B4F5F458A1F@gid.co.uk> <v2mcbb19c781004291600p4ac8840bhcac182f8d62667ee@mail.gmail.com> <m2wcbb19c781004291636rd7d5709dr81563f4ce6f4bf25@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 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 tha= t >>>>> 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 progr= am counter), or >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (caddr_t)1 to indicate that execut= ion is to pick up where >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 it left off. =A0The data argument = provides 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 tha= t 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 plac= e 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 = process is no longer >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 traced and continues execution nor= mally. >>>> >>>> =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 ptr= ace(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.= org" >>>> >>>> >>> >>> >>> -- >>> 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) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0error =3D ptrace_set_pc(td= 2, (u_long)(uintfptr_t)addr); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (error) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > > 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 > After reading the code more carefully the correct way would be to modify it like this. --- case PT_CONTINUE: { if (addr !=3D (void *)1) { error =3D ptrace_set_pc(td2, (u_long)(uintfptr_t)ad= dr); } } if (error) break; --- Note that im just learning programming so this might not be the correct way to do it. With Regards Gunnar
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?w2lcbb19c781004291649p96fb1c68scef0bce53ea253b3>