有没有人对PTRACE_SYSEMU的使用有任何好的解释,教程,书籍或指南?
答案 0 :(得分:0)
我觉得有趣:
使用ptrace的编程库更容易:
对于pinktrace有例子,sydbox源是复杂的pinktrace用例的例子。总的来说,我发现作者是关于使用和测试pinktrace的好人。
答案 1 :(得分:0)
来自Linux内核源代码的小测试使用了PTRACE_SYSEMU:
http://code.metager.de/source/xref/linux/stable/tools/testing/selftests/x86/ptrace_syscall.c 或http://lxr.free-electrons.com/source/tools/testing/selftests/x86/ptrace_syscall.c
186 struct user_regs_struct regs;
187
188 printf("[RUN]\tSYSEMU\n");
189 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
190 err(1, "PTRACE_SYSCALL");
191 wait_trap(chld);
192
193 if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0)
194 err(1, "PTRACE_GETREGS");
195
196 if (regs.user_syscall_nr != SYS_gettid ||
197 regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
198 regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
199 regs.user_arg4 != 14 || regs.user_arg5 != 15) {
200 printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
201 nerrs++;
202 } else {
203 printf("[OK]\tInitial nr and args are correct\n");
204 }
205
206 printf("[RUN]\tRestart the syscall (ip = 0x%lx)\n",
207 (unsigned long)regs.user_ip);
208
209 /*
210 * This does exactly what it appears to do if syscall is int80 or
211 * SYSCALL64. For SYSCALL32 or SYSENTER, though, this is highly
212 * magical. It needs to work so that ptrace and syscall restart
213 * work as expected.
214 */
215 regs.user_ax = regs.user_syscall_nr;
216 regs.user_ip -= 2;
217 if (ptrace(PTRACE_SETREGS, chld, 0, ®s) != 0)
218 err(1, "PTRACE_SETREGS");
219
220 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
221 err(1, "PTRACE_SYSCALL");
222 wait_trap(chld);
223
224 if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0)
225 err(1, "PTRACE_GETREGS");
226
所以,它看起来只是另一个ptrace
调用,它允许程序运行直到它进行下一次系统调用;然后停止孩子并发出信号。它可以读取寄存器,可选择更改一些并重新启动系统调用。
在http://lxr.free-electrons.com/source/kernel/ptrace.c?v=4.10#L1039中实施,与其他踩踏ptrace
来电一样:
1039 #ifdef PTRACE_SINGLESTEP
1040 case PTRACE_SINGLESTEP:
1041 #endif
1042 #ifdef PTRACE_SINGLEBLOCK
1043 case PTRACE_SINGLEBLOCK:
1044 #endif
1045 #ifdef PTRACE_SYSEMU
1046 case PTRACE_SYSEMU:
1047 case PTRACE_SYSEMU_SINGLESTEP:
1048 #endif
1049 case PTRACE_SYSCALL:
1050 case PTRACE_CONT:
1051 return ptrace_resume(child, request, data);
手册页有一些信息:http://man7.org/linux/man-pages/man2/ptrace.2.html
PTRACE_SYSEMU,PTRACE_SYSEMU_SINGLESTEP(自Linux 2.6.14起) 对于PTRACE_SYSEMU,继续并在进入下一个时停止 系统调用,不会执行。见 关于系统调用的文档 - 在下面停止。对于 PTRACE_SYSEMU_SINGLESTEP,做同样的但也是单步的if 不是系统调用。此调用由User等程序使用 模式Linux ,希望模拟所有tracee的系统调用。 data参数被视为PTRACE_CONT。地址 参数被忽略了。目前支持这些请求 仅在x86上。
因此,它不可移植,仅用于x86平台上的Usermode linux(um)作为经典PTRACE_SYSCALL
的变体。对于sysemu的测试有一些评论,请点击此处:http://lxr.free-electrons.com/source/arch/um/os-Linux/start_up.c?v=4.10#L155
155 __uml_setup("nosysemu", nosysemu_cmd_param,
156 "nosysemu\n"
157 " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
158 " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
159 " behaviour of ptrace() and helps reducing host context switch rate.\n"
160 " To make it working, you need a kernel patch for your host, too.\n"
161 " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n"
162 " information.\n\n");
163
164 static void __init check_sysemu(void)
评论中的链接从2004年开始重定向到秘密网站http://sysemu.sourceforge.net/:
为什么?
UML使用ptrace()和PTRACE_SYSCALL来捕获系统调用。但是,通过 这样,您就无法删除真正的系统调用,只能对其进行监控。 UML, 避免真正的系统调用并模拟它,替换真正的系统调用 调用getpid()。此方法生成两个上下文切换 一个。解决方案
解决方案是将ptrace()的行为更改为不调用real 系统调用,因此我们不必通过调用getpid()来替换它。 怎么样?
通过向ptrace(),PTRACE_SYSEMU添加一个新命令,就像这样 PTRACE_SYSCALL没有执行系统调用。要添加此命令,我们需要 修补主机内核。要在UML内核中使用这个新命令,我们 还需要修补UML内核。