3.2.3節:特權級

原來看第3.2.3節的時候,感覺很難的。爲什麼會感覺難呢? 因爲這一節談到的特權級別關係比較複雜,不容易弄清楚。這次重看一次這一節後,進行了一點小結,這才感覺比較清楚了。
      這一節的主要內容可以用下面這個表格來描述。

目標代碼段

Jmp指令

Call指令

直接調用

通過調用門

一致碼段

CPL>=DPL,不檢查RPL

可以跳轉到相同或者更高特權級別執行

CPL<=DPL_G,RPL<=DPL_G

CPL>=DPL

訪問調用門的規則同訪問數據段,即調用門只能被特權級別不低於其DPL(DPL_G)的代碼訪問。可以跳轉到相同或者更高特權級別執行。

非一致碼段

RPL<=CPL=DPL

只能跳轉到同特權級別的代碼段

 

1.  三種特權級別

CPL:當前特權級別。當前正在運行的代碼所處的特權級別,保存在CS和SS的低2位中。

DPL:描述符特權級別,即段描述符中DPL字段的值,是與描述符相關的特權級別。

RPL:請求特權級別,即用於訪問代碼、數據或者堆棧的段選擇子低2位的值。

注意特權級別的表示:有0至3這4個特權級別,0級最高,3級最低,即數字大則特權級別低。表中CPL、RPL、DPL等都是代表數字的。

2. 一致碼段和非一致碼段

(1)一致碼段:無論採用哪種方式跳轉到一致碼段,CPL都不改變(不變化爲目標代碼段的DPL),也即在加載目標代碼段選擇子時,只加載高14位,表示CPL的低2位保持不變。

(2)非一致碼段:無論採用哪種方式跳轉到非一致碼段,CPL都發生改變,也即在加載目標代碼段選擇子時,將整個選擇子放入到CS中。

“一致”的意思就是:代碼段被調用執行時不使用自己的描述符的DPL,而採用調用者特權級別,CS的低2位保持不變,與調用者特權級別保持一致。

是不是一致碼段由描述符中的相應位標誌確定(參看47到49頁的表格)。

3. Jmp與Call

Jmp指令僅僅進行執行流程的跳轉,不會保存返回地址。

Call指令在進行流程跳轉前會保存返回地址,以便在跳轉目標代碼中可以使用ret指令返回到call指令的下一條指令處繼續執行。執行段內跳轉時,只保存EIP;如果是段間跳轉,還保存CS。

對於使用Call指令(無論是直接調用還是通過調用門)進行的跳轉,如果跳轉後特權級別將發生改變(總是從低到高,從上述第2點知道,只有跳轉到非一致碼段時纔會發生特權級別變化),則執行call指令前必須準備好任務狀態段TSS。跳轉過程是:(1)保存調用者的SS和ESP到被調用者堆棧中(2)調用參數先保存在調用者堆棧中,然後被複制到被調用者堆棧中(3)當前CS和EIP被保存到被調用者堆棧中。在通過call進行的有特權級別變化的跳轉中,堆棧會發生切換,這時要保存當前堆棧指針(SS:ESP),而當前指令指針(CS:EIP)保存到新的堆棧(被調用者堆棧)中,這是與沒有特權級別變化的跳轉不同的。沒有特權級別變化時,不需要保存SS:ESP,不存在調用參數的複製,不存在堆棧切換。

4. ret和retf

這兩個指令的功能都是調用返回。

(1) ret在返回時只從堆棧中取得EIP;retf中的字母f表示far,即段間轉移返回,要從堆棧中取得EIP和CS。

(2)兩個指令都可以帶參數,表示發生過程調用時參數的個數,返回時需要從堆棧中退出相應個數的參數

(3)恢復CS時,如果發現將發生特權級別變化(當前CS的低2位不等於從堆棧中取得的新的CS值的低2位。從上述第2點知道,只有跳轉到非一致碼段時纔會發生特權級別變化,那麼,也只有從非一致碼段返回時纔會發生特權級別返回),則還要從調用者堆棧中取得ESP和SS恢復到相應寄存器中,也即恢復調用者堆棧。

5. 任務狀態段TSS

爲避免相互干擾,要求不同特權級別的代碼運行時使用不同的堆棧,也就是在特權級別發生改變時必須切換堆棧段。0、1、2特權級別的堆棧指針保存在TSS中,在跳轉到相應級別時從TSS中取出相應的堆棧指針進行堆棧切換。因爲只有從低特權級別跳轉到高特權級別時才需要從TSS中取得新的堆棧指針,所以TSS中不存在最低特權級別3的堆棧指針。

 

綜上所述,所有的複雜只有一點:僅僅在通過調用門從低特權級別跳轉到高特權級別的非一致碼段時,纔會發生CPL改變,才需要先準備好TSS,纔會發生堆棧切換(在調用前從TSS中取得新的堆棧指針;調用返回時從被調用者堆棧中取得原堆棧指針進行恢復)。

CPL、RPL、DPL的區別


CPL(Current   Privilege   Level) 當前(代碼)特權級。在保護模式下,CS寄存器、SS寄存器中分別存放着代碼段、堆棧段的選擇子。CPL在CS、SS的第0、1位(第0位到15位)中。CPL一般情下等於所裝載的段的特權級。對於一致代碼段來說,CPL不會隨着所裝載的段的特權級而改變。

DPL(Descriptor   Privilege   Level) 描述符特權級在每個存儲段(數據段、代碼段、堆棧段)描述符、門(調用門、任務門、中斷門、陷阱門)描述符、任務狀態段(TSS)描述符的第5個字節(第0字節到第7字節)的第5、6位(第0位到第7位)中。DPL主要用來與CPL比較,來確定當前代碼是否能夠訪問相應的段。

RPL(Request   Privilege   Level) 選擇子特權級,在每個選擇子的第0、1位(第0位到15位)中。RPL主要用來改寫CPL,當進行段訪問的時候,取CPL和RPL中數值大的一個(即取權限小的一個)。如:CPL爲0,要訪問的調用門DPL爲2,但是選擇子的RPL爲3,此時不可以訪問調用門。

發佈了287 篇原創文章 · 獲贊 216 · 訪問量 175萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章