system_call
函数的汇编代码如下:
.text:FFFFFFFF8020AFC0 public system_call
.text:FFFFFFFF8020AFC0 swapgs ; 将gs切换至内核态
.text:FFFFFFFF8020AFC3 db 66h, 66h, 66h, 66h, 2Eh
.text:FFFFFFFF8020AFC3 nop word ptr [rax+rax+00000000h]
.text:FFFFFFFF8020AFD0 mov gs:pt_regs._r12, rsp ; old_rsp, 用户态栈指针
.text:FFFFFFFF8020AFD9 mov rsp, gs:pt_regs._r13 ; kernel_stack
.text:FFFFFFFF8020AFE2 sti
.text:FFFFFFFF8020AFE3 sub rsp, 50h ; rsp->pt_regs.rip
.text:FFFFFFFF8020AFE7 mov [rsp+40h], rdi ; arg0
.text:FFFFFFFF8020AFEC mov [rsp+38h], rsi ; arg1
.text:FFFFFFFF8020AFF1 mov [rsp+30h], rdx ; arg2
.text:FFFFFFFF8020AFF6 mov [rsp+20h], rax ; 系统调用号
.text:FFFFFFFF8020AFFB mov [rsp+18h], r8 ; arg4
.text:FFFFFFFF8020B000 mov [rsp+10h], r9 ; arg5
.text:FFFFFFFF8020B005 mov [rsp+8], r10 ; arg3
.text:FFFFFFFF8020B00A mov [rsp+0], r11 ; eflags
.text:FFFFFFFF8020B00E mov [rsp+48h], rax ; 系统调用号
.text:FFFFFFFF8020B013 mov [rsp+50h], rcx ; 返回地址rip
.text:FFFFFFFF8020B018 mov rcx, gs:pt_regs._r13
.text:FFFFFFFF8020B021 sub rcx, 1FD8h ; thread_union大小为8KB
.text:FFFFFFFF8020B028 test [rcx+thread_union.thread_info.flags], 181h
.text:FFFFFFFF8020B02F jnz tracesys
.text:FFFFFFFF8020B035 cmp rax, 11Fh ; 检查系统调用号
.text:FFFFFFFF8020B03B ja badsys
.text:FFFFFFFF8020B041 mov rcx, r10
.text:FFFFFFFF8020B044 call ds:sys_call_table[rax*8]
.text:FFFFFFFF8020B04B mov [rsp+20h], rax ; 返回值
.text:FFFFFFFF8020B04B system_call endp
.text:FFFFFFFF8020B050 ret_from_sys_call:
.text:FFFFFFFF8020B050 mov edi, 0FEFFh ; flag_mask
.text:FFFFFFFF8020B055 sysret_check proc near
.text:FFFFFFFF8020B055 mov rcx, gs:pt_regs._r13
.text:FFFFFFFF8020B05E sub rcx, 1FD8h ; kernel_stack
.text:FFFFFFFF8020B065 cli
.text:FFFFFFFF8020B066 mov edx, [rcx+10h]
.text:FFFFFFFF8020B069 and edx, edi
.text:FFFFFFFF8020B06B jnz short sysret_careful
.text:FFFFFFFF8020B06D mov rcx, [rsp+50h] ; 返回地址
.text:FFFFFFFF8020B072 mov r11, [rsp+0] ; eflags
.text:FFFFFFFF8020B076 mov r10, [rsp+8] ; arg3
.text:FFFFFFFF8020B07B mov r9, [rsp+10h] ; arg5
.text:FFFFFFFF8020B080 mov r8, [rsp+18h] ; arg4
.text:FFFFFFFF8020B085 mov rax, [rsp+20h] ; 返回值
.text:FFFFFFFF8020B08A mov rdx, [rsp+30h] ; 返回地址
.text:FFFFFFFF8020B08F mov rsi, [rsp+38h] ; arg2
.text:FFFFFFFF8020B094 mov rdi, [rsp+40h] ; arg1
.text:FFFFFFFF8020B099 mov rsp, gs:pt_regs._r12 ; old_rsp
.text:FFFFFFFF8020B0A2 swapgs ; 切换回用户态gs
.text:FFFFFFFF8020B0A5 sysret ; 中断返回
进入system_call
函数的寄存器初始状态:
// include/asm-x86/ptrace.h
struct pt_regs {
unsigned long r15;
unsigned long r14;
unsigned long r13; // kernel_stack
unsigned long r12; // old_rsp
unsigned long rbp;
unsigned long rbx;
/* arguments: non interrupts/non tracing syscalls only save upto here*/
unsigned long r11; // eflags
unsigned long r10; // arg3
unsigned long r9; // arg5
unsigned long r8; // arg4
unsigned long rax; // 系统调用号&系统调用返回值
unsigned long rcx; // 返回地址rip
unsigned long rdx; // arg2
unsigned long rsi; // arg1
unsigned long rdi; // arg0
unsigned long orig_rax; // 系统调用号(2)
/* end of arguments */
/* 内核态返回用户态需要恢复现场的数据 */
unsigned long rip; // 返回地址(2), 默认内核栈起始地址
unsigned long cs; // 用户态代码段
unsigned long eflags; // 用户态eflags
unsigned long rsp; // 用户栈顶
unsigned long ss; // 用户数据段
/* top of stack page */
};
- rcx:返回地址
- rax:系统调用号
0xffffffff8020afd0 <system_call+16>: mov %rsp,%gs:0x18 # 切换至内核栈
发起系统调用的用户态栈顶,其参数依次为:
- 返回地址
- 用户态代码段 cs
- 用户态 eflags
- 用户态栈顶 rsp
- 用户态栈段 ss
用户程序发起系统调用的汇编代码如下:
.text:FFFFFFFF8020B018 mov rcx, gs:pt_regs._r13
.text:FFFFFFFF8020B021 sub rcx, 1FD8h ; thread_union大小为8KB
此时rsp指向thread_union
结构体的首地址。
发起系统调用
返回值为pid=956
成功返回进程pid: