2012-05-16 27 views
0

我有一個設備驅動程序,它允許用戶空間應用程序使用ioctl機制執行各種操作。作爲初始ioctl調用的一部分返回的是對應用程序在其他ioctl調用中提供的用戶空間應用程序應該不透明的句柄。從IOCTL調用返回一個內核句柄 - 安全問題?

在驅動程序內部,句柄是內核空間中某個控制/上下文塊的地址。如果可以信任該應用程序來忠實地回傳處理,那麼一切都很好。值得關注的是,如果應用程序是惡意的並且傳回一些驅動程序然後將其轉換爲適當的指針類型並取消引用它的任意句柄。

我在想的一個健全性檢查是與PAGE_OFFSET比較,如果小於(確保地址至少指向內核內存),則拒絕。如果頁面錯誤我認爲在內核空間中不合法呢?一個簡單的方案可能是檢查句柄是否先前返回到用戶空間,但是搜索開銷可能很高(因爲可能有很多這些句柄)。

有沒有一個強大而有效的方法來驗證句柄?任何幫助表示讚賞。

謝謝。

回答

2

切勿接受來自不可信程序的指針。
在您的代碼和其他代碼上(例如,使用您查看進程不能訪問的內存),無法完成這些攻擊。

有辦法驗證它,但它們很複雜或昂貴。例如:
1.將所有句柄放在一個數組中。驗證指針是否在數組內,並正確對齊。但是,你可以使用數組索引作爲句柄。
2.掃描您的句柄數據庫,並將指針與用戶給出的指針進行比較。不要取消引用該句柄,直到在數據庫中找到該句柄。但是,再次使用一些ID來查找,而不是指針,可以簡化它。

有可能需要驗證更多的東西:
1.亞歷克斯評論,如果有幾個可能的手柄類型,請確認您得到正確的類型(即防止h = get_handle_typeA(); use_handle_typeB(h))。
2.確保每個進程只使用它創建的句柄。所以一個進程將無法猜測句柄的值,並希望得到一個有效的值。

+0

更重要的是,如果有不同類型的「手柄」(比方說,A型和對象的對象的類型B),他們也需要進行類型檢查(即,你確實會得到一個類型A句柄,你期望得到一個類型A句柄)。如果某些句柄或其他輸入參數是相關的,則需要對它們進行驗證,這不僅有助於將它們視爲單獨的實體時纔有意義,而且它們在所呈現的組合中是有意義的。此外,返回指針會削弱地址隨機化方案,並可以簡化成功的利用創建。我會使用索引,而不是指針。 –

0

爲什麼你甚至需要一個句柄?打開文件一個手柄,你可以在那裏藏匿自己的私人數據,例如:

static long your_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 
{ 
     struct your_struct *p = f->private_data; 
     ... 
+0

我仍然需要某種方法將「arg」映射到整個「struct your_struct」內的特定私有數據(因爲存在大量私有子數據實例)。我使用每個句柄類型的RB樹數據庫來驗證「arg」句柄。 – ravi

+0

所以你的意思是應用程序可以多次調用初始ioctl並獲得幾個不同的句柄?如果是這樣,那麼你會需要一些方法來採取arg,並找出它在your_struct中的哪個句柄。 在這一點上,儘管只需更改API以便每個打開文件有一個句柄,並且如果應用程序需要多個句柄,它可以多次打開您的設備。 – mpe