您的位置:首页 > 其它

Process Tracing Using Ptrace

2007-05-12 12:41 399 查看




















"LinuxGazette...makingLinuxjustalittlemorefun!"

ProcessTracingUsingPtrace

BySandeepS

Theptracesystemcalliscrucialtotheworkingofdebuggerprogramslikegdb-yetitsbehaviourisnotverywelldocumented-unlessyoubelievethatthebestdocumentationiskernelsourceitself!Ishallattempttodemonstratehowptracecanbeusedtoimplementsomeofthefunctionalityavailableintoolslikegdb.

1.Introduction

ptrace()isasystemcallthatenablesoneprocesstocontroltheexecutionofanother.Italsoenablesaprocesstochangethecoreimageofanotherprocess.Thetracedprocessbehavesnormallyuntilasignaliscaught.Whenthatoccurstheprocessentersstoppedstateandinformsthetracingprocessbyawait()call.Thentracingprocessdecideshowthetracedprocessshouldrespond.TheonlyexceptionisSIGKILLwhichsurelykillstheprocess.
Thetracedprocessmayalsoenterthestoppedstateinresponsetosomespecificeventsduringitscourseofexecution.Thishappensonlyifthetracingprocesshassetanyeventflagsinthecontextofthetracedprocess.Thetracingprocesscanevenkillthetracedonebysettingtheexitcodeofthetracedprocess.Aftertracing,thetracerprocessmaykillthetracedoneorleavetocontinuewithitsexecution.

Note:Ptrace()ishighlydependentonthearchitectureoftheunderlyinghardware.Applicationsusingptracearenoteasilyportableacrossdifferentarchitecturesandimplementations.

2.MoreDetails

Theprototypeofptrace()isasfollows.

#include<sys/ptrace.h>
longintptrace(enum__ptrace_requestrequest,pid_tpid,
void*addr,void*data)


Ofthefourarguments,thevalueofrequestdecideswhattobedone.PidistheIDoftheprocesstobetraced.Addristheoffsetintheuserspaceofthetracedprocesstowherethedataiswrittenwheninstructedtodoso.Itistheoffsetinuserspaceofthetracedprocessfromwhereawordisreadandreturnedastheresultofthecall.

TheparentcanforkachildprocessandtraceitbycallingptracewithrequestasPTRACE_TRACEME.ParentcanalsotraceanexistingprocessusingPTRACE_ATTACH.Thedifferentvaluesofrequestarediscussedbelow.

2.1Howdoesptrace()work.

Wheneverptraceiscalled,whatitfirstdoesistolockthekernel.Justbeforereturningitunlocksthekernel.Let'sseeitsworkinginbetweenthisfordifferentvaluesofrequest.

PTRACE_TRACEME:

Thisiscalledwhenthechildistobetracedbytheparent.Assaidabove,anysignals(exceptSIGKILL),eitherdeliveredfromoutsideorfromtheexeccallsmadebytheprocess,causesittostopandletstheparentdecidehowtoproceed.Insideptrace(),theonlythingthatischeckediswhethertheptraceflagofthecurrentprocessisset.Ifnot,permissionisgrantedandtheflagisset.Alltheparametersotherthanrequestareignored.

PTRACE_ATTACH:

Hereaprocesswantstocontrolanother.Onethingtorememberisthatnobodyisallowedtotrace/controltheinitprocess.Aprocessisnotallowedtocontrolitself.Thecurrentprocess(caller)becomestheparentoftheprocesswithprocessIDpid.Butagetpid()bythechild(theonebeingtraced)returnstheprocessIDoftherealparent.

Whatgoesbehindthescenesisthatwhenacallismade,theusualpermissionchecksaremadealongwithwhethertheprocessisinitorcurrentoritisalreadytraced.Ifthereisnoproblem,permissionisgivenandtheflagisset.Nowthelinksofthechildprocessarerearranged;e.g.,thechildisremovedfromthetaskqueueanditsparentprocessfieldischanged(theoriginalparentremainsthesame).Itisputtothequeueagaininsuchapositionthatinitcomesnexttoit.FinallyaSIGSTOPsignalisdeliveredtoit.Hereaddranddataareignored.

PTRACE_DETACH:

