<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          LWN:seccomp用戶空間通知功能以及信號處理!

          共 3100字,需瀏覽 7分鐘

           ·

          2021-05-01 21:07

          關(guān)注了就能看到更多這么棒的文章哦~

          Seccomp user-space notification and signals

          By Jonathan Corbet
          April 9, 2021
          DeepL assisted translation
          https://lwn.net/Articles/851813/

          seccomp()機制允許增加一個 filter program 過濾程序(以 "classic "BPF 的形式),來對是否允許進(jìn)程調(diào)用某個系統(tǒng)調(diào)用做出決定。user-space notification 功能可以把決定權(quán)進(jìn)一步交給另一個進(jìn)程來做。正如 Sargun Dhillon 最近的 patch set 所示,用戶空間通知仍然有一些沒有處理完美的場景,特別是在涉及到 signal 之時。這個 patch 進(jìn)行了一個簡單改動,希望能解決一個相當(dāng)復(fù)雜的問題。這個問題是 Go 語言的搶占模式(preemption model)的改動引出的。

          通常可以使用 seccomp() 來作為一種簡單的縮減攻擊面的方式,從而使得大部分系統(tǒng)調(diào)用對于目標(biāo)進(jìn)程來說都可以不受限制地使用。用戶空間通知這個功能也可以用在這種情況下,但它的主要目的其實是另一種情況:允許那個監(jiān)控進(jìn)程來模擬完成目標(biāo)進(jìn)程的系統(tǒng)調(diào)用。舉例來說,某個容器管理器(container manager)希望在容器內(nèi)提供 mount() 功能,但需要嚴(yán)格限制可以 mount 哪些東西。這時就可以利用用戶空間通知功能,來允許(擁有特權(quán)的,也就是 privileged)監(jiān)控進(jìn)程來真正進(jìn)行這個它同意進(jìn)行的 mount 動作,并將結(jié)果返回給目標(biāo)進(jìn)程。

          當(dāng)監(jiān)控進(jìn)程在處理一個攔截下來的系統(tǒng)調(diào)用時,目標(biāo)進(jìn)程會被阻塞在內(nèi)核中,一直等待返回結(jié)果。不過如果該進(jìn)程收到一個 signal(信號),那么就會終止這個等待狀態(tài),立即對該 signal 做出響應(yīng)。如果該信號本身不是一個 fatal signal,那么可能會導(dǎo)致系統(tǒng)調(diào)用返回一個 EINTR 錯誤給此進(jìn)程。并且,監(jiān)控進(jìn)程并不知道這個 signal,于是它后面還是會試圖給內(nèi)核提供對原來那個系統(tǒng)調(diào)用的處理結(jié)果。此時,它會得到一個 ENOENT 錯誤,表明之前等待的進(jìn)程已經(jīng)不存在了。

          這會帶來一些不方便之處,尤其是當(dāng)監(jiān)控進(jìn)程已經(jīng)替目標(biāo)進(jìn)程執(zhí)行了某些耗費很多時間的任務(wù)的情況下。如果該 signal 沒有殺死目標(biāo)進(jìn)程,那么很可能不久之后還會重試,導(dǎo)致一些額外的工作。不過大多數(shù)時候,在 seccomp() 監(jiān)控之下運行的程序中很少會有這類 non-fatal signal。

          Go signal

          準(zhǔn)確地說,這是過去的事實情況,但 Go 語言的開發(fā)者們也有責(zé)任。Go 語言的 "goroutine" 輕量級線程模型(lightweight thread model)要求 Go runtime(運行時)來處理 schedule 工作,也就是根據(jù)需要在 goroutine 之間切換確保它們都有機會運行。除此之外,偶爾還會出現(xiàn) "stop the world" 的情況,也就是所有的 goroutine 都被暫停,從而讓垃圾收集器(garbage collector)完成工作。之前實現(xiàn)這個功能的具體方式是讓編譯器在每個函數(shù)的開頭來增加一個 preemption check 來處理。

          但是,如果一個 goroutine 運行了很長時間卻一直沒有調(diào)用任何函數(shù),那么會發(fā)生什么?如果該 routine 在某個非常嚴(yán)格的循環(huán)中執(zhí)行的話就可能會發(fā)生這種情況。最壞情況下,比如這個 goroutine 可能一直在 spin 等待一個鎖,導(dǎo)致鎖的持有者(另一個 goroutine)都沒有機會運行,也就無法釋放這個鎖,這種情況往往會導(dǎo)致用戶不滿。另一種也會導(dǎo)致 goroutine 之間的 preemption 的情況,就是執(zhí)行那些耗時很長的系統(tǒng)調(diào)用。

          Go 開發(fā)者們已經(jīng)嘗試了一些方法來解決這個問題。其中一種就是在代碼向回跳轉(zhuǎn)(backward jump)的地方插入 preemption check(例如在某個循環(huán)的末尾)。但是哪怕將檢查代碼減少到只有一條指令,這帶來的性能損失也還是太高了。這種方法對于那些耗時很長的系統(tǒng)調(diào)用場景也沒有幫助。所以 Go 社區(qū)決定用一種非合作性的搶占機制(non-cooperative preemption mechanism)來解決這個問題。簡單來說,任何一個運行了 10ms 而沒有 yield(讓出)過的 goroutine 都會收到 runtime 發(fā)出的 SIGURG signal,然后 Go runtime 運行時會重新安排一個線程來執(zhí)行、啟動垃圾回收、或者做其他什么需要在此時做的工作。

          而通過 seccomp()轉(zhuǎn)給另一個進(jìn)程執(zhí)行的系統(tǒng)調(diào)用往往會比平時運行的時間更長長,而監(jiān)控進(jìn)程可能在執(zhí)行的相應(yīng)任務(wù)(例如 mount 文件系統(tǒng))可能需要更加長的時間。顯然,這導(dǎo)致了 Go 程序中大量的以 seccomp()轉(zhuǎn)發(fā)出去的系統(tǒng)調(diào)用被打斷,人們當(dāng)然希望找到一種方法來避免這些中斷事件。

          Masking non-fatal signals

          為了解決這個問題,Dhillon 的 patch set 為 SECCOMP_IOCTL_NOTIF_RECV(監(jiān)控進(jìn)程接受通知會用這個)ioctl() 增加了一個新的 flag(SECCOMP_USER_NOTIF_FLAG_WAIT_KILLABLE)。如果在向監(jiān)督進(jìn)程發(fā)出通知時設(shè)置了這個 flag,目標(biāo)進(jìn)程就會進(jìn)入 "killable" wait 狀態(tài),這意味著 fatal signal 仍可以被正常傳遞處理,但任何其他 signal 都會被屏蔽掉,直到監(jiān)控進(jìn)程處理完成之后再說。因此,non-fatal signal 將不會再打斷系統(tǒng)調(diào)用(此時監(jiān)控進(jìn)程正在處理這些系統(tǒng)調(diào)用)。

          請注意,如果在監(jiān)控進(jìn)程收到通知之前,就出現(xiàn)了一個 non-fatal signal 到達(dá),那么目標(biāo)進(jìn)程的這個系統(tǒng)調(diào)用仍將像從前一樣被打斷。此時這個 seccomp 通知將會被取消掉,如果監(jiān)控進(jìn)程試圖去讀取該通知的話,會收到一個 error。在這種情況下,最終結(jié)果就像系統(tǒng)調(diào)用一開始就沒有發(fā)生過一樣。不過,一旦通知被送達(dá),系統(tǒng)調(diào)用就會得到執(zhí)行,并一直運行到結(jié)束。這個改動相對較小,它解決了這個問題,盡管這個解決方案是在使用 seccomp()和用戶空間通知功能時可能會給 Go 的搶占機制增加不確定時長的 delay 為代價的。delay 其實本來也正是搶占機制想要預(yù)防的,但這個 delay 至少是在監(jiān)控進(jìn)程的控制之下,而且應(yīng)該不會是無限延遲。

          截至目前,這組 patch set 已經(jīng)發(fā)布了兩次,它沒有收到多少回應(yīng)。這可能表明,到目前為止很少有人看過它,這對于用戶空間 API 的安全相關(guān)的改動來說,不是一個好兆頭。在得到更多 review 之前,這項工作不太可能取得進(jìn)展,使用 seccomp()和用戶空間通知功能的 Go 用戶也將繼續(xù)忍受當(dāng)前的困擾。

          全文完
          LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。

          歡迎分享、轉(zhuǎn)載及基于現(xiàn)有協(xié)議再創(chuàng)作~

          長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~



          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕高清无码视频 | 黄色免费国产 | 91av影音先锋 | 中国色情一级视频 | 欧美午夜性爱 |