Linux x86_64内核终止D状态的进程
来源:互联网 发布:windows回滚工具 编辑:程序博客网 时间:2024/06/08 10:30
说实话,64位系统上做这样的事是比较难的,因为你无法通过修改p->thread.ip来到达将进程拽出死循环的目的。要想知道64位系统上到底该怎么把进程执行绪引出,我们得先看看”标准“的做法是什么。
标准的做法就是fork时的行为,一个新进程刚刚被创建,它第一次进入运行状态之前,并不是通过switch_to切出的,为了让它”看起来像“是被切出而后被切入,就需要ret_from_fork来制造现场。问题是既然无法修改p->thread.ip,那又如何把执行绪引导到ret_from_fork里。
答案在于,64位(这里特指x86_64)系统是在switch_to中直接通过标志位判断跳转的,其过程如下:
1.在copy_thread中设置TIF_FORK标志2.在switch_to中判断TIF_FORK标志是否存在,若存在则直接跳转到ret_from_fork
因此ret_from_fork在64位系统中是硬编码到switch_to中的,不像32位系统中那样是可以随意修改的。
到这里,想通过修改堆栈上保存的PC寄存器来达到跳出循环的这条心也该死了。一个进程被切入,要么循着被切出之前的路径走,要么进入ret_from_fork,只有这两条路。如果循着之前的路,那还是在死循环里面,那么只能给D进程设置TIF_FORK标记,引导它进入ret_from_fork!然而我们并不是真的希望它return from fork,而是因为这是不得已的办法,它只能到ret_from_fork里面。接下来怎么办?
接下来的技术涉及到inline hook,我们希望hook掉ret_from_fork这个entry!具体如何inline hook,本文不讲,不然本文又要很长很长了。本文仅仅给出ret_from_fork被hook后的样子:
ENTRY(ret_from_fork) DEFAULT_FRAME LOCK ; btr $TIF_FORK,TI_flags(%r8) push kernel_eflags(%rip) CFI_ADJUST_CFA_OFFSET 8 popf # reset kernel eflags CFI_ADJUST_CFA_OFFSET -8 call schedule_tail # rdi: 'prev' task parameter GET_THREAD_INFO(%rcx) testl $_TIF_D, TI_flags(%rcx) # 这里判断是不是有新增的TIF_D标识,如果有,就直接do_exit jnz do_exit RESTORE_REST testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? je int_ret_from_sys_call testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET jnz int_ret_from_sys_call RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET jmp ret_from_sys_call # go to the SYSRET fastpath CFI_ENDPROCEND(ret_from_fork)
然后,模块里非常简单的设置TIF_FORK和TIF_D即可:
if (pid > 0) { for_each_process(p) { if (task_pid_vnr(p) == pid) { set_task_state(p, TASK_INTERRUPTIBLE); // 设置TIF_FORK,目的是执行流导入ret_from_fork set_tsk_thread_flag(p, TIF_FORK); // 设置TIF_D,目的是将执行流在hook后的ret_from_fork里进行区分 set_tsk_thread_flag(p, TIF_D); wake_up_process(p); break; } }}
和32位系统的实验方法一样,D进程将被拉出死循环,然后死掉!
注意,用kprobe/jprobe技术进行hook事实上就是一种inline hook的应用,然而我们不方便用它来hook ret_from_fork,因为你既不能在ret_from_fork之前执行hook,也不能之后执行hook,而必须在其中间,即调用完schedule_tail之后去执行do_exit,因此,正确的做法是hook别的函数而不是hook ret_from_fork这个函数。仔细观察ret_from_fork的汇编码,就会发现在int_ret_from_sys_call,ret_from_sys_call的pre handler中进行TIF_D的判断并且执行do_exit应该是正确的做法!
温州皮鞋,下雨进水不会胖!
- Linux x86_64内核终止D状态的进程
- Linux x86内核终止D状态的进程
- Linux如何终止D状态的进程
- linux下进程的状态,创建,替换,等待,终止
- linux进程状态D
- Linux进程状态:D
- linux进程状态D
- Linux 进程的 Uninterruptible sleep(D) 状态
- Linux 进程的 Uninterruptible sleep(D) 状态
- Linux 进程的 Uninterruptible sleep(D) 状态
- Linux 进程的 Uninterruptible sleep(D) 状态
- UNIX的进程终止状态小结
- 如何获取进程的终止状态
- Linux杀掉D状态进程
- Linux之进程的终止
- Linux进程-进程的终止
- Linux进程管理之进程的终止
- Linux进程管理之进程的终止
- 数据库程序实现增删改查的实际应用
- 洛谷 P1373 小a和uim之大逃离
- Android BarUtils-栏相关工具类
- Java程序优化细节
- MediaRecorder 录制视频
- Linux x86_64内核终止D状态的进程
- Intellij IDEA 搭建Spring MVC & MyBatis开发环境
- 冒泡排序法
- 数组
- POJ 1006生理周期
- JVM调优总结 -Xms -Xmx -Xmn -Xss
- Android 3D滑动菜单完全解析,实现推拉门式的立体特效
- CUDA里面GRID, BLOCK 边界检测
- 进程与线程的超级简单形象解释