Stoptracingaprocess.Thetracermaydecidewhetherthechildshouldcontinuetolive.ThisundoesalltheeffectsmadebyPTRACE_ATTACH/PTRACE_TRACEME.Theparentsendstheexitcodeforthechildindata.Ptraceflagofthechildisreset.Thenthechildismovedtoitsoriginalpositioninthetaskqueue.Thepidofrealparentiswrittentotheparentfield.Thesingle-stepbitwhichmighthavebeensetisreset.Finallythechildiswokenupasnothinghadhappenedtoit;addrisignored.

PTRACE_PEEKTEXT,PTRACE_PEEKDATA,PTRACE_PEEKUSER:

Theseoptionsreaddatafromchild'smemoryanduserspace.PTRACE_PEEKTEXTandPTRACE_PEEKDATAreaddatafrommemoryandboththeseoptionshavethesameeffect.PTRACE_PEEKUSERreadsfromtheuserspaceofchild.Awordisreadandplacedintoatemporarydatastructure,andwiththehelpofput_user()(whichcopiesastringfromthekernel'smemorysegmenttotheprocess'memorysegment)therequireddataiswrittentodataandreturns0onsuccess.

InthecaseofPTRACE_PEEKTEXT/PTRACE_PEEKDATA,addristheaddressofthelocationtobereadfromchild'smemory.InPTRACE_PEEKUSERaddristheoffsetofthewordinchild'suserspace;dataisignored.

PTRACE_POKETEXT,PTRACE_POKEDATA,PTRACE_POKEUSER:

Theseoptionsareanalogoustothethreeexplainedabove.Thedifferenceisthattheseareusedtowritethedatatothememory/userspaceoftheprocessbeingtraced.InPTRACE_POKETEXTandPTRACE_POKEDATAawordfromlocationdataiscopiedtothechild'smemorylocationaddr.

InPTRACE_POKEUSERwearetryingtomodifysomelocationsinthe
task_struct
oftheprocess.Astheintegrityofthekernelhastobemaintained,weneedtobeverycareful.Afteralotofsecuritychecksmadebyptrace,onlycertainportionsofthetask_structisallowedtochange.Hereaddristheoffsetinchild'suserarea.

PTRACE_SYSCALL,PTRACE_CONT:

Boththesewakesupthestoppedprocess.PTRACE_SYSCALLmakesthechildtostopafterthenextsystemcall.PTRACE_CONTjustallowsthechildtocontinue.Inboth,theexitcodeofthechildprocessissetbytheptrace()wheretheexitcodeiscontainedindata.Allthishappensonlyifthesignal/exitcodeisavalidone.Ptrace()resetsthesinglestepbitofthechild,sets/resetsthesyscalltracebit,andwakesuptheprocess;addrisignored.

PTRACE_SINGLESTEP;

DoesthesameasPTRACE_SYSCALLexceptthatthechildisstoppedaftereveryinstruction.Thesinglestepbitofthechildisset.Asabovedatacontainstheexitcodeforthechild;addrisignored.

PTRACE_KILL:

Whenthechildistobeterminated,PTRACE_KILLmaybeused.Howthemurderoccursisasfollows.Ptrace()checkswhetherthechildisalreadydeadornot.Ifalive,theexitcodeofthechildissettosigkill.Thesinglestepbitofthechildisreset.Nowthechildiswokenupandwhenitstartstoworkitgetskilledaspertheexitcode.

2.2Moremachine-dependentcalls

Thevaluesofrequestdiscussedabovewereindependentonthearchitectureandimplementationofthesystem.Thevaluesdiscussedbelowarethosethatallowthetracingprocesstoget/set(i.e.,toread/write)theregistersofchildprocess.Theseregisterfetching/settingoptionsaremoredirectlydependentonthearchitectureofthesystem.Thesetofregistersincludegeneralpurposeregisters,floatingpointregistersandextendedfloatingpointregisters.Thesemoremachine-dependentoptionsarediscussedbelow.Whentheseoptionsaregiven,adirectinteractionbetweentheregisters/segmentsofthesystemisrequired.

PTRACE_GETREGS,PTRACE_GETFPREGS,PTRACE_GETFPXREGS:

Thesevaluesgivethevalueofgeneralpurpose,floatingpoint,extendedfloatingpointregistersofthechildprocess.Theregistersarereadtothelocationdataintheparent.Theusualchecksforaccessontheregistersaremade.Thentheregistervaluesarecopiedtothelocationspecifiedbydatawiththehelpofgetreg()and__put_user()functions;addrisignored.

