Ptrace源码分析报告docWord格式文档下载.docx

上传人:b****6 文档编号:20935193 上传时间:2023-01-26 格式:DOCX 页数:9 大小:21.34KB
下载 相关 举报
Ptrace源码分析报告docWord格式文档下载.docx_第1页
第1页 / 共9页
Ptrace源码分析报告docWord格式文档下载.docx_第2页
第2页 / 共9页
Ptrace源码分析报告docWord格式文档下载.docx_第3页
第3页 / 共9页
Ptrace源码分析报告docWord格式文档下载.docx_第4页
第4页 / 共9页
Ptrace源码分析报告docWord格式文档下载.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

Ptrace源码分析报告docWord格式文档下载.docx

《Ptrace源码分析报告docWord格式文档下载.docx》由会员分享,可在线阅读,更多相关《Ptrace源码分析报告docWord格式文档下载.docx(9页珍藏版)》请在冰豆网上搜索。

Ptrace源码分析报告docWord格式文档下载.docx

其中,第二个参数指定了对象进程的进程号,addr和data分别是内存地址和传入的数据。

Figure12.1.3ptrace的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的一个字长度的数据。

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类似,只是被跟踪进程执行下一个系统调用的时候仍会暂停。

Figure2图三表示了ptrace调用实现与硬件有关的四个参数。

PTRACE_SETOPTIONS设置ptrace跟踪的参数选项,选项的值由data中的位图变量指定(可取图4中的值)。

PTRACE_GETEVENTMSG获取被跟踪进程的信息,并存放在data指向的跟踪进程的内存空间里。

对于PTRACE_EVENT_EXIT信号,data中的值为跟踪进程终结的时候的返回值。

对于PTRACE_EVENT_FORK,PTRACE_EVENT_VFORK和PTRACE_EVENT_CLONE信号,则data中的值为新进程的pid。

PTRACE_GETSIGINFO获取引起被跟踪进程暂停的信号,并保存在data指向的内存空间。

参数addr忽略。

PTRACE_SETSIGINFO设置引起被跟踪进程暂停的信号为data指向的内存空间中的siginfo_t结构体。

Figure3Figure4图5是ptrace的实现和硬件有关的参数PTRACE_GETREGS和PTRACE_GETFPREGS读取被跟踪进程的寄存器的值到跟踪进程中,保存在data指向的位置。

PTRACE_SETREGS和PTRACE_SETFPREGS将被跟踪进程的寄存器的值写改为跟踪进程中data指向的值。

PTRACE_SYSEMU让被跟踪进程继续执行,并且在下一个系统调用前停下了,但是不会执行该系统调用。

PTRACE_SYSEMU_SINGLESTEP和PTRACE_SYSEMU类似,但是实在下一条指令执行前停下来。

Figure52.1.4ptrace的使用过程Ptrace的使用过程主要分为三部分,具体的将在2.2,2.3和2.4中描述实现被跟踪进程和跟踪进程的关联。

这个可以通过带PTRACE_TRACEME或者PTRACE_ATTACH参数的ptrace调用实现。

前者有被跟踪进程调用,后者由发起跟踪的进程调用。

在被跟踪进程调用系统调用时被暂停,并切换到跟踪进程。

在跟踪进程中做调试工作。

可以通过带PTRACE_PEEKTEXT等参数的ptrace调用实现。

2.1.5ptrace在内核源码的位置头文件include/linux/syscalls.h声明了sys_ptraceinclude/linux/ptrace.h声明了externlongarch_ptraceinclude/asm-i386/ptrace.h维护了堆里面的寄存器值C文件kernel/ptrace.csys_ptracearch/i386/kernel/ptrace.c定义了longarch_ptrace定义了intdo_syscall_tracearch/i386/kernel/entry.S中包含了跟踪进程和被跟踪进程间切换的代码。

2.1.6ptrace的调用过程建立跟踪关联实现被跟踪进程和跟踪进程的关联。

这两个参数实现都在“kernel/ptrace.c“文件中。

下面先讲较为复杂的PTRACE_ATTACH的函数。

intptrace_attachstructtask_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行将当前进程(即跟踪进程)设置为被跟踪进程的父进程。

Figure6PTRACE_TRACEME的源码如图7所示,由于是将自己标记为被父进程跟踪,不需要判断权限和修改自己的父进程为跟踪进程,因此不需要锁定任务列表的锁,而只需锁定自己的任务结构体。

第447行判断了是否已经被跟踪,448行判断安全性,453行把当前进程标识为被父进程跟踪。

被跟踪进程与跟踪进程间的切换2.3.1entry.S中被跟踪进程与跟踪进程间的切换被跟踪进程在调用系统调用的时候会暂停下来,当前进程会前切换跟踪进程。

这节我要讲的是从被跟踪进程进入系统调用开始,到切换到跟踪进程位置的实现过程。

arch/i386/kernel/entry.SFigure7Figure8Figure9系统调用的入口在“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.2do_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作为一组来处理,分别处理修改对应的标志位。

