[英]In a Linux system call, are system call parameters preserved in registers after the syscall finished (at the sys_exit tracepoint)?
是否保證能夠讀取sys_exit
跟蹤點的所有系統調用參數?
sysdig 驅動程序是一個 kernel 模塊,用於使用 kernel static 跟蹤點捕獲系統調用。 在這個項目中,一些系統調用參數是在sys_enter
tracepoint 讀取的,而其他一些參數是在sys_exit
讀取的(當然是返回值,以及用戶空間中的內容以避免頁面錯誤)。
為什么不讀取sys_exit
的所有參數? 這是因為某些參數在sys_exit
可能不可用嗎?
是否保證能夠讀取
sys_exit
跟蹤點的所有系統調用參數?
是的......不,我們需要將參數與寄存器區分開來。 Linux 系統調用應該保留所有通用用戶空間寄存器,除了用於返回值的寄存器(在某些架構上還有第二個寄存器來指示是否發生錯誤)。 然而,這並不意味着系統調用的輸入參數在進入和退出之間不能改變:如果一個寄存器保存了指向某些數據的指針的值,而寄存器本身沒有改變,它指向的數據很可能會改變.
查看 static 跟蹤點sys_exit
的代碼,您可以看到僅跟蹤系統調用號 ( id
) 及其返回值 ( ret
)。 有關更多信息,請參閱我的答案底部的注釋。
為什么不讀取
sys_exit
的所有參數? 這是因為某些參數可能在sys_exit
不可用嗎?
是的,我會說確保跟蹤參數的正確性是僅在出口處跟蹤是一個壞主意的主要原因。 即使您獲得了寄存器的值,您也無法知道系統調用退出時的實際參數。 即使系統調用本身可以保證保存和恢復用戶寄存器的 state,系統調用本身也可以更改作為參數傳遞的數據。 例如, recvmsg
系統調用采用指向 memory 中的struct msghdr
的指針,該指針既用作輸入又用作 output 參數; poll
系統調用對指向struct pollfd
的指針執行相同的操作。 此外,另一個線程或程序可能在進行系統調用時很好地修改了程序的 memory,從而改變了數據。
在特定情況下,系統調用也可能需要很長時間才能返回(例如sleep
或終端上的阻塞read
、偵聽套接字上的accept
等)。 如果您只在出口處進行跟蹤,您將獲得非常不正確的時間信息,最重要的是,您必須等待很長時間才能捕獲任何有意義的信息,即使該信息已經在入口點可用。
關於sys_exit
跟蹤點的注意事項
盡管您可以從計算機上提取當前任務的已保存寄存器的值,但我並不完全確定在sys_exit
跟蹤點中這樣做的語義。 我搜索了有關此特定案例的一些文檔,但沒有運氣,並且 kernel 代碼很好......復雜。
到達退出鈎子的調用鏈應該是:
entry_INT80_32
用於 x86 int 0x80
)
int 0x80
的do_int80_syscall_32()
)
如果在系統調用期間將致命信號傳遞給進程,而實際進程永遠不會到達系統調用的出口(即沒有任何值返回到用戶空間),跟蹤點仍然會被命中。 當發生此類信號傳遞時,將使用特殊的內部返回值,例如-ERESTARTSYS
(參見此處)。 此值不是實際的系統調用返回值(它不會返回到用戶空間),而是僅供 kernel 使用。 因此,如果進程接收到致命信號,則看起來sys_exit
跟蹤點正在被特殊的-ERESTARTSYS
命中。 例如,在SIGSTOP
+ SIGCONT
的情況下不會發生這種情況。 不過,對此持保留態度,因為我無法為此找到適當的文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.