




已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Ptrace 的源码分析 前言我们组选择了系统调用拦截这个题目,本想参考strace来做一个类似的系统调用的拦截程序。但是后来发现我们发言前已经有同学介绍过系统调用ptrace的使用和相应的DEMO程序了,为了和他们的工作区别开来,我们的重点放在了研究ptrace的内核实现上。在这里我们主要描述ptrace的概述、标记跟踪、被跟踪进程与跟踪进程间切换和ptrace调试四大部分。虽然我们自己写了DEMO程序,也简略分析了strace,但是为了能够突出重点更详细的说明ptrace的结构,我们都将这些省去了。下面是我们的报告,请李老师批阅。 Ptrace内核实现 Ptrace概述Ptrace在Unix的早起版本里面就已经存在了,主要是用来对特定进程进行跟踪和调试的一个系统调用。在ptrace的使用中,我们将相关的进程分为被跟踪的进程和跟踪进程两种。通过ptrace系统调用,跟踪进程可以跟踪被跟踪进程的系统调用行为,并且还可以更改被跟踪进程的寄存器、内存和特定的调式寄存器(i386架构中只能改第七号调试寄存器)。此外,ptrace还提供的单步调试的功能,它的软中断比硬件提供的单步调试功能更加精确。使用这个系统调用,程序员可以很方便的调试自己的程序。据我们所知,现有的strace和gdb都在一定程度上依赖于ptrace系统调用。Ptrace这个系统调用对于程序调试有及其重要的作用,因此ptrace具有较大的研究意义。2.1.2 ptrace系统调用的格式Ptrace的原型如图1所示,有四个参数,第一个参数request决定了ptrace的行为。后面三个参数要根据第一个参数的取值才有特定的含义。其中,第二个参数指定了对象进程的进程号,addr和data分别是内存地址和传入的数据。Figure 12.1.3 ptrace的request参数Ptrace的request参数决定了ptrace系统调用的行为,它在内核源码的include/linux/ptrace.h和include/asm-i386/ptrace.h中定义。图二、三和图四在include/linux/ptrace.h中定义,图五在include/asm-i386/ptrace.h。图二罗列了ptrace中与硬件架构无关的几个参数:PTRACE_ME: 由被跟踪进程调用,调用该系统调用的进程把自己标记为被父进程跟踪。下面的参数都是由跟踪进程调用的。PTRACE_PEEKTEXT和PTRACE_PEEKDATA:从被跟踪进程的内存空间里读取位于addr地址的一个字长度的数据。忽略data参数。PTRACE_PEEKUSER: 读取被跟踪进程的用户空间中偏移量为addr的一个字长度的数据。忽略data参数。PTRACE_POKETEXT和PTRACE_POKEDATA:把data指向的一个字长的数据拷贝到被跟踪进程的内存中位置为addr内存空间里。PTRACE_POKEUSER: 将data指向的一个字长的数据拷贝到被跟踪进程的用户空间中偏移量为addr的内存空间里。PTRACE_CONT:重启被跟踪进程,并将data指向的作为信号传给被跟踪进程。如果data是零,那么只是正常的重启进程。忽略addr参数。PTRACE_KILL:发送SIGKILL到被跟踪进程。忽略addr和data参数。PTRACE_SINGLESTEP:和和PTRACE_CONT类似,只是被跟踪进程执行下一条指令的时候会立刻暂停。PTRACE_ATTACH:跟踪者用这个参数来将指定的pid的进程作为被跟踪进程,并将被跟踪进程作为跟踪进程的子进程。PTRACE_DETACH:和PTRACE_CONT类似,重启被跟踪进程。但是会先回复PTRACE_ATTACH和PTRACE_ME的操作。data被作为参数传递给被跟踪进程,忽略addr参数。PTRACE_SYSCALL:和PTRACE_CONT类似,只是被跟踪进程执行下一个系统调用的时候仍会暂停。Figure 2图三表示了ptrace调用实现与硬件有关的四个参数。PTRACE_SETOPTIONS:设置ptrace跟踪的参数选项,选项的值由data中的位图变量指定(可取图4中的值)。PTRACE_GETEVENTMSG:获取被跟踪进程的信息,并存放在data指向的跟踪进程的内存空间里。对于PTRACE_EVENT_EXIT信号,data中的值为跟踪进程终结的时候的返回值。对于PTRACE_EVENT_FORK,PTRACE_EVENT_VFORK 和PTRACE_EVENT_CLONE信号,则data中的值为新进程的pid。忽略addr参数。PTRACE_GETSIGINFO:获取引起被跟踪进程暂停的信号,并保存在data指向的内存空间。参数addr忽略。PTRACE_SETSIGINFO:设置引起被跟踪进程暂停的信号为data指向的内存空间中的siginfo_t结构体。参数addr忽略。Figure 3Figure 4图5是ptrace的实现和硬件有关的参数:PTRACE_GETREGS 和PTRACE_GETFPREGS:读取被跟踪进程的寄存器的值到跟踪进程中,保存在data指向的位置。参数addr忽略。PTRACE_SETREGS和PTRACE_SETFPREGS:将被跟踪进程的寄存器的值写改为跟踪进程中data指向的值。参数addr忽略。PTRACE_SYSEMU:让被跟踪进程继续执行,并且在下一个系统调用前停下了,但是不会执行该系统调用。PTRACE_SYSEMU_SINGLESTEP:和PTRACE_SYSEMU类似,但是实在下一条指令执行前停下来。Figure 52.1.4 ptrace的使用过程Ptrace的使用过程主要分为三部分,具体的将在2.2, 2.3和2.4中描述: 实现被跟踪进程和跟踪进程的关联。这个可以通过带PTRACE_TRACEME或者PTRACE_ATTACH参数的ptrace调用实现。前者有被跟踪进程调用,后者由发起跟踪的进程调用。 在被跟踪进程调用系统调用时被暂停,并切换到跟踪进程。 在跟踪进程中做调试工作。可以通过带PTRACE_PEEKTEXT等参数的ptrace调用实现。2.1.5 ptrace在内核源码的位置头文件:include/linux/syscalls.h: 声明了sys_ptrace()include/linux/ptrace.h: 声明了extern long arch_ptrace()include/asm-i386/ptrace.h: 维护了堆里面的寄存器值C文件:kernel/ptrace.c: sys_ptrace()arch/i386/kernel/ptrace.c: 定义了long arch_ptrace() 定义了int do_syscall_trace() arch/i386/kernel/entry.S中包含了跟踪进程和被跟踪进程间切换的代码。2.1.6 ptrace的调用过程 建立跟踪关联实现被跟踪进程和跟踪进程的关联。这个可以通过带PTRACE_TRACEME或者PTRACE_ATTACH参数的ptrace调用实现。前者有被跟踪进程调用,后者由发起跟踪的进程调用。这两个参数实现都在kernel/ptrace.c文件中。下面先讲较为复杂的PTRACE_ATTACH的函数。int ptrace_attach(struct task_struct *task)第153行至157行判断指定的pid是否合法,不能是自己或者init()进程。2.6内核中新加了线程组的概念,在task_struct结构中新增了tgid字段,tgid记录了主进程的pid。第169行至178行循环申请任务列表的锁。第181行判断了是不是已经被跟踪了,同一个进程只能被跟踪一次。第183行的may_attach函数则判断了当前用户是否有能够跟踪指定的任务。126行至131行判断了两个进程是否属于同一个用户或者同一个组;如果不是,则用capabale()判断当前进程是否可以被提升为特权用户进程。smp_rmb()用来同步对称多处理器,表示读操作不可跨越。然后判断目标进程的内核是否可以转储,不行的话则提升当前进程是否可以被提升为特权用户进程。最近137行检查ptrace的安全性。经过上面的一系列的判断,终于可以判定当前进程有权限跟踪目标进程了。第188行判断当前进程是否为目标进程的父进程。如果是,则只标记目标进程被跟踪(PT_PTRACED位);如果不是,则在标记目标进程被跟踪以外还标记PT_ADTTACHED位。第190行判断当前进程是否有跟踪所有系统调用的权限(CAP_SYS_PTRACE位),如果是,则标记PT_PTRACE_CAP位,此时如果被跟踪进程中的excv系统调用执行带suid的文件时仍然可以被跟踪进程跟踪到。第193行将当前进程(即跟踪进程)设置为被跟踪进程的父进程。Figure 6PTRACE_TRACEME的源码如图7所示,由于是将自己标记为被父进程跟踪,不需要判断权限和修改自己的父进程为跟踪进程,因此不需要锁定任务列表的锁,而只需锁定自己的任务结构体。第447行判断了是否已经被跟踪,448行判断安全性,453行把当前进程标识为被父进程跟踪。 被跟踪进程与跟踪进程间的切换2.3.1 entry.S中被跟踪进程与跟踪进程间的切换被跟踪进程在调用系统调用的时候会暂停下来,当前进程会前切换跟踪进程。这节我要讲的是从被跟踪进程进入系统调用开始,到切换到跟踪进程位置的实现过程。arch/i386/kernel/entry.SFigure 7Figure 8Figure 9系统调用的入口在arch/i386/kernel/entry.S中的第225行。226行先将当前系统调用号压栈保存,然后227行调用图7中的SAVE_ALL将所有的寄存去压栈保存。231行检查是否被标识为被跟踪,如果是则跳转到338行。然后在243行调用到arch/i386/kernel/ptrace.c中的do_syscall_trace()。在do_syscall_trace()中,被跟踪线程依次调用ptrace_notify(),ptrace_stop() 和 schedule()将当前进程切换到跟踪进程(具体的在这节末描述)。从do_syscall_trace()回来后回到第343行,若返回值为1, 则表示PTRACE_SYSEMU被标记(即不执行系统调用),则进入resume_userspace;若返回值为0,则从栈中回复当前系统调用号到寄存器eax,检查系统调用号是否在系统调用列表上面,然后进入系统调用。 include/asm-i386/thread_info.h当系统调用退出的时候,会回到第238行的syscall_exit,第242和243行检查系统调用过程中是否被_TIF_ALLWORK_MASK所标记的事件,如果有需要处理的则跳转到353行的syscall_exit_work.。254行判断如果不包含_TIF_SYSCALL_TRACE,_TIF_SYSCALL_AUDIT或者_TIF_SINGLESTEP,则跳转到work_pending。第356行sti打开所有中断。然后调用arch/i386/kernel/ptrace.c中的do_syscall_trace(),从而再次将跟踪进程切换为当前进程。2.3.2 do_syscall_trace()中的进程切换do_syscall_trace() 在arch/i386/kernel/ptrace.c中定义,负责将当前进程从被跟踪进程切换到跟踪进程。第660行判断是不是标记了TIF_SYSCALL_EMU,665行判断是否单步调试。第669与670行在进入系统调用的时候检查系统调用号。672行判断是否已经存在进程审计的上下文。674行在系统调用退出时调用audit_syscall_exit将其审计信息保存在审计上下文结构体中;但是如果是单步,则直接跳到out什么都不做。690行则判断如果当前进程没有被跟踪,则直接跳到out。700行和701行判断如果是单步调试,则发送SIGTRAP给当前进程。然后703行判断是不是标记了TIF_SYSCALL_TRACE或者TIF_SYSCALL_EMU,如果没有,则直接跳到out而不需要做下面的工作。如果是标记了TIF_SYSCALL_TRACE或者TIF_SYSCALL_EMU,则最终会执行709行代码,通过调用ptrace_notify()函数来通知跟踪进程。其中PT_TRACESYSGOOD是ptrace命令中PTRACE_SETOPTIONS参数的一个位图位。设置PT_TRACESYSGOOD后,709行使得被跟踪进程通知跟踪进程的信号的第七个bit设置为1,这样有利于跟踪进程判断是不是系统调用产生的trap。ptrace_notify()调用了ptrace_stop()来暂停当前进程,ptrace_stop()中调用schedule()将当前进程切换为跟踪进程。722行和723行,在进入系统调用的时候,将其审计信息保存在审计上下文结构体中。625行的ret的值在720行被设置过,如果没有标记TIF_SYSCALL_EMU,则直接返回0;如果标记了,则将系统调用号设置为不可用的-1,从而掉过该次系统调用。然后729行和730行保存审计信息。 Ptrace调试主要参数详解Ptace的源码量很大,我们读了很多,但是全部写下来实在有些困难。因此我们详细描述了一下的几个参数的实现方式。 PTRACE_CONT,PTRACE_SYSCALL,PTRACE_SYSEMUPTRACE_CONT,PTRACE_SYSCALL,PTRACE_SYSEMU作为一组来处理,分别处理修改对应的标志位。PTRACE_SYSEMU:让被跟踪进程继续执行,并且在下一个系统调用前停下了,但是不会执行该系统调用。第487行设置了TIF_SYSCALL_EMU标记位,第488行清除了TIF_SYSCALL_TRACE标记位。PTRACE_SYSCALL:和PTRACE_CONT类似,只是被跟踪进程执行下一个系统调用的时候仍会暂停。第490行设置了TIF_SYSCALL_TRACE标记位,第491行清除了TIF_SYSCALL_EMU标记位。PTRACE_CONT标记重启被跟踪进程,并将data指向的作为信号传给被跟踪进程。第493行和494行清除了TIF_SYSCALL_EMU标记位和TIF_SYSCALL_TRACE标记位。Figure 10在arch/i386/kernel/entry.S中系统调用进入和退出的时候对这两个位进行了判断。如图11和12所示,在进入系统调用的时候,会判断TIF_SYSCALL_EMU和TIF_SYSCALL_TRACE位,如果设置了,则进入系统调用的跟踪。Figure 11Figure 12如图13所示,从系统调用的返回的时候,会进行TIF_SYSCALL_TRACE的判断,如果设置了,则进入系统调用的跟踪。Figure 13 PTRACE_DETACHPTRACE_DETACH:和PTRACE_CONT类似,重启被跟踪进程。但是会先回复PTRACE_ATTACH或者PTRACE_ME的动作,也就是取消跟踪。data作为信号传递给被跟踪进程。detach操作通过调用关系如下ptrace_detach-_ptrace_detach-_ptrace_unlink实现。如图15所示,ptrace_detach检查data是否有效,并且调用ptrace_disable来消除ptrace跟踪的标记位(见图16),然后调用_ptrace_detach。在_ptrace_detach中调用_ptrace_unlink将被跟踪进程的父进程设置为原来的父进程。然后用wake_up_process唤醒被跟踪进程。Figure 14Figure 15Figure 16 PTRACE_KILL如图17所示,第510行判断被跟踪进程是否活着,如果已经死了,那么就不需要kill了。如果还活着,则向被跟踪进程发送SIGKILL信号(这里先设置exit_code)。然后514行清除单步调试标志位,515行唤醒被跟踪进程。Figure 17如图18所示,第259行消除了单步跟踪标志位。第262行至第265行消除了调试(如果TRAP_FLAG为1,则每执行一步就会陷入陷阱;PT_DTRACE是ptrace定义的单步执行的软件标志位)。Figure 18当被跟踪进程进入到do_syscall_trace的时候,会检测是否设置了exit_code(这里指SIGKILL信号),如果设置了则向自己发送SIGKILL信号。Figure 19 PTRACE_SINGLESTEPPTRACE_SINGLESTEP和PTRACE_SYSEMU_SINGLESTEP的处理类似,第521行判断了data代表的信号是否有效,第531行将这个信号设置成发送给被跟踪进程的信号第533行唤醒了被跟踪进程。中间的第524号至530行设置了相关的标志位,带SYSEMU表示下次系统调用暂停,但是不执行系统调用。Figure 20在set_singlestep中设置了TRAP_FALG位与PT_DTRACE位。前面描述过了,PT_DTRACE是ptrace定义的单步调试位。Figure 21 PTRACE_PEEKTEXT, PTRACE_PEEKDATAPTRACE_PEEKTEXT, PTRACE_PEEKDATA分别从被跟踪进程的指令空间和数据空间里读取一个字长的数据。这两个操作在linux中是一样的处理,因为用户进程的指令空间和数据空间是一致的。access_process_vm在kernel/ptrace.c中定义,它是对特定进程读写存储空间的函数。在access_process_vm函数中,通过get_task_mm获取指定进程的虚存空间,然后用get_user_pages将用户空间的内存映射到内存空间来,接着用copy_to_user_page将一个字长的数据写到指定的内存空间(在PTRACE_POKETEXT, PTRACE_POKEDATA中用copy_from_user_page从指定的内存空间读取数据)。Figure 22Figure 23 PTRACE_PEEKUSRPTRACE_PEEKUSER: 读取被跟踪进程的用户空间中偏移量为addr的一个字长度的数据。第386行到388行检查addr是否为可用的在堆栈中的位置。第391行判断addr参数指向的是不是前17个(FRAME_SIZE)寄存器,如果是,则调用getreg获取寄存器信息。第393行到第398行获取调式寄存器。第399行将获取的值写入到用户空间。Figure 24在getreg函数中,DS,ES,SS,CS是16位寄存器,所以取大于GS的寄存器要-8。调用get_stack_long获取保存在进程堆栈中的寄存器值。Figure 25 PTRACE_POKETEXT, PTRACE_POKEDATAPTRACE_POKETEXT, PTRACE_POKEDATA分别向被跟踪进程的指令空间和数据空间里写入一个字长的数据,是PT
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年医用高能射线设备合作协议书
- 2025年脲醛塑料项目合作计划书
- 心理健康课件素材
- 2025年医用电子直线加速器项目发展计划
- 空气知识课件
- 2025年注射用骨肽合作协议书
- 二零二五年度房地产预售包销合作协议
- 二零二五年度创新型农业用地租赁合同示范文本
- 二零二五年度高端移民定居全程辅导服务合同范本
- 二零二五年个人心理咨询分期购买合同范本
- 2025国家公务员考试时事政治试题(附含答案)
- 医学肺部知识培训课件
- 2025新人教版七年级数学课外拓展计划
- 职工心理安全课件
- 创维光伏培训课件
- 民警心理减压活动方案
- 财政预算编制
- 农村农业无人机应用合作协议
- 2025-2030中国聚乳酸纤维行业销售格局与供需平衡现状调研报告
- 制图接触网工程图例图的40课件
- 飞行营地项目可行性研究报告
评论
0/150
提交评论