保護模式特權層級DPL,RPL,CPL 之間的聯絡和區別

來源:互聯網
上載者:User

著作權聲明:轉載時請以超連結形式標明文章原始出處和作者資訊及本聲明
http://myjfm.blogbus.com/logs/57252310.html

---------------------

 

CPL是當前進程的權限等級(Current Privilege Level),是當前正在執行的代碼所在的段的特權級,存在於cs寄存器的低兩位。
RPL說明的是進程對段訪問的請求許可權(Request Privilege
Level),是對於段選擇子而言的,每個段選擇子有自己的RPL,它說明的是進程對段訪問的請求許可權,有點像函數參數。而且RPL對每個段來說不是固定

的,兩次訪問同一段時的RPL可以不同。RPL可能會削弱CPL的作用,例如當前CPL=0的進程要訪問一個資料區段,它把段選擇符中的RPL設為3,這樣
雖然它對該段仍然只有特權為3的存取權限。
DPL儲存在段描述符中,規定訪問該段的權限等級(Descriptor Privilege Level),每個段的DPL固定。
當進程訪問一個段時,需要進程特權級檢查,一般要求DPL >= max {CPL, RPL}

下面打一個比方,中國官員分為6級國家主席1、總理2、省長3、市長4、縣長5、鄉長6,假設我是當前進程,層級總理(CPL=2),我去聊城市
(DPL=4)考察(呵呵),我用省長的層級(RPL=3
這樣也能嚇死他們:-))去訪問,可以吧,如果我用縣長的層級,人家就不理咱了(你看看電視上的微服私訪,呵呵),明白了吧!為什麼採用RPL,是考慮到
安全的問題,就好像你明明對一個檔案用有寫入權限,為什麼用唯讀開啟它呢,還不是為了安全!

[轉者註:以下插播: http://www.oldlinux.org/oldlinux/viewthread.php?tid=3627 ]

"CPU中只有DPL和CPL,沒有儲存RPL的地方。"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~這個說法有問題,RPL存放在段選擇子中,而段選擇子可以載入到段寄存器中(可見部分); 我們知道,寄存器(包括段寄存器)物理上是在CPU裡的。

我的問題是,當要在不同特權級的程式碼片段切換時,在特權檢查中,DPL, CPL, RPL分別存取在什麼地方?
~~~~~~~~~~~~~~~~~~~~~~~~~~~DPL存放在段/門描述符中,RPL存放在段選擇子中,CPL即是當前CS中段選擇子的RPL。
在不同特權級的代碼切換時,如果我們頭腦裡分別有原程式碼片段的DPL/CPL和新程式碼片段的DPL/RPL兩個情境,也許就不會有那麼多困惑了。

如果說此時當前的CPL是CS段寄存器中的RPL,那麼當用CS段寄存器載入另一個特權級的程式碼片段時,就需要更新CS段寄存器,使得它指向目標程式碼片段描述
符,並且要標記其中的RPL位,這樣不就把原來標記當前程式碼片段特權層級(CPL)給掩蓋掉了嗎。那麼如何去實現這個判斷(DPL >
max(CPL,RPL)  ?這個是我最最疑惑的地方
~~~~~~~~~~~~~~~~~~~~~~~~~~沒錯,CPL就是CS中的RPL。你之所以感到困惑,是因為誤解了特權級檢查的時機——不是在載入
了CS之後才進行這個檢查,而是在載入的同時就由CPU中的特殊並行硬體進行新舊兩份DPL/RPL的比較檢查,檢查通過才會真正載入,否則觸發異常。另外,DPL >
max(CPL,RPL)  是當前代碼訪問資料區段時的特權級檢查條件,不是你說的程式碼片段切換的特權級檢查條件;程式碼片段切換的特權級檢查條件要分好幾種情
況的,具體件上面趙博的回複。

在INVISIBLE DESCRIPTOR裡,亦會有個CPL--by sjlung
~~~~~~~~~~~~~~~~~~~~~~~~這個純粹是誤解,段寄存器不可見部分緩衝的是段描述符,那裡面沒有CPL只有DPL。再說一遍,CPL即是CS中段選擇子部分(可見部分!)的RPL。

 

[插播完畢]-------------------------------------------------------

 

 

全面解釋:
--------------------------------------------------------------------------------

RPL是段選擇子裡面的bit 0和bit 1位組合所得的值,但這裡要首先搞清楚什麼是段選擇子,根據Intel
的檔案(IA-32 IntelR Architecture Software Developer's Manual, Volume
3System Programming Guide)它是一個16Bit identifier (原文:A segment selector
is a 16-bit identifier for a segment). 但 identifier 又是什麼. identifier
可以是一個變數的名字( An identifier is a name for variables), 簡單的說它可以就是一般意義的變數. 這裡
16-bit identifier for a segment
可以就是一個一般意義的16bit變數但同時要求對它的值解釋的時候必須跟據Intel定下的規則---也就是bit 0和bit
1位的組合值就是RPL等等…
因此在程式裡如果有需要的話你可以聲明一個或者多個變數來代表這些段選擇子,這樣的話你的程式在某一時刻就可以有很多段選擇子,當然有那麼多段選擇子就有
那麼多RPL.可以這樣說程式有多少個是RPL是你怎樣看待你自己聲明的變數. |
程式的CPL(CS.RPL)是CS register 裡bit 0和bit 1 位組合所得的值.在某一時刻就只有這個值唯一的代表程式的CPL. 

而DPL是段描述符中的特權級, 它的本意是用來代表它所描述的段的特權級.
一個程式可以使用很多段(Data,Code,Stack)也可以只用一個code段等.在正常的情況下當程式的環境建立好後,段描述符都不需要改變
-----當然DPL也不需要改變. 

一、對資料區段和堆棧段訪問時的特權級控制:

要求訪問資料區段或堆棧段的程式的CPL≤待訪問的資料區段或堆棧段的DPL,同時選擇子的RPL≤待訪問的資料區段或堆棧段的DPL,即程式訪問資料區段或堆棧段要遵循一個

準則:只有相同或更高特權級的代碼才能訪問相應的資料區段。這裡,RPL可能會削弱CPL的作用,訪問資料區段或堆棧段時,預設用CPU和RPL中的最小特權
級去訪問資料區段,所以max {CPL, RPL} ≤ DPL,否則訪問失敗。

二、對程式碼片段訪問的特權級控制(代碼執行權的特權轉移):

讓我們先來記一些“定律”:
所有的程式轉跳,CPU 都不會把段選擇子的RPL賦給轉跳後程式的CS.RPL. .

轉跳後程式的CPL(CS.RPL)只會有下面的倆種可能
轉跳後程式的CPL(CS.RPL) = 轉跳前程式的CPL(CS.RPL) 
或
轉跳後程式的CPL(CS.RPL) = 轉跳後程式的CodeDescriptor.DPL

以 Call 為例(只能跳到等於當前特權級或比當前特權級更高的段):
怎樣決定這兩種選擇,這就要首Crowdsourced Security Testing道轉跳後程式的段是一致程式碼片段還是非一致程式碼片段.其實也很簡單,規則如下:
如果能成功轉跳到一致程式碼片段, 轉跳後程式的CPL(CS.RPL) = 轉跳前程式的CPL(CS.RPL),(轉跳後程式的CPL繼承了轉跳前程式的CPL)
如果能成功轉跳到非一致程式碼片段,
轉跳後程式的CPL(CS.RPL) =轉跳後程式的Descriptor.DPL。(轉跳後程式的CPL變成了該程式碼片段的特權級.我在前面提到DPL是
段描述符中的特權級, 它的本意是用來代表它所描述的段的特權級)怎樣才能成功轉跳啦?

這裡有四個重要的概念:

1).段的保護觀念是高特權級不找低特權級辦事,低特權級找高特權級幫忙,相同的一定沒問題.(這樣想邏輯是沒錯,事實對不對就不知道.)也就是縣長不找 鄉長,鄉長不求農民,反過來農民求鄉長,鄉長找縣長.這個概念是最重要的。
2) 一致程式碼片段的意義:
讓客人很方便的利用主人(一致程式碼片段)的東西為自己辦事.但客人這身份沒有改變NewCS.RPL=OldCS.RPL所以只能幫自己辦事。比方說鄉長有
一頭牛,農民可以借來幫自己種田,但不能種別人的田.但是如果你是鄉長當然可以種鄉裡所有的田。
3)
非一致程式碼片段的意義:主人(非一致程式碼片段)可以幫客人但一定是用自己的身份NewCS.RPL=
DestinationDescriptorCode.DPL這裡可能有安全的問題,
搞不好很容易農民變縣長。主人太頑固了一定要堅持自己的身份,有什麼方法變通一下,來個妥協好不好。好的,它就是RPL的用處。

4) RPL:
它讓程式有需要的時候可以表示一個特權級更低的身份Max(RPL,CPL)而不會失去本身的特權級CPL(CS.RPL),有需要的時候是指要檢查身份
的時候。事實上RPL跟段本身的特權級DPL和當前特權級CPL沒有什麼關係,因為RPL的值在成功轉跳後並不賦給轉跳後的CS.RPL。
還是要問怎樣才能成功轉跳啦?這裡分兩種情況:

普通轉跳(沒有經過Gate
這東西):即JMP或Call後跟著48位全指標(16位段選擇子+32位地址位移),且其中的段選擇子指向程式碼片段描述符,這樣的跳轉稱為直接(普通)跳
轉。普通跳轉不能使特權級發生躍遷,即不會引起CPL的變化,看下面的詳細描述:

目標是一致程式碼片段:
要求:CPL(CS.RPL)>=DestinationDescriptorCode.DPL ,其他RPL是不檢查的。
轉跳後程式的CPL(NewCS.RPL) = 轉跳前程式的CPL( OldCS.RPL)
上面的安排就是概念1,2的意思,此時,CPL沒有發生變化,縱使它執行了特權級(DPL)較高的代碼。若訪問時不滿足要求,則發生異常。
目標是非一致程式碼片段:
要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL≤CPL(CS.RPL)
轉跳後程式的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL

上面的安排就是概念3的意思和部分1的意思----主人(非一致程式碼片段)只幫相同特權級的客人做事。因為前提是CPL=DPL,所以轉跳後程式的
CPL(NewCS.RPL) =
DestinationDescriptorCode.DPL不會改變CPL的值,特權級(CPL)也沒有發生變化。如果訪問時不滿足前提
CPL=DPL,則引發異常。

通過調用門的跳轉:當段間轉移指令JMP和段間轉移指令CALL後跟著的目標段選擇子指向一個調用門描述符時,該跳轉就是利用調用門的跳轉。這時如果選擇子後跟著32位的地址位移,也不會被cpu使用,因為調用門描述符已經記錄了目標代碼的位移。使用調門進行的跳轉比普通跳轉多一個步驟,即在訪問調用門描述符時要將描述符當作一個資料區段來檢查存取權限,要求指示調用門的選擇子的RPL≤門描述符DPL,同時當前程式碼片段CPL≤門描述符DPL,就如同訪問資料區段一樣,要求訪問資料區段的程式的CPL≤待訪問的資料區段的DPL,同時選擇子的RPL≤待訪問的資料區段或堆棧段的DPL。只有滿足了以上條件,CPU才會進一步從調用門描述符中讀取目標程式碼片段的選擇子和地址位移,進行下一步的操作。

從調用門中讀取到目標代碼的段選擇子和地址位移後,我們當前掌握的資訊又回到了先前,和普通跳轉站在了同一條起跑線上(普通跳轉一開始就得到了目標代碼的

段選擇子和地址位移),有所不同的是,此時,CPU會將讀到的目標程式碼片段選擇子中的RPL清0,即忽略了調用門中程式碼片段選擇子的RPL的作用。完成這一步後,CPU開始對當前程式的CPL,目標程式碼片段選擇子的RPL(事實上它被清0後總能滿足要求)以及由目標代碼選擇子指示的目標程式碼片段描述符中的DPL進行特權級檢查,並根據情況進行跳轉,具體情況如下:

目標是一致程式碼片段:
要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL ,RPL不檢查,因為RPL被清0,所以事實上永遠滿足RPL≤DPL,這一點與普通跳轉一致,適用於JMP和CALL。
轉跳後程式的CPL(NewCS.RPL) = 轉跳前程式的CPL( OldCS.RPL),因此特權級沒有發生躍遷。

目標是非一致程式碼片段:
當用JMP指令跳轉時:
要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL<=
CPL(CS.RPL)(事實上因為RPL被清0,所以RPL≤CPL總能滿足,因此RPL與CPL的關係在此不檢查)。若不滿足要求則程式引起異常。
轉跳後程式的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL
因為前提是CPL=DPL,所以轉跳後程式的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL不會改變CPL的值,特權級也沒有發生變化。如果訪問時不滿足前提CPL=DPL,則引發異常。
當用CALL指令跳轉時:
要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL(RPL被清0,不檢查),若不滿足要求則程式引起異常。
轉跳後程式的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL
當條件CPL=DPL時,程式跳轉後CPL=DPL,特權級不發生躍遷;當CPL>DPL時,程式跳轉後
CPL=DPL,特權級發生躍遷,這是我們當目前位置唯一見到的使程式當前執行憂先級(CPL)發生變化的跳轉方法,即用CALL指令+調用門方式跳轉,
且目標程式碼片段是非一致程式碼片段。


總結:以上介紹了兩種情況的跳轉,分別是普通跳轉和使用調用門的跳轉,其中又可細分為JMP跳轉和CALL跳轉,跳轉成功已否是由CPL,RPL和DPL

綜合決定的。所有跳轉都是從低特權級代碼向同級或更高特權級(DPL)跳轉,但保持當前執行特權級(CPL)不變,這裡有點難於區別為什麼說向高特權級跳轉,又說特權級沒變,這裡“高特權級”是指目標程式碼片段描述符的DPL,它規定了可以跳轉到該段代碼的最高特權級;而後面的CPL不變才真正說明了特權級未發生躍遷。我們可以看到,只有用CALL指令+調用門方式跳轉,且目標程式碼片段是非一致程式碼片段時,才會引起CPL的變化,即引起代碼執行特權級的躍遷,這是目前得知的改變執行特權級的唯一辦法,如果各位讀者還知道其他方法請留言告訴我。

 

 

---------------------------------------------------

一致程式碼片段,非一致程式碼片段

一致位:在描述符屬性中TYPE(包含4個二進位位)欄位的第2位。
當 S=1 時TYPE中的4個二進位位情況:
     3       2       1       0
   執行位 一致位 讀寫位 訪問位
執行位:置1時表示可執行,置0時表示不可執行;
一致位:置1時表示一致碼段,置0時表示非一致碼段;
讀寫位:置1時表示可讀可寫,置0時表示唯讀;
訪問位:置1時表示已訪問,置0時表示未訪問。

所以一致程式碼片段和非一致程式碼片段的意思就是指這個一致位是否置1,置1就是一致程式碼片段,置0就為非一致程式碼片段 。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.