2014-05-06 104 views
2

我必須編寫LKM,它攔截一些系統調用。 解決辦法是:sys_call_table的符號的安全卸載內核模塊

  1. 查找地址,檢查是否地址是正確的(檢查例如該sys_call_table的[__ NR_close]指向SYS_CLOSE的地址)
  2. 禁止中斷在CR0
  3. 禁用WP位
  4. 變化sys_call_table的[__ NR_close]我自己的功能
  5. 啓用WP位
  6. 允許中斷。加載模塊工作正常。

但是,模塊的安全卸載呢?

考慮到我將sys_call_table恢復到原始狀態並卸載模塊的情況 - 如果內核仍在其他CPU的其他進程的系統調用上下文中執行代碼,該怎麼辦?我會在內核模式下發生頁面錯誤(因爲模塊代碼段的頁面不可用,因爲模塊已被卸載)。 共享資源是sys_call_table中的條目。如果我可以訪問受鎖定保護的條目 - 那麼我可以安全地卸載我的模塊。

但是,由於內核系統調用處理程序沒有任何這種鎖(例如/ x86/kernel/entry_32.S) - 這意味着沒有安全的方式卸載我的模塊?這是真的嗎?

UPDATE1

我需要得到有關文件的信息訪問舊內核(其中fanotify(2)不可用),從2.4內核版本開始。我需要這些信息才能通過防病毒引擎執行訪問掃描。

+3

你可能想弄清楚爲什麼你要首先攔截/掛鉤系統調用。這裏的人們會認爲你要麼解決XY問題,要麼寫惡意軟件。 – tangrs

回答

1

你說得對,沒有安全的方式卸載你的模塊,一旦你這樣做了。這就是爲什麼以這種方式替換/打包系統調用表條目的原因之一。

在最新版本中,sys_call_table不是導出符號 - 至少部分是爲了阻止這件事。

理論上可以支持更強大的系統調用替換機制,但內核維護人員認爲整個概念充滿錯誤和困惑的潛力,他們拒絕支持它。 (網絡搜索會顯示幾個很久以前的辯論關於Linux內核郵件列表上的這個問題。)

(說到此處爲一個確切幾年前誰使用相同的技術。)

當然你也可以無論如何。然後,你可以「冒險」卸載你的模塊 - 因此可能導致內核恐慌(但當然它可能會工作99%的時間)。或者,您無法允許您的模塊完全卸載(需要重新啓動才能升級或卸載)。