第487行设置了TIF_SYSCALL_EMU标记位,第488行清除了TIF_SYSCALL_TRACE标记位。

第490行设置了TIF_SYSCALL_TRACE标记位,第491行清除了TIF_SYSCALL_EMU标记位。

PTRACE_CONT标记重启被跟踪进程,并将data指向的作为信号传给被跟踪进程。

第493行和494行清除了TIF_SYSCALL_EMU标记位和TIF_SYSCALL_TRACE标记位。

Figure10在“arch/i386/kernel/entry.S“中系统调用进入和退出的时候对这两个位进行了判断。

如图11和12所示,在进入系统调用的时候,会判断TIF_SYSCALL_EMU和TIF_SYSCALL_TRACE位,如果设置了,则进入系统调用的跟踪。

Figure11Figure12如图13所示,从系统调用的返回的时候,会进行TIF_SYSCALL_TRACE的判断,如果设置了,则进入系统调用的跟踪。

Figure13PTRACE_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唤醒被跟踪进程。

Figure14Figure15Figure16PTRACE_KILL如图17所示,第510行判断被跟踪进程是否活着,如果已经死了,那么就不需要kill了。

如果还活着,则向被跟踪进程发送SIGKILL信号(这里先设置exit_code)。

然后514行清除单步调试标志位,515行唤醒被跟踪进程。

Figure17如图18所示,第259行消除了单步跟踪标志位。

第262行至第265行消除了调试(如果TRAP_FLAG为1,则每执行一步就会陷入陷阱;

PT_DTRACE是ptrace定义的单步执行的软件标志位)。

Figure18当被跟踪进程进入到do_syscall_trace的时候,会检测是否设置了exit_code(这里指SIGKILL信号),如果设置了则向自己发送SIGKILL信号。

Figure19PTRACE_SINGLESTEPPTRACE_SINGLESTEP和PTRACE_SYSEMU_SINGLESTEP的处理类似,第521行判断了data代表的信号是否有效,第531行将这个信号设置成发送给被跟踪进程的信号第533行唤醒了被跟踪进程。

中间的第524号至530行设置了相关的标志位,带SYSEMU表示下次系统调用暂停,但是不执行系统调用。

Figure20在set_singlestep中设置了TRAP_FALG位与PT_DTRACE位。

前面描述过了,PT_DTRACE是ptrace定义的单步调试位。

Figure21PTRACE_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从指定的内存空间读取数据)。

Figure22Figure23PTRACE_PEEKUSRPTRACE_PEEKUSER读取被跟踪进程的用户空间中偏移量为addr的一个字长度的数据。

第386行到388行检查addr是否为可用的在堆栈中的位置。

第391行判断addr参数指向的是不是前17个(FRAME_SIZE)寄存器,如果是,则调用getreg获取寄存器信息。

第393行到第398行获取调式寄存器。

第399行将获取的值写入到用户空间。

Figure24在getreg函数中,DS,ES,SS,CS是16位寄存器,所以取大于GS的寄存器要-8。

调用get_stack_long获取保存在进程堆栈中的寄存器值。

Figure25PTRACE_POKETEXT,PTRACE_POKEDATAPTRACE_POKETEXT,PTRACE_POKEDATA分别向被跟踪进程的指令空间和数据空间里写入一个字长的数据,是PTRACE_PEEKTEXT,PTRACE_PEEKDATA的逆操作。

通过调用access_process_vm函数中向指定的内存空间写入数据,详见2.4.5。

Figure26PTRACE_POKEUSRPTRACE_POKEUSR是向指定的用户空间写入一个字长的数据,第414行至第416行判断addr是否合法,第418行判断写入的是不是一般寄存器,如果是则调用putreg来写值。

如果不是,则判断是不是调试寄存器,如果是,则改变调试寄存器的值(但是实际上只有7号调试寄存器的值能够改变)。

Figure27Figure28PTRACE_GETREGSPTRACE_GETREGS读取被跟踪进程的寄存器的值到跟踪进程中,保存在data指向的位置。

第543行access_ok判断了datap指向的空间是否可写(在i386只检查了指向的空间是否在用户空间)。

第547行至550行,将记录在堆栈中的被跟踪进程的寄存器值写入到跟踪进程的data指向的用户空间。

如果成功,则551行把返回值设置为0。

Figure29PTRACE_SETREGSPTRACE_SETREGS将data指向的位置的值写入到保存被跟踪进程的寄存器的堆栈。

第557行access_ok判断了datap指向的空间是否可读(在i386只检查了指向的空间是否在用户空间)。

第562行,从用户空间datap指向的位置读取一个字长的值。

第563行将读取的值写入到被跟踪进程的第i个寄存器在堆栈中的位置。

如果成功,则566行把返回值设置为0。

Figure30参考资料Linux内核源代码情景分析毛德操,胡希明深入分析Linux内核源代码陈莉君SourceofStrace-4.5.19SourceofLinuxkernel-2.6.16.18玩转ptracehttp//其他不计其数的BLOG

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 教育学心理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1