linux - x64 - x32 syscall



為什麼x86-64 Linux系統調用會修改RCX,這個值意味著什麼? (1)

我正在嘗試使用 sys_brk syscall在linux中分配一些內存。 這是我嘗試過的:

BYTES_TO_ALLOCATE equ 0x08

section .text
    global _start

_start:
    mov rax, 12
    mov rdi, BYTES_TO_ALLOCATE
    syscall

    mov rax, 60
    syscall

根據linux調用約定,我希望返回值在 rax 寄存器中(指向已分配內存的指針)。 我在gdb中運行它,在進行 sys_brk 系統調用之後,我注意到以下寄存器內容

在系統調用之前

rax            0xc      12
rbx            0x0      0
rcx            0x0      0
rdx            0x0      0
rsi            0x0      0
rdi            0x8      8

在系統調用之後

rax            0x401000 4198400
rbx            0x0      0
rcx            0x40008c 4194444 ; <---- What does this value mean?
rdx            0x0      0
rsi            0x0      0
rdi            0x8      8

在這種情況下,我不太了解 rcx 寄存器中的值。 哪一個用作指向我用 sys_brk 分配的8個字節的開頭的指針?


系統調用返回值一如既往地在 rax 。 請參閱 i386和x86-64上UNIX和Linux系統調用的調用約定是什麼

請注意, sys_brk 界面與 brk / sbrk POSIX函數略有不同; 請參閱 Linux brk(2) 手冊頁 C庫/內核差異部分 。 具體來說, Linux sys_brk 設置 程序中斷 ; arg和返回值都是指針。 請參閱 Assembly x86 brk()調用 。 這個答案需要upvotes,因為它是這個問題上唯一的好人。

你問題的另一個有趣的部分是:

在這種情況下,我不太了解rcx寄存器中的值

您將看到 syscall / sysret 指令如何設計為允許內核恢復用戶空間執行但仍然很快的機制。

syscall 不執行任何加載或存儲,它只修改寄存器。 它不使用特殊寄存器來保存返回地址,而只使用常規整數寄存器。

在內核返回到用戶空間代碼之後, RCX=RIPR11=RFLAGS 並不是巧合 。 這種情況的唯一方法是,如果 ptrace 系統調用在內核中修改了進程保存的 rcxr11 值。 ( ptrace 是gdb使用的系統調用)。 在這種情況下,Linux將使用 iret 而不是 sysret 返回用戶空間,因為較慢的通用情況 iret 可以做到這一點。 ( 如果你在64位代碼中使用32位int 0x80 Linux ABI會發生什麼? 對於Linux系統調用入口點的一些演練。大多數是32位進程的入口點,而不是來自64位系統調用的入口點然而,這是一個過程。)

而不是將返回地址推送到內核堆棧(如 int 0x80 ), syscall

  • 設置RCX = RIP,R11 = RFLAGS(因此在執行 syscall 之前,內核甚至無法查看這些寄存器的原始值)。
  • 使用配置寄存器( IA32_FMASK MSR)中的預配置掩碼屏蔽 IA32_FMASK 。 這讓內核禁用中斷(IF),直到它完成 swapgs 並將 swapgs 設置為指向內核堆棧。 即使將 cli 作為入口點的第一條指令,也會有一個漏洞的窗口。 你也可以通過屏蔽 DF 來免費獲得 rep movs 所以即使用戶空間使用了 stdrep movs / rep movs 也會向上移動。

    有趣的事實:AMD首次提出的 syscall / swapgs 設計並沒有掩蓋RFLAGS,但 他們在內核開發人員在amd64郵件列表上的反饋之後 (在〜2000年,第一個芯片之前的幾年)改變了它。

  • 跳轉到配置的 syscall 入口點(設置CS:RIP = IA32_LSTAR )。 我想,舊的 CS 值不會保存在任何地方。

  • 它沒有做任何其他事情,內核必須使用 swapgs 來訪問保存內核堆棧指針的信息塊,因為 rsp 仍然有來自用戶空間的值。

因此, syscall 的設計需要一個系統調用ABI,其中註冊符號,這就是為什麼這些值是它們的原因。





system-calls