为什么除了eax之外还提供orig_eax?

Mat*_*ner 15 c linux cpu-registers linux-kernel

为什么orig_eax列入成员sys/user.hstruct user_regs_struct

osg*_*sgx 37

因为它struct pt_regs是......,http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/arch/x86/include/asm/user_32.h#L77

 73  * is still the layout used by user mode (the new
 74  * pt_regs doesn't have all registers as the kernel
 75  * doesn't use the extra segment registers)
Run Code Online (Sandbox Code Playgroud)

因此,许多用户空间实用程序orig_eax在此处需要一个字段,因此它也包含在内user_regs_struct(以便与旧的调试器和ptracers 兼容)

下一个问题是"为什么orig_eax成员被包括在内struct pt_regs?".

它被添加到linux 0.95 http://lxr.linux.no/#linux-old+v0.95/include/sys/ptrace.h#L44中.我建议这是在使用pt_regsstruct 之后的其他一些unix之后完成的.评论0.95说

  29 * this struct defines the way the registers are stored on the 
  30 * stack during a system call.
Run Code Online (Sandbox Code Playgroud)

所以,地方orig_eax是由syscall接口定义的.这是http://lxr.linux.no/#linux-old+v0.95/kernel/sys_call.s

  17 * Stack layout in 'ret_from_system_call':
  18 *      ptrace needs to have all regs on the stack.
  19 *      if the order here is changed, it needs to be 
  20 *      updated in fork.c:copy_process, signal.c:do_signal,
  21 *      ptrace.c ptrace.h
  22 *
  23 *       0(%esp) - %ebx
 ...
  29 *      18(%esp) - %eax
 ...
  34 *      2C(%esp) - orig_eax
Run Code Online (Sandbox Code Playgroud)

为什么我们需要保存eax两次?因为eax将用于syscall的返回值(同一个文件,下面一点):

  96_system_call:
  97        cld
  98        pushl %eax              # save orig_eax
  99        push %gs
...
 102        push %ds
 103        pushl %eax              # save eax.  The return value will be put here.
 104        pushl %ebp
...
 117        call _sys_call_table(,%eax,4)
Run Code Online (Sandbox Code Playgroud)

Ptrace需要能够读取syscall之前的所有寄存器状态和syscall的返回值; 但返回值写入%eax.然后原始eax,在系统调用之前使用将丢失.为了保存它,有一个orig_eax字段.

更新:感谢R ..和伟大的LXR,我orig_eax在linux 0.95中进行了全面搜索.

它不仅用于ptrace,还用于重新启动系统调用时的do_signal(如果存在系统调用,则结束ERESTARTSYS)

 158                        *(&eax) = orig_eax;
Run Code Online (Sandbox Code Playgroud)

更新2:Linus 说了一些有趣的事情:

将ORIG_EAX设置为某个有效系统调用号的值非常重要,这样系统调用重启逻辑(请参阅信号处理代码)不会触发.

UPDATE3:ptracer app(调试器)可以更改orig_eax为更改要调用的系统调用号:http: //lkml.org/lkml/1999/10/30/82(在某些版本的内核中,是要在ptrace中更改的EIO ORIG_EAX)

  • 破解(看似)脆弱的问题的答案! (3认同)
  • 我认为这与系统调用有关(可能还有系统调用重启).+1用于追踪细节! (2认同)