2012-07-13 68 views
5

我想在我的服務器上執行任意(潛在危險)的二進制文件。因此,我使用objcopy將「main」符號重命名爲「other_main」,以便我可以鏈接到我自己的小主函數中,該函數在調用other_main之前爲RLIMIT_CPU設置適當的值並切換SECCOMP標誌。到目前爲止,我對這個解決方案非常滿意。SECCOMP:如何模擬malloc,realloc和free?

現在的問題是,第三方程序代碼可能包含一些對malloc的調用,可能會立即終止程序(sbrk不允許)。因此,我希望在設置應該由malloc/realloc/calloc/free使用的SECCOMP之前預先分配一些合理大小的數組(例如20MB)。不幸的是,我不知道如何歸檔最後一步。我是否必須自己實施所有這4項功能?我怎樣才能將自己的函數注入到stdlib中(例如,printf在內部調用malloc時會發生什麼?)。

+0

是否重命名符號realy作品?我真的不知道操作系統是如何處理被剝離的二進制文件的。 – 2012-07-13 20:34:09

+0

重命名符號在這裏工作正常。 objcopy似乎非常強大。你顯然不允許去除二進制文件,但這對我來說不是問題,因爲我自己編譯二進制文件。這只是不可信的C代碼。 – tux21b 2012-07-13 20:46:44

+0

你能否爲你的用戶提供一個不同於你的操作系統庫的C庫(例如Newlib)?如果是這樣,編寫自己的'sbrk'(不能離開你的沙箱),然後malloc/realloc/calloc/free和朋友都可以工作。 – 2012-07-13 20:59:15

回答

3

並非所有的malloc實現都基於sbrk(),例如有GNU mmalloc。如果需要自定義實現,This doc也可能有用。

+兩個簡單的malloc實現here

+0

唯一被允許的系統調用是讀,寫,簽名和退出。所以我也不能使用mmap,除非我在程序開始時預先分配足夠的內存(合理大小的靜態數組似乎對我的用例來說沒問題)。這個鏈接看起來很有用,假設我真的需要實現我自己的malloc。但我仍然不知道如何替換printf和stdlib中其他地方使用的內部malloc調用。 – tux21b 2012-07-13 20:57:27

+0

我已經更正了答案:dlmalloc實際上使用sbrk()。但是,我發現基於mmap()的GNU mmaloc。在你的情況下,你可能會考慮在其基礎上使用靜態池[]代替堆+簡單處理功能。例如,你也可以在靜態數組中保存N個引用。那當然是假動態記憶。 – pmod 2012-07-13 21:09:16

1

seccompsandbox

  • 使的Seccomp在一個線程中,其執行RPC(超過經由read/write一個預分配socketpair)到另一個(非的Seccomp)線程在相同的進程中能夠執行特權操作,如mmap
  • 修補功能,如malloc(內存中,在運行時)重定向到ir seccomp-safe wrappers

Chromium's seccomp Sandbox有一些關於工作原理的更多細節。

2

對於malloc和free,你的程序只需要定義它自己的版本。我見過的大多數libc實現(包括glibc,klibc和dietlibc)都會很樂意使用您的內存分配器例程。因此,在進入seccomp模式之前,使用mmap或sbrk分配一大塊內存,然後從這個塊中分配你的malloc/free。 memmgr是一個簡單的堆分配器,可以很容易地適應從固定緩衝區分配。

seccomp的真正問題在於它允許的系統調用集(讀,寫,退出和sigreturn)根本不足以運行鏈接到或多或少與任何 libc鏈接的程序。例如:

  • glibc中,出口和_exit調用exit_group glibc中
  • ,printf的可以調用MMAP在dietlibc
  • ,scanf的可調用的ioctl
  • 等等等等

這些調用是必要的,通常有很好的理由。例如,當從stdin讀取輸入時,dietlibc使用ioctl檢查stdin是否爲tty,以便刷新標準輸出。這是標準行爲,以確保在讀取交互式輸入之前提示是可見的,前提是輸出是行緩衝的。

所以,我得出結論,原來的seccomp模式或多或少是無用的。然而,模式2(又名「過濾器模式」)更有用,因爲它允許您將特定的系統調用列入白名單。我的github頁面上有一個proof of concept,它運行seccomp模式2中的程序,但允許它們使用printf和scanf,以及使用malloc/free分配內存。