1. 程式人生 > >80x86保護模式下特權級轉移

80x86保護模式下特權級轉移

80386搞的這個保護模式,最大的特點就是加入了安全檢查,不再像真實模式下那樣,程式程式碼可以隨意jmp,隨意call了,受到了特權級的約束,關於特權級的概念我看無數的資料,各種大牛的解釋,反覆理解了好多次,這回我要再次整理一下。

CPL:當前CPU正在處理的程式碼段的特權級,存放在當前cs暫存器和ss暫存器的低2位;

DPL:要跳轉過去的目的碼段的特權級,規定了能訪問該段的特權級的標準,存放在該段的段描述中;

RPL:請求特權級,是判斷一個跳轉是不是合法的第二個標準,也是必須的要有的,下文詳細解釋,存放在目標段選擇子中的低2位;

資料段堆疊段:訪問這兩個段的判斷,比較簡單,只要當前正在處理的程式碼段的CPL和RPL特權級都高於目標資料段或目標堆疊段的特權級就可以了,沒什麼好講的。



一致程式碼段:可以理解成核心中的程式碼,但是屬於核心中受保護級別比較低的那些程式碼,是核心專門提供給使用者程式訪問和呼叫的程式碼,它雖然是OS核心中的程式碼,特權級高,但允許被低特權級的使用者程式碼訪問。不過僅僅是被訪問,當前的CPL還是使用者程式碼段的CPL,不要期望核心程式碼的CPL,哈哈。

非一致程式碼段:這個就是普通使用者程式中定義的段,section/segment等,它只允許同特權級的程式碼相互跳轉。即使用者程式碼只能跳轉到使用者程式碼,核心程式碼也只能跳轉到核心程式碼。不要以為核心程式碼可以訪問使用者程式碼和使用者資料,這樣就很容易被搗蛋的人利用,使核心執行壞蛋寫的噁心程式碼,導致核心崩潰。



================================================================================
                                下面詳細解答一些我在學習時遇到的問題
================================================================================
1.有CPL和DPL進行判斷不就可以了嗎?為什麼還需要一個RPL呢?
     因為當低許可權的使用者程式碼去呼叫高許可權的OS核心程式碼來訪問一個目標段時,由於CPU執行的是OS核心程式碼,所以CPL變成了作業系統的CPL,如果沒有RPL,那麼此時CPL許可權比任何使用者程式碼的許可權都高,也就可以去訪問任何資料,這就不安全了。所以引入RPL,讓它去代表訪問許可權,因此在檢查CPL的同時,也會檢查RPL.一般來說如果RPL的數字比CPL大(許可權比CPL的低),那麼RPL會起決定性作用。


2.程式碼跳轉有幾種方式都是用什麼指令?
      程式碼跳轉大概可以分為2類,一類是直接跳轉或者叫普通跳轉,一類是通過門描述符來跳轉。用jmp和call可以實現跳轉

3.什麼是跳轉什麼是訪問?
      跳轉特指去執行目的碼段的程式碼去了,除了進行特權級檢查判斷是否合法外,還會改變CPL
      訪問只是指去資料段或者堆疊段取資料,還是執行當前的程式碼,只進行特權級檢測,不改變CPL

4.直接跳轉的特性
      直接跳轉不發生特權級的躍遷,即不改變CPL,具體如下:

程式碼段 要求 特權變化
一致程式碼段 CPL >= DPL ,RPL不檢查,也說是一致程式碼段描述符中的DPL規定可以轉移到一致的程式碼段的最內層特權級(3級可以轉移到0級,而0級只能轉移到0級)。一致程式碼段描述符內DPL的這種解釋,正好與正常的DPL的解釋相反。這是為了提供對應用程式的共享支援,而不要求改變特權級。 轉跳後程序的CPL = 轉跳前程式的CPL
非一致程式碼段 CPL = DPL & RPL<= DPL 轉跳後程序的CPL = 轉跳前程式的CPL

5.利用門描述符跳轉的特性
     這種方式,可以改變CPL。通過門描述符和call指令,可以實現從低特權級到高特權級的轉移,具體如下:
程式碼段 要求 特權變化
一致程式碼段 CPL >= DPL ,RPL不檢查 因為RPL被清0,所以事實上永遠滿足RPL <= DPL,這一點與普通跳轉一致,適用於JMP和CALL。
轉跳後程序的CPL = 轉跳前程式的CPL,因此特權級沒有發生躍遷。
非一致程式碼段(JMP) CPL = DPL (RPL被清0,不檢查)
,若不滿足要求則程式引起異常。
轉跳後程序的CPL = DPL,
因為前提是CPL=DPL,所以轉跳後程序的CPL = DPL不會改變CPL的值,特權級也沒有發生變化。如果訪問時不滿足前提CPL=DPL,則引發異常。
非一致程式碼段(CALL) CPL >= DPL(RPL被清0,不檢查),若不滿足要求則程式引起異常。 轉跳後程序的CPL = DPL,
當條件CPL=DPL時,程式跳轉後CPL=DPL,特權級不發生躍遷;當CPL>DPL時,程式跳轉後CPL=DPL,特權級發生躍 遷,這是我們當目前位置唯一見到的使程式當前執行優先順序(CPL)發生變化的跳轉方法,即用CALL指令+呼叫門方式跳轉,且目的碼段是非一致程式碼段。


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

      從呼叫門中讀取到目的碼的段選擇子和地址偏移後,我們當前掌握的資訊又回到了先前,和普通跳轉站在了同一條起跑線上(普通跳轉一開始就得到了目的碼的段選擇子和地址偏移),有所不同的是,此時,CPU會將讀到的目的碼段選擇子中的RPL清0,即忽略了呼叫門中程式碼段選擇子的RPL的作用。完成這一步後,CPU開始對當前程式的CPL,目的碼段選擇子的RPL(事實上它被清0後總能滿足要求)以及由目的碼選擇子指示的目的碼段描述符中的DPL進行特權級檢查,並根據情況進行跳轉。