PTRACE_SETREGS,PTRACE_SETFPREGS,PTRACE_SETFPXREGS:

Thesearevaluesofrequestthatallowthetracingprocesstosetthegeneralpurpose,floatingpoint,extendedfloatingpointregistersofthechildrespectively.Therearesomerestrictionsinthecaseofsettingtheregisters.Somearenotallowedtobechanged.Thedatatobecopiedtotheregisterswillbetakenfromthelocationdataoftheparent.Herealsoaddrisignored.

2.3Returnvaluesofptrace()

Asuccessfulptrace()returnszero.Errorsmakeitreturn-1andseterrno.SincethereturnvalueofasuccessfulPEEKDATA/PEEKTEXTmaybe-1,itisbettertochecktheerrno.Theerrorsare

EPERM:Therequestedprocesscouldn'tbetraced.Permissiondenied.

ESRCH:Therequestedprocessdoesn'texistorisbeingtraced.

EIO:Therequestwasinvalidorread/writewasmadefrom/toinvalidareaofmemory.

EFAULT:Read/writewasmadefrom/tomemorywhichwasnotreallymapped.

ItisreallyhardtodistinguishbetweenthereasonsofEIOandEFAULT.Thesearereturnedforalmostidenticalerrors.

3.Asmallexample.

Ifyoufoundtheparameterdescriptiontobeabitdry,don'tdespair.Ishallnotattemptanythingofthatsortagain.Iwilltrytowritesimpleprogramswhichillustratemanyofthepointsdiscussedabove.

Hereisthefirstone.Theparentprocesscountsthenumberofinstructionsexecutedbythetestprogramrunbythechild.
Herethetestprogramislistingtheentriesofthecurrentdirectory.


#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<syscall.h>
#include<sys/ptrace.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>

intmain(void)
{
longlongcounter=0;/*machineinstructioncounter*/
intwait_val;/*child'sreturnvalue*/
intpid;/*child'sprocessid*/

puts("Pleasewait");

switch(pid=fork()){
case-1:
perror("fork");
break;
case0:/*childprocessstarts*/
ptrace(PTRACE_TRACEME,0,0,0);
/*
*mustbecalledinordertoallowthe
*controloverthechildprocess
*/
execl("/bin/ls","ls",NULL);
/*
*executestheprogramandcauses
*thechildtostopandsendasignal
*totheparent,theparentcannow
*switchtoPTRACE_SINGLESTEP
*/
break;
/*childprocessends*/
default:/*parentprocessstarts*/
wait(&wait_val);
/*
*parentwaitsforchildtostopatnext
*instruction(execl())
*/
while(wait_val==1407){
counter++;
if(ptrace(PTRACE_SINGLESTEP,pid,0,0)!=0)
perror("ptrace");
/*
*switchtosinglesteptracingand
*releasechild
*ifunablecallerror.
*/
wait(&wait_val);
/*waitfornextinstructiontocomplete*/
}
/*
*continuetostop,waitandreleaseuntil
*thechildisfinished;wait_val!=1407
*Low=0177LandHigh=05(SIGTRAP)
*/
}
printf("Numberofmachineinstructions:%lld/n",counter);
return0;
}


openyourfavouriteeditorandwritetheprogram.Thenrunitbytyping
ccfile.c

a.out

Youcanseethenumberofinstructionsneededforlistingofyourcurrentdirectory.
cd
tosomeotherdirectoryandruntheprogramfromthereandseewhetherthereisanydifference.(notethatitmaytakesometimefortheoutputtoappear,ifyouareusingaslowmachine).

4.Conclusion

Ptrace()isheavilyusedfordebugging.Itisalsousedforsystemcalltracing.Thedebuggerforksandthechildprocesscreatedistracedbytheparent.Theprogramwhichistobedebuggedisexec'dbythechild(intheaboveprogramitwas"ls")andaftereachinstructiontheparentcanexaminetheregistervaluesoftheprogrambeingrun.Ishalldemonstrateprogramswhichexploitptrace'sversatilityinthenextpartofthisseries.Goodbyetillthen.



SandeepS

IamafinalyearstudentofGovernmentEngineeringCollegeinThrissur,Kerala,India.MyareasofinterestsincludeFreeBSD,NetworkingandalsoTheoreticalComputerScience.

Copyright©2002,SandeepS.
Copyinglicensehttp://www.linuxgazette.net/copying.html
PublishedinIssue81ofLinuxGazette,August2002
















内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: