在IA32的操作系統中,段被分為了4個特權級,分別為0-3級,有時候我們也叫做ring0-ring3,其中,數值越小特權級越高。如下圖所示:
圖中,核心代碼和數據所在的段的特權級都比較高,一般在ring0,而用戶程序所在的段的特權級較低,一般在ring3。當低特權級的任務試圖在未被允許的情況下訪問高特權級的段時,將會產生常規保護錯誤。
而處理器是如何區分所在段的特權級,進而對其進行保護的呢?這就不得不提到CPL、DPL和RPL三者了。但是在開始之前,我們需要先了解一下一致代碼段和非一致代碼段。
一致代碼段和非一致代碼段
在操作系統中,我們有些高特權級的代碼是希望被低特權級的程序所訪問的,比如一些庫函數,於是我們將這些高特權級代碼放在一個叫做一致代碼段的段里。而有些高特權級的代碼,我們並不想讓低特權級的程序所訪問,於是我們把他們放在一個叫做非一致代碼段的段里。具體來說,當通過call或者jmp指令轉移到其它段時(即訪問其他段),當轉移的目標是一個優先級更高的一致代碼段時,我們是可以進行訪問的,但是當前的特權級會被延續下去;當轉移的目標是一個優先級更高的非一致代碼段時,這時的訪問會引起常規保護錯誤(除非使用調用門或任務門)。
總結來說:
-
一致代碼段:由系統(高特權級)共享給低特權級的程序的代碼所在的段,主要有下面兩點限制:
- 高特權級程序不能訪問低特權級的數據
- 低特權級的程序可以訪問高特權級的代碼,但是特權級不會改變,還是保持低特權級程序的特權級
-
非一致代碼段:為了避免被低特權級程序所訪問而保護起來的代碼段,主要有一點限制:
- 只允許同級之間訪問
-
另外,數據段都是非一致的
所遵循的規則如下圖所示:
CPL
CPL全稱Current Privilege Level,顧名思義,CPL代表的是當前執行的任務和程序的特權級。它存儲在cs和ss的第0位和第1位上。一般情況下,CPL等於代碼所在段的特權級,當程序轉移到不同的代碼段時,處理器將改變CPL的值。
但是當訪問一致代碼段時,並不會改變CPL,正如一致代碼段中所說,一致代碼段可以被低特權級的程序所訪問,但是並不會改變特權級,所以也就不會改變CPL,這就是與上面加粗的“一般情況”相對的“非一般情況”。
DPL
DPL全程為Descriptor Privilege Level,它代表段或者門的特權級。他被存儲在段描述符或者門描述符屬性中的DPL字段上。
當當前的代碼段試圖訪問一個段或者門時,DPL將會和CPL以及段或者門選擇子的RPL相比較,而對於段或者門類型的不同,比較規則也不同,具體如下:
- 數據段:如果訪問的是一個數據段,DPL代表訪問此段的最低特權級,即只有CPL <= DPL(數值上),才有權限訪問。
- 非一致代碼段(不使用調用門):DPL代表訪問此段的特權級。即只有DPL = RPL,才有權限訪問。
- 調用門:DPL規定了當前執行的任務和程序可以訪問此調用門的最低特權級,即要CPL <= DPL
- 一致代碼段和非一致代碼段(使用調用門訪問):DPL規定了訪問此段的最高特權級。即只有CPL >= DPL,才有權限訪問。
- TSS:DPL規定了訪問此TSS的最低特權級。
總結一下就是:
- 在 數據段、調用門、TSS中,DPL代表最低特權級,訪問要求:CPL <= DPL
- 在 不使用調用門訪問的非一直代碼段時,訪問要求: CPL = DPL
- 在 一致代碼段和使用調用門訪問的非一致代碼段中,DPL 代表最高特權級,訪問要求:CPL >= DPL
RPL
RPL全稱是Requested Privilege Level。RPL保存在段選擇子的第0位和第1位上。我們在上文說了當一個段訪問另一個段時,CPL與DPL的比較規則,但是僅僅比較CPL和DPL是不夠的,處理器還要通過檢查RPL來確定能否訪問另一個段。
操作系統往往用RPL來避免低特權級應用程序訪問高特權級段內的數據,即便提出訪問請求的段有足夠的特權級,如果RPL不夠也是不行的,當RPL的值比CPL大的時候,RPL將起決定性作用。也就是說,只有當CPL和RPL都小於要訪問的數據段的DPL時,才有權限訪問該數據段。關於為什么引入RPL的討論還是比較復雜的,此處不再深入探討。
完
參考:
- 《一個操作系統的實現》 於淵