疑難雜症:Linux下殺毒軟件CPU佔用率爲何持續升高

 

最近筆者遇到這樣一個相對比較疑難的事件,某個在Linux下運行的殺毒軟件啓動後在,某些情況下CPU佔用率會持續升高,而且在交易量較高的情況下極易復現。而奇怪的是我們之前已經對於殺毒軟件的CPU使用率進行了上限限定,但是出現這樣異常事件表明殺毒軟件並沒有執行之前設定的資源佔用控制策略,CPU使用率始終持續異常偏高。

分析下來這個事件還是很有借鑑意義的,由於此事件涉及一些敏感信息,因此具體不便公開的細節也就不透露了,僅把可以公開的情況梳理一下,供各位讀者參考。首先我們先明確一下鉤子(hook)函數的概念,簡單來講這就是一類改變其它函數行爲的函數,舉個簡單的例子,我每次進入會議室的時候都是直接推開門然後進入的,但是現在我在進入門之前要先向向會議室主持人申請,得到許可才能進入,那麼向主持人申請的動作就被attatch到了進入會議室這個動作上了,整個過程就可以簡單的理解爲hook。

我們知道在Linux下想改變系統的行爲,需要代碼運行的內核態,比如kprobe,fsnotify等機制,提供了root用戶hook到內核代碼的權限,並最終將自己的代碼段attach到內核調用中。

CPU使用率過高的原因分析

經確認這款殺毒軟件的CPU佔用率控制模型如下圖,其守護模塊會定時判斷agent資源使用情況,如果超標則將釋放掃描模塊使用的CPU與內存資源。

 

但是具體分析下來這樣的機制在IO頻繁的系統上存在缺陷,具體原因掃描模塊在內核態下執行時下無法釋放CPU資源。分析過程如下:

經確認殺毒軟件agent在行爲監測時,在進程將文件加載到內存前,會使用hook技術對於open等系統調用進行attach,確定加載的文件不含惡意代碼後,才允許進程加載該文件。因此在Linux內核找到系統調用的attatch機制的相關代碼進行分析。

1.系統調用中sys_open函數使用fsnotify機制對於attach注入到sys_open函數的進程進行回調通知。(具體代碼位置在kernel/open.c)

 

2.attach到sys_open的代碼執行過程始終是處於內核態中的,同時Linux的fsnotify機制也會加內核鎖,在內核鎖解鎖前該進程無法釋放CPU,不能被打斷。(具體代碼位置在kernel/fsnotify.c)

 

殺毒軟件掃描模塊attach內核函數的機制與fsnotify類似,因此其掃描模塊在進行行爲檢測時會在內核態執行且不能被打斷,而在系統中原本就有大量IO操作的情況下,守護模塊將失效。

 

 

在POC測試時,該殺毒軟件在文件掃描時其CPU佔用率始終不高,這其中的原因是由於在掃描文件時該殺毒軟件全部運行於用戶態下,不存在內核態運行的情況,因此守護模塊可正常調節CPU使用情況。

解決方案淺析

先說一下實測結論在加入attach延時操作後,IO吞吐量巨幅下降。經訪照該殺毒軟件的機制進行實測模擬,在內核sys_open函數attach加入延時操作,觀察對於系統IO的影響。

 

在加入將內核sys_open延時一倍的操作後,我在華爲的在鯤鵬4C/8G的平臺實測上,每秒鐘文件打開、關閉文件操作的次數,由每秒867次的鋒值下降到了72次,出現了90%以上的下降。這可能與內核鎖的雪崩效應有關。

經確認在之前的版本之所以沒有出現問題,是由於當守護進程在確認CPU調節失效後會對自身agent進行整體自毀操作(modelu_exit),因此不會觸發類似於CPU佔用率持續升高的案例。那麼針對這樣的機制具體的解決方案如下:

  1. 對於內核態代碼執行,加入全局併發數限制,對於所有執行在內核態的掃描線程,進行全局併發鎖限制,具體併發數的設置還需要進行進一步測試後得出結果,在鯤鵬4C/8G的平臺上測試最大併發數設置爲4基本不會對系統正常調用產生影響,建議先將系統CPU個數設定爲最大併發數,進行測試。
  2. 對於對於內核態代碼執行加入每秒執行次數限制,對於所有執行在內核態的掃描線程,進行全局的執行次數限制,加入執行令牌,每秒執行次數不應該大於最大IO數量的10%,在此方案下也可避免對於系統正常調用的影響。
  3. 加入掃描任務調度機制:避免在內核態執行耗時的掃描任務,只是快速收到系統的open調用指令後,將相關的掃描任務加入調試隊列,就立刻返回,在用戶態統一執行掃描任務,也可避免由於代碼長時間運行於內核態造成的問題。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章