亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

《Orange’s 一個(gè)操作系統(tǒng)的實(shí)現(xiàn)》3.保護(hù)模式5-

系統(tǒng) 1868 0

學(xué)習(xí)過(guò)程中遇到一個(gè)對(duì)保護(hù)模式總結(jié)很好的Blog,轉(zhuǎn)來(lái)分享一下。

先說(shuō)下特權(quán)級(jí)的概念,在保護(hù)模式下,系統(tǒng)依靠特權(quán)級(jí)來(lái)實(shí)施代碼和數(shù)據(jù)的保護(hù),相當(dāng)于權(quán)限啦。特權(quán)級(jí)共有4個(gè)級(jí)別,0,1,2,3,數(shù)字越小表示權(quán)限越高。如圖:?

保護(hù)模式 對(duì)CPL,RPL,DPL的總結(jié) - xuejianxinokok - xuejianxinokok的博客
???
較為核心的代碼和數(shù)據(jù)放在較高(靠?jī)?nèi))的層級(jí)中,處理器用此來(lái)防止較低特權(quán)的任務(wù)在不被允許的情況下訪問(wèn)處于高特權(quán)級(jí)的段。為了防止概念混淆,我們不用特權(quán)級(jí)大小來(lái)說(shuō)明,改為內(nèi)層(高),外層(低)來(lái)講。

特權(quán)級(jí)有3種 CPL , DPL RPL ,每個(gè)都是有4個(gè)等級(jí)。?
我對(duì)他們的 關(guān)系 理解是這樣:一般來(lái)說(shuō), CPL 代表當(dāng)前代碼段的權(quán)限,如果它想要去訪問(wèn)一個(gè)段或門(mén),首先要看看對(duì)方的權(quán)限如何,也就是檢查對(duì)方的 DPL ,如果滿足當(dāng)前的權(quán)限比要訪問(wèn)的權(quán)限高,則有可能允許去訪問(wèn),有些情況我們還要檢查?
選擇子的權(quán)限,即 RPL ,因?yàn)槲覀兺ㄟ^(guò)選擇子:偏移量的方式去訪問(wèn)一個(gè)段,這算是一個(gè)訪問(wèn)請(qǐng)求動(dòng)作,因此?
稱為請(qǐng)求訪問(wèn)權(quán)限 RPL (Requst Privilege Level)。當(dāng)請(qǐng)求權(quán)限也滿足條件,那么訪問(wèn)就被允許了。
?

CPL (Current Privilege Level)?
CPL 是當(dāng)前執(zhí)行的任務(wù)的特權(quán)等級(jí),它存儲(chǔ)在CS和SS的第0位和第1位上。(兩位表示0~3四個(gè)等級(jí))?
通常情況下, CPL 等于代碼所在段的特權(quán)等級(jí),當(dāng)程序轉(zhuǎn)移到不同的代碼段時(shí),處理器將改變 CPL 。?
注意:在遇到 一致代碼 段時(shí),情況特殊, 一致代碼 段的特點(diǎn)是:可以被 等級(jí)相同或者更低特權(quán)級(jí) 的代碼訪問(wèn),當(dāng)處理器訪問(wèn)一個(gè)與當(dāng)前代碼段 CPL 特權(quán)級(jí)不同的 一致代碼 段時(shí), CPL 不會(huì)改變。?

DPL (Descriptor Privilege Level) ?
表示門(mén)或者段的特權(quán)級(jí),存儲(chǔ)在門(mén)或者段的描述符的 DPL 字段中。正如上面說(shuō)的那樣,當(dāng)當(dāng)前代碼段試圖訪問(wèn)一個(gè)段或者門(mén)時(shí),其 DPL 將會(huì)和當(dāng)前特權(quán)級(jí) CPL 以及段或門(mén)的選擇子比較,根據(jù)段或者門(mén)的類(lèi)型不同, DPL 的含義不同:?
??? 1.數(shù)據(jù)段的 DPL :規(guī)定了訪問(wèn)此段的最低權(quán)限。比如一個(gè)數(shù)據(jù)段的 DPL 是1,那么只有運(yùn)行在 CPL 為0或1的程序才可能訪問(wèn)它。為什么說(shuō)可能呢?因?yàn)檫€有一個(gè)比較的因素是 RPL 。訪問(wèn)數(shù)據(jù)段要滿足有 效特權(quán)級(jí)別 (上述) 高于數(shù)據(jù)段的 DPL .?
??? 2.非 一致代碼 段的 DPL (不使用調(diào)用門(mén)的情況): DPL 規(guī)定訪問(wèn)此段的特權(quán),只有 CPL 與之相等才有可能訪問(wèn)。?
??? 3.調(diào)用門(mén)的 DPL ,規(guī)定了程序或任務(wù)訪問(wèn)該門(mén)的最低權(quán)限。與數(shù)據(jù)段同。?
??? 4. 一致代碼 段和通過(guò)調(diào)用門(mén)訪問(wèn)的非 一致代碼 段, DPL 規(guī)定訪問(wèn)此段的最高權(quán)限。?
???? 比如一個(gè)段的 DPL 為2,那么 CPL 為0或者1的程序都無(wú)法訪問(wèn)。?
?? 5. TSS的 DPL ,同數(shù)據(jù)段。?

RPL (Rquest Privilege Level)
?
RPL 是通過(guò)選擇子的低兩位來(lái)表現(xiàn)出來(lái)的( 這么說(shuō)來(lái),CS和SS也是存放選擇子的,同時(shí) CPL 存放在CS和SS的低兩位上,那么對(duì)CS和SS來(lái)說(shuō),選擇子的 RPL =當(dāng)前段的 CPL )。處理器通過(guò)檢查 RPL CPL 來(lái)確認(rèn)一個(gè)訪問(wèn)是否合法。即提出訪問(wèn)的段除了有足夠的特權(quán)級(jí) CPL ,如果 RPL 不夠也是不行的(有些情況會(huì)忽略 RPL 檢查)。?
為什么要有 RPL ?
操作系統(tǒng)往往通過(guò)設(shè)置 RPL 的方法來(lái)避免低特權(quán)級(jí)的應(yīng)用程序訪問(wèn)高特權(quán)級(jí)的內(nèi)層數(shù)據(jù)。?
例子情景:調(diào)用者調(diào)用操作系統(tǒng)的某過(guò)程去訪問(wèn)一個(gè)段。?
當(dāng)操作系統(tǒng)(被調(diào)用過(guò)程)從應(yīng)用程序(調(diào)用者)接受一個(gè)選擇子時(shí),會(huì)把選擇子的 RPL 設(shè)置稱調(diào)用者的權(quán)限等級(jí),于是操作系統(tǒng)用這個(gè)選擇子去訪問(wèn)相應(yīng)的段時(shí)(這時(shí) CPL 為操作系統(tǒng)的等級(jí),因?yàn)檎谶\(yùn)行操作系統(tǒng)的代碼),處理器會(huì)使用調(diào)用者的特權(quán)級(jí)去進(jìn)行特權(quán)級(jí)檢查,而不是正在實(shí)施訪問(wèn)動(dòng)作的操作系統(tǒng)的特權(quán)級(jí)( CPL ),這樣操作系統(tǒng)就不用以自己的身份去訪問(wèn)(就防止了應(yīng)用去訪問(wèn)需要高權(quán)限的內(nèi)層數(shù)據(jù),除非應(yīng)用程序本身的權(quán)限就足夠高)。?
那么 RPL 的作用就比較明顯了:因?yàn)橥粫r(shí)刻只能有一個(gè) CPL ,而當(dāng)?shù)蜋?quán)限的應(yīng)用去調(diào)用擁有至高權(quán)限的操作系統(tǒng)的功能來(lái)訪問(wèn)一個(gè)目標(biāo)段時(shí),進(jìn)入操作系統(tǒng)代碼段時(shí) CPL 變成了操作系統(tǒng)的 CPL ,如果沒(méi)有 RPL ,那么權(quán)限檢查的時(shí)候就會(huì)用 CPL ,而這個(gè) CPL 權(quán)限比應(yīng)用程序高,也就可能去訪問(wèn)需要高權(quán)限才能訪問(wèn)的數(shù)據(jù),這就不安全了。所以引入 RPL ,讓它去代表訪問(wèn)權(quán)限,因此在檢查 CPL 的同時(shí),也會(huì)檢查 RPL .一般來(lái)說(shuō)如果 RPL 的數(shù)字比 CPL 大(權(quán)限比 CPL 的低),那么 RPL 會(huì)起決定性作用。?
說(shuō)這么多不明白都不行啦~真累?
下面是引用的一個(gè)超棒的關(guān)于權(quán)限控制的總結(jié):?
引用地址 ?
還有一篇文章 在此 。?

■ 數(shù)據(jù)訪問(wèn)時(shí)的權(quán)限check

一、 訪問(wèn)data segment時(shí)(ds、es、fs 及gs)?
1、 程序指令要訪問(wèn)數(shù)據(jù)時(shí),data segment selector 被加載進(jìn) data segment register(ds、es、fs 和 gs)前,處理器會(huì)進(jìn)行一系列的權(quán)限檢查,通過(guò)了才能被加載進(jìn)入segment register。處理器分為兩步進(jìn)行檢查:?
★? CPL (當(dāng)前程序運(yùn)行的權(quán)限級(jí)別)與 RPL (位于selector中的? RPL )作比較,并設(shè)置有效權(quán)限級(jí)別為低權(quán)限的一個(gè)。?
★ 得出的有效權(quán)限級(jí)別與 DPL (segment descriptor 中的 DPL )作比較,有效權(quán)限級(jí)別高于 DPL ,那么就通過(guò)。低于就不允許訪問(wèn)。
?
2、舉個(gè)例子:?
如果: CPL ?= 3、 RPL ?= 2、 DPL ?= 2。那么
EPL =? CPL ?>? RPL ??? CPL ?:? RPL ;?
if (EPL <=? DPL ) {?
/* 允許訪問(wèn) */?
} else {?
/* 失敗,#GP 異常生產(chǎn),執(zhí)行異常 */
}
?
或者:?
if (( CPL ?<=? DPL ) && ( RPL ?<=? DPL )) {?
/* 允許訪問(wèn) */?
} else {?
/* 失敗,#GP 異常生產(chǎn),執(zhí)行異常 */?
}

?? 也就是要訪問(wèn)目標(biāo)data segment,那么必須要有足夠的權(quán)限,這個(gè)足夠的權(quán)限就是:當(dāng)前運(yùn)行的權(quán)限級(jí)別及選擇子的請(qǐng)求權(quán)限級(jí)別要高于等于目標(biāo)data segment的權(quán)限級(jí)別。

?

二、 訪問(wèn)stack segment時(shí)?
1、 該問(wèn)stack 時(shí)的權(quán)限檢查更嚴(yán)格, CPL 、 RPL DPL 三者必須相等才能通過(guò)該問(wèn)請(qǐng)求。

2、 舉個(gè)例子:

?

?

if ( CPL ?==? RPL ?&&? RPL ?==? DPL ?&&? CPL ?==? DPL ) {?
????? /* 允許訪問(wèn) */?
} else {?
???? /* 失敗,#GP 異常生產(chǎn),執(zhí)行異常 */?
}

?

也就是說(shuō)每個(gè)權(quán)限級(jí)別有相對(duì)應(yīng)的statck segment。不能越權(quán)訪問(wèn),即使高權(quán)限訪問(wèn)低權(quán)限也是被拒絕的

?

?

?

■ 控制權(quán)的轉(zhuǎn)移及權(quán)限檢查。

?? 權(quán)限檢查的4個(gè)要素:

★? CPL :處理器當(dāng)前運(yùn)行的級(jí)別,也就是:當(dāng)前 CS 的級(jí)別,在 CS 的 BIT0 ~ Bit1

★? DPL :訪問(wèn)目標(biāo)代碼段所需的級(jí)別。定義在 segment descriptor 的? DPL ?域中

★? RPL : 通過(guò) selector 進(jìn)行訪問(wèn)時(shí),selector 內(nèi)定義的級(jí)別。

★ conforming/nonconforming:目標(biāo)代碼屬于 nonconforming 還是 conforming 定義在segment descritptor 的 C 標(biāo)志位中

x86 的各方面檢查依賴于目標(biāo)代碼段是 nonconforming(不一致) 還是 conforming (一致) ?類(lèi)型


一、 直接轉(zhuǎn)移(far call 及 far jmp)?
??? 1、 直接轉(zhuǎn)移定義為不帶gate selector或 taskselector的遠(yuǎn)調(diào)用。當(dāng)執(zhí)行一條 call cs:eip 或 jmp cs:eip 指令時(shí),cs 是目標(biāo)代碼段的selector,處理器在加載指令操作數(shù)中的cs進(jìn)cs register前,要進(jìn)行一系列的權(quán)限檢查,控制權(quán)的轉(zhuǎn)移權(quán)限分兩部分,根據(jù)目標(biāo)代碼段descriptor定義的兩種情況:?
1)、nonconforming target code segment?
★ 直接轉(zhuǎn)移后的權(quán)限級(jí)別是不能必改變的。因此, CPL ?必須要等于目標(biāo)代碼段的? DPL 。?
★ 要有足夠的請(qǐng)求權(quán)限進(jìn)行訪問(wèn)。因此,目標(biāo)代碼段選擇子的 RPL ?<=? CPL

2)、conforming target code segment?
★ conforming code segment 允許訪問(wèn)高權(quán)限級(jí)別的代碼。這里只需檢查? CPL ?>=? DPL ?即可, RPL ?忽略不檢查。?
★ 轉(zhuǎn)移后 CPL 不會(huì)改變。

?? 2、 以上兩步通過(guò)后,處理器加載目標(biāo)代碼段的CS 進(jìn)入CS register,但權(quán)限級(jí)別不改變,繼而 RPL 被忽略。

★ 處理器根據(jù)CS selector在相應(yīng)的descriptor table 找到 code segment descriptor。CS 的Bit2(TI域) 指示在哪個(gè)descriptor table 表查找,CS.TI = 0 時(shí)在GDT查找,CS.TI = 1時(shí)在LDT 查找。?
★ CS的Bit15~Bit3 是selector index 值,處理器基于GDT或LDT來(lái)查找segment descriptor。具體是:GDTR.base 或 LDTR.base + CS.SI × 8 得出code segment descritpro。?
★ 處理器自動(dòng)加載code segment descriptor 的 base address、segment limit及attribute 域進(jìn)入 CS register的相應(yīng)的隱藏域。?
★ 轉(zhuǎn)到CS.base + eip 處執(zhí)行指令

總結(jié):用代碼形式來(lái)說(shuō)明直接轉(zhuǎn)移 call cs:eip 這條指令?
例: call 1a:804304c (即cs = 1a, eip = 804304c)

?

?

target_cs = 1a;?
target_eip = 0x0804304c;?
CPL ?= CS. RPL ;??????????? /* 當(dāng)前執(zhí)行的代碼段的權(quán)限級(jí)別就是 CPL ?*/?
RPL ?= target_cs. RPL ;???? /* 目標(biāo)段 selector 的低3位是 RPL ?*/?
target_si = target_cs.SI;??? /* 目標(biāo)段 selector 的索引是Bit15~Bit3 */?
target_ti = target_cs.TI;??? /* 目標(biāo)段selector的描述符表索引是Bit2 */
CODESEG_DESCRIPTOR target_descriptor;

if (target_ti == 0) { /* target_cs.TI為0 就是參考到 GDT(全局描述符表) */?
/* 以GDTR寄存器的base 為基地址加上selector的索引乘以8即得出目標(biāo)?
?????? 段描述符,目標(biāo)描述符的 DPL 就是目標(biāo)段所需的訪問(wèn)權(quán)限 */?
??? target_descriptor = GDTR.base + target_si * 8

} else {?????????????? /* 否則就是參考 LDT (局部描述符表)*/?
??? /* 以 LDTR寄存器的base 為基地址得出目標(biāo)段描述符 */

target_descriptor = LDTR.base + target_si * 8;?
}
?
DPL ?= target_descriptor. DPL ;???? /* 獲取 DPL ?*/
?
if (target_descriptor.type & 0x06) { /* conforming */?
if ( CPL ?>=? DPL ) {?? /* 允許執(zhí)行高權(quán)限代碼 */?
???? /* go ahead */?
??? } else {?
???? /* 引發(fā) #GP 異常 */?
??? goto DO_GP_EXCEPTION;?
}?

} else {????????????????? /* nonconforming */?
??? if ( CPL ?==? DPL ?&&? RPL ?<=? CPL ) {???
??????? /* go ahead */?
??? } else {?
??????? /* 引發(fā) #GP 異常 */?
?????? goto DO_GP_EXCEPTION;?
??? }?
???
}
?
/****** go ahead … …******/?
CS = target_cs;?????????? /* 加載目標(biāo)段CS 進(jìn)入 CS 寄存器 */?
EIP = target_eip;??????? /* 加載目標(biāo)指令EIP 進(jìn)入 EIP 寄存器 */?
???????????????? /* 當(dāng)前執(zhí)行權(quán)限? CPL ?不改變 */

goto target_descriptor.base + target_eip; /* 跳轉(zhuǎn)到目標(biāo)地址執(zhí)行 */
?

DO_GP_EXCEPTION:???? /* 執(zhí)行 #GP異常點(diǎn) */?
?????????? … …

?

?

?

二、 使用call gate 進(jìn)行控制權(quán)的轉(zhuǎn)移?
使用call gate進(jìn)行轉(zhuǎn)移控制,目的是建立一個(gè)利用gate進(jìn)行向高權(quán)限代碼轉(zhuǎn)移的一種保護(hù)機(jī)制。gate符相當(dāng)一個(gè)進(jìn)入高權(quán)限代碼的一個(gè)通道。


對(duì)于指令 call cs:eip 來(lái)說(shuō):?
★ 目標(biāo)代碼的selector是一個(gè)門(mén)符的選擇子。用來(lái)獲取門(mén)描述符。?
★ 門(mén)描述符含目標(biāo)代碼段的selector及目標(biāo)代碼的偏移量。?
★ 目標(biāo)代碼的ip值被忽略。因?yàn)殚T(mén)符已經(jīng)提供了目標(biāo)代碼的偏移量。?

1、 權(quán)限的檢查?
★ 首先,必須要有足夠的權(quán)限來(lái)訪問(wèn)gate符,所以: CPL ?<= DPLg(門(mén)符的 DPL )且: RPL ?<= DPLg?
★ 進(jìn)前代碼向高權(quán)限代碼轉(zhuǎn)移,所以,對(duì)于conforming類(lèi)型的代碼段來(lái)說(shuō),必須 CPL ?>= DPLs(目標(biāo)代碼段的 DPL )?
★ 對(duì)于nonconforming類(lèi)型代碼段來(lái)說(shuō),必須 CPL ?= DPLs?
★ call 指令改變當(dāng)前權(quán)限,而jmp指令不改變當(dāng)前權(quán)限。

總結(jié):

?

?

if (( CPL ?<= DPLg) && ( RPL ?<= DPLg)) { /* 足夠的權(quán)限訪問(wèn)門(mén)符 */?
if (target.C == CONFORMING) {?? /* 目標(biāo)代碼屬于 conforming類(lèi)型 */?
??? /* 向高權(quán)限級(jí)別代碼轉(zhuǎn)移控制 */?
??? if ( CPL ?>= DPLs) {?
?????????? /* 通過(guò)訪問(wèn) */?
????? } else {?
??????????? /* 失敗,#Gp異常發(fā)生 */?
??? }?

??? } else {?????????????? /* 目標(biāo)代碼屬于 nonconforming 類(lèi)型 */?
?????? /* 平級(jí)轉(zhuǎn)移 */?
??? if ( CPL ?== DPLs) {?
??????????? /* 通過(guò)訪問(wèn) */?
??????? } else {?
???????????? /* 失敗,#GP 異常發(fā)生 */?
??????? }?
}

} else {?? /* 沒(méi)有足夠權(quán)限訪問(wèn)門(mén)符 */?
/* #GP 異常發(fā)生 */?
}

?

?

2、 控制權(quán)的轉(zhuǎn)移?
指令:call 1a:804304c (其中1a是call gate selector)

?

?

gate_selector = 0x1a;?????????????? /* call gate selector */?
RPL ?= gate_selector. RPL ;??????????? /* 門(mén)符選擇子 RPL ?*/?
CPL ?= CS. RPL ;???????????????????? /* 當(dāng)前代碼段低3位是 CPL */
CALLGATE_DESCRIPTOR call_gate_descriptor;????? /* 門(mén)符的描述符 */?
CODESEG_DESCRIPTOR target_cs_descritpor;????? /* 目標(biāo)代碼段的描述符 */
call_gate_si = gate_selector.SI;????? /* 門(mén)符 selector 的索引 */?
call_gate_ti = gate_selector.TI;????? /* 門(mén)符selector的描述符表索引 */?
??????????????????????????????????????????????????????????????????????????
/* 獲取call gate descriptor */?
if (call_gate_ti == 0) {????? /* TI為0 就是參考到 GDT(全局描述符表) */?
/* 以GDTR寄存器的base 為基地址加上selector的索引乘以8即得出門(mén)符的描述符,門(mén)符的 DPL 就是門(mén)符的訪問(wèn)權(quán)限 */?
??? call_gate_descriptor = GDTR.base + call_gate_si * 8;?
} else {?????????????? /* 否則就是參考 LDT (局部描述符表)*/?
???? /* 以 LDTR寄存器的base 為基地址得出目標(biāo)段描述符 */?
call_gate_descriptor = LDTR.base + call_gate_si * 8;?
}

/* 獲取 target code segment descriptor */
target_cs = call_gate_descriptor.selector;??? /* 獲取門(mén)符的目標(biāo)代碼段選擇子 */?
target_cs_si = target_cs.SI;???????? /* 目標(biāo)代碼段的索引 */?
target_cs_ti = target_cs.TI;????????????????? /* 目標(biāo)代碼描述符表索引 */
if (target_cs_ti == 0)?
??? target_cs_descriptor = GDTR.base + target_cs_si * 8;?
else?
??? target_cs_descriptor = LDTR.base + target_cs_si * 8;

DPLg = call_gate_descriptor. DPL ;???? /* 獲取門(mén)符的 DPL ?*/?
DPLs = target_cs_descriptor. DPL ;???? /* 獲取目標(biāo)代碼段的 DPL ?*/

if ( CPL ?<= DPLg &&? RPL ?<= DPLg) {?? /* 有足夠權(quán)限訪問(wèn)門(mén)符 */?
???? if (target_cs_descriptor.type & 0x06) { /* conforming */?
????????? if ( CPL ?>= DPLs) {?
???????????????? /* 允許訪問(wèn)目標(biāo)代碼段 */?
????????? } else {?
???????????????? /* #GP 異常產(chǎn)生 */?
????????? }?
???? } else if ( CPL ?== DPLs) { /* nonconforming */?
???????? /* 允許訪問(wèn)目標(biāo)代碼段 */?
???? } else {?
????????? /* 拒絕訪問(wèn),#GP 異常發(fā)生 */?
????????? goto DO_GP_EXCEPTION;?
???? }?
} else { /* 無(wú)權(quán)限訪問(wèn)門(mén)符 */?
???? /* 拒絕訪問(wèn), #GP異常發(fā)生 */?
???? goto DO_GP_EXCEPTION;?
}
?
/* 允許訪問(wèn) */?
current_CS = target_cs;?????? /* 加載目標(biāo)代碼段進(jìn)入CS 寄存器 */?
current_CS. RPL ?= DPLs;??????? /* 改變當(dāng)前執(zhí)行段權(quán)限 */?
current_EIP = call_gate_descriptor.offset;?? /* 加載EIP */
?
/* 跳轉(zhuǎn)到目標(biāo)代碼執(zhí)行 */?
/* goto current_CS:current_EIP */?
goto target_cs_descriptor.base + call_gate_descriptor.offset;
?
return;
?
DO_GP_EXCEPTION:???????? /* 執(zhí)行異常 */

?

?

?

三、 使用中斷門(mén)或陷井門(mén)進(jìn)行轉(zhuǎn)移?
?? 中斷門(mén)符及陷井門(mén)必須存放在IDT中,IDT表也可以存放call gate。

1、 中斷調(diào)用時(shí)的權(quán)限檢查?
?? 用中斷門(mén)符進(jìn)行轉(zhuǎn)移時(shí),所作的權(quán)限檢查同call gate相同,區(qū)別在于intterrupt gate 轉(zhuǎn)移不需要檢查 RPL ,因?yàn)?,沒(méi)有 RPL 需要檢查。?
★ 必須有足夠的權(quán)限訪問(wèn)門(mén)符, CPL ?<= DPLg?
★ 向同級(jí)權(quán)限代碼轉(zhuǎn)移時(shí), CPL ?== DPLs,向高權(quán)限代碼轉(zhuǎn)移時(shí), CPL ?> DPLs

總結(jié)

?

?

if ( CPL ?<= DPLg) { /* 有足夠權(quán)限訪問(wèn)門(mén)符 */?
??? if ( CPL ?>= DPLs) {?
??????? /* 允許訪問(wèn)目標(biāo)代碼頭 */?
??? } else {?
???????? /* 失敗,#GP異常發(fā)生 */?
??? }

} else {?
/* 失敗,#GP異常發(fā)生 */?
}

?

2、 控制權(quán)的轉(zhuǎn)移?
?? 發(fā)生異?;蛑袛嗾{(diào)用時(shí)?
★ 用中斷向量在中斷描述符表查找描述符:中斷向量×8,然后加上IDT表基址得出描述符表。?
★ 從查找到的描述符中得到目標(biāo)代碼段選擇子,并在相應(yīng)的GDT或LDT中獲取目標(biāo)代碼段描述符。?
★ 目標(biāo)代碼段描述符的基址加上門(mén)符中的offset,確定最終執(zhí)行入口點(diǎn)。


中斷或陷井門(mén)符轉(zhuǎn)移的總結(jié):?
例: int 0x80 指令發(fā)生的情況

?

?

vector = 0x80;?
INTGATE_DESCRIPTOR gate_descriptor = IDTR.base + vector * 8;?
CODESEG_DESCRIPTOR target_descriptor;?
TSS tss = TR.base;?????????????? /* 得到TSS 內(nèi)存塊 */?
DPLg = gate_descriptor. DPL ;?
target_cs = gate_descriptor.selector;
?
if ( CPL ?<= DPLg) {??????????? /* 允許訪問(wèn)門(mén)符 */

if (target_cs.TI == 0) {?? /* index on GDT */?
??? target_descriptor = GDTR.base + target_cs.SI * 8;?
} else {????????????? /* index on LDT */?
target_descriptor = LDTR.base + target_cs.SI * 8;?
??? }

DPLs = target_descriptor. DPL ;?


if ( CPL ?> DPLs) {???? /* 向高權(quán)限代碼轉(zhuǎn)移 */?

??? /* 根據(jù)目標(biāo)代碼段的 DPL 值來(lái)選取相應(yīng)權(quán)限的stack結(jié)構(gòu) */?
??? switch (DPLs) {?
??? case 0 :???? /* 假如目標(biāo)代碼處理0級(jí),則選0級(jí)的stack結(jié)構(gòu) */?
???????????? SS = tss.ss0;?
???????????? ESP = tss.esp0;?
???????????? break;?
??????? case 1:?
???????????? SS = tss.ss1;?
??????????? ESP = tss.esp1;?
???????????? break;?
??????? case 2:?
???????????? SS = tss.ss2;?
???????????? ESP = tss.esp2;?
???????????? break;?
??? }

?????? /* 以下必須保護(hù)舊的stack結(jié)構(gòu),以便返回 */?
??? *--esp = SS;????????? /* 將當(dāng)前SS入棧保護(hù) */?
??? *--esp = ESP;???????? /* 將當(dāng)前ESP入棧保護(hù) */?

} else if ( CPL ?== DPLs) {?
???? /* 同級(jí)轉(zhuǎn)移,繼續(xù)向下執(zhí)行 */?
} else {?
??? /* 失敗,#GP異常產(chǎn)生,轉(zhuǎn)去處理異常 */?
}?


*--esp = EFLAGS;????????? /* eflags 寄存器入棧 */?

???? /* 分別將 NT、NT、RF及VM標(biāo)志位清0 */?
EFLAGS.TF = 0;????????????
EFLAGS.NT = 0;?
EFLAGS.RF = 0;?
EFLAGS.VM = 0;?

if (gate_descriptor.type == I_GATE32) { /* 假如是中斷門(mén)符 */?
EFLAGS.IF = 0;????????? /* 也將IF標(biāo)志位清0,屏蔽響應(yīng)中斷 */?
???? }?
?????????????
???? *--esp = CS;????????????? /* 當(dāng)前段選擇子入棧 */?
???? *--esp = EIP;???????????? /* 當(dāng)前EIP 入棧 */
CS = target_selector;????? /* 加載目標(biāo)代碼段 */?
CS. RPL ?= DPLs;??????????? /* 改變當(dāng)前執(zhí)行權(quán)限級(jí)別 */?
EIP = gate_descriptor.offset; /* 加載進(jìn)入EIP */?

/* 執(zhí)行中斷例程 */?
goto target_descritptor.base + gate_descriptor.offset;?

} else {?
/* 失敗,#GP 異常產(chǎn)生,轉(zhuǎn)去處理異常 */?
}

?

?

?

■ 堆棧的切換


控制權(quán)發(fā)生轉(zhuǎn)移后,處理器自動(dòng)進(jìn)行相應(yīng)的堆棧切換。?
1、 當(dāng)轉(zhuǎn)向到同權(quán)限級(jí)別的代碼時(shí),不會(huì)進(jìn)行堆棧級(jí)別的調(diào)整,也就是不進(jìn)行堆棧切換。?
2、 當(dāng)轉(zhuǎn)向高權(quán)限級(jí)別時(shí),將發(fā)生相應(yīng)級(jí)別的堆棧切換。從TSS塊獲取相應(yīng)級(jí)別的stack結(jié)構(gòu)。

例:假如當(dāng)前運(yùn)行級(jí)別 CPL 為2時(shí),發(fā)生了向0級(jí)代碼轉(zhuǎn)移時(shí):

?

?

TSS tss = TR.base;???????? /* 從TR寄存器中獲取TSS 塊 */?
CPL ?= 2;???????????????? /* 當(dāng)前運(yùn)行級(jí)別為2 級(jí)*/?
DPL ?= 0;???????????????? /* 目標(biāo)代碼需要級(jí)別為 0 級(jí) */

/* 根據(jù)目標(biāo)代碼需要的級(jí)別進(jìn)行選取相應(yīng)的權(quán)限級(jí)別的stack結(jié)構(gòu) */?
switch ( DPL ) {?
case 0:?
???? SS = tss.ss0;?
???? ESP = tss.esp0;?
???? break;?
case 1:?
???? SS = tss.ss1;?
???? ESP = tss.esp1;?
???? break;?
case 2:?
???? SS = tss.ss2;?
???? ESP = tss.esp2;?
???? break;?
}
?
*--esp = SS;????????? /* 保存舊的stack結(jié)構(gòu) */?
*--esp = ESP;
?
/* 然后再作相當(dāng)?shù)谋4婀ぷ鳎绫4鎱?shù)等 */
*--esp = CS;???????? /* 最后保存返回地址 */?
*--esp = EIP;

?

?

?

?

■ 控制權(quán)的返回


當(dāng)目標(biāo)代碼執(zhí)行完畢,需要返回控制權(quán)給原代碼時(shí),將產(chǎn)生返回控制權(quán)行為。返回控制權(quán)行為,比轉(zhuǎn)移控制權(quán)行為簡(jiǎn)單得多。因?yàn)?,一切條件已經(jīng)在交出控制權(quán)之前準(zhǔn)備完畢,返回時(shí)僅需出棧就行了。

1、 near call 的返回?
近調(diào)用情況下,段不改變,即CS不改變,權(quán)限級(jí)別不改變。僅需從棧中pop返回地址就可以了。


2、 直接控制權(quán)轉(zhuǎn)移的返回(far call或far jmp)?
?? 直接控制權(quán)的轉(zhuǎn)移是一種不改變當(dāng)前運(yùn)行級(jí)別的行為。只是發(fā)生跨段的轉(zhuǎn)移。這時(shí),CS被從棧中pop出來(lái)的CS值加載進(jìn)去,處理器會(huì)檢查 CPL 與這個(gè)pop出來(lái)的選擇子中的 RPL 進(jìn)行檢查,相符則返回。不相符則發(fā)生 #GP異常。?
???
總結(jié):假如當(dāng)前運(yùn)行的目標(biāo)代碼執(zhí)行完畢后,將要返回。這時(shí) CPL 為2

?

?

CPL ?= 2;????? /* 當(dāng)前代碼運(yùn)行級(jí)別為 2 */?
… …?
EIP = *esp++;?? /* pop出原EIP 值 */?
CS = *esp++;??? /* pop出原CS值 */
?
if ( CPL ?== CS. RPL ) {???
/* CS. RPL ?代表是原來(lái)的運(yùn)行級(jí)別,與 CPL 相符則返回 */?
return ;?
} else {?
/* #GP異常產(chǎn)生,執(zhí)行異常處理 */?
}

?

?

3、 利用各種門(mén)符進(jìn)行向高權(quán)限代碼轉(zhuǎn)移后的返回?
從高權(quán)限代碼返回低權(quán)限代碼,須從stack中pop出原來(lái)的stack結(jié)構(gòu)。這個(gè)stack結(jié)構(gòu)屬于低權(quán)限代碼的stack結(jié)構(gòu)。然后直接pop 出原返回地址就可以了。?

總結(jié):

CPL ?= 0;??????? /* 當(dāng)前運(yùn)行級(jí)別為 0 級(jí) */?
… …?
EIP = *esp++;??? /* 恢復(fù)原地址 */?
CS = *esp++;???? /* 恢復(fù)原地址及運(yùn)行級(jí)別 */

ESP = *esp ++;???? /* 恢復(fù)原stack結(jié)構(gòu) */?
SS = *esp++;???? /* 恢復(fù)原stack 結(jié)構(gòu),同時(shí)恢復(fù)了原stack訪問(wèn)級(jí)別 */
?
return ;?????? /* 返回 */
?
************************************************************************************
3、DPL,RPL,CPL 之間的聯(lián)系和區(qū)別是什么?RPL和CPL是必須相同嗎?如果相同,為什么要釆用兩個(gè)而不改用一個(gè)呢??



答:特權(quán)級(jí)是保護(hù)模式下一個(gè)重要的概念,CPL,RPL和DPL是其中的核心概念,查閱資料無(wú)數(shù),總結(jié)如下:?
? 簡(jiǎn)單解釋?zhuān)?

--------------------------------------------------------------------------------?

? CPL是當(dāng)前進(jìn)程的權(quán)限級(jí)別(Current Privilege Level),是當(dāng)前正在執(zhí)行的代碼所在的段的特權(quán)級(jí),存在于cs寄存器的低兩位。?
? RPL說(shuō)明的是進(jìn)程對(duì)段訪問(wèn)的請(qǐng)求權(quán)限(Request Privilege Level),是對(duì)于段選擇子而言的,每個(gè)段選擇子有自己的RPL,它說(shuō)明的是進(jìn)程對(duì)段訪問(wèn)的請(qǐng)求權(quán)限,有點(diǎn)像函數(shù)參數(shù)。而且RPL對(duì)每個(gè)段來(lái)說(shuō)不是固定的,兩次訪問(wèn)同一段時(shí)的RPL可以不同。RPL可能會(huì)削弱CPL的作用,例如當(dāng)前CPL=0的進(jìn)程要訪問(wèn)一個(gè)數(shù)據(jù)段,它把段選擇符中的RPL設(shè)為3,這樣雖然它對(duì)該段仍然只有特權(quán)為3的訪問(wèn)權(quán)限。?
DPL存儲(chǔ)在段描述符中,規(guī)定訪問(wèn)該段的權(quán)限級(jí)別(Descriptor Privilege Level),每個(gè)段的DPL固定。?
當(dāng)進(jìn)程訪問(wèn)一個(gè)段時(shí),需要進(jìn)程特權(quán)級(jí)檢查,一般要求DPL >= max {CPL, RPL}?
下面打一個(gè)比方,中國(guó)官員分為6級(jí)國(guó)家主席1、總理2、省長(zhǎng)3、市長(zhǎng)4、縣長(zhǎng)5、鄉(xiāng)長(zhǎng)6,假設(shè)我是當(dāng)前進(jìn)程,級(jí)別總理(CPL=2),我去聊城市(DPL=4)考察(呵呵),我用省長(zhǎng)的級(jí)別(RPL=3 這樣也能?chē)標(biāo)浪麄?-))去訪問(wèn),可以吧,如果我用縣長(zhǎng)的級(jí)別,人家就不理咱了(你看看電視上的微服私訪,呵呵),明白了吧!為什么采用RPL,是考慮到安全的問(wèn)題,就好像你明明對(duì)一個(gè)文件用有寫(xiě)權(quán)限,為什么用只讀打開(kāi)它呢,還不是為了安全!?


? 全面解釋?zhuān)?
--------------------------------------------------------------------------------?

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

? 而DPL是段描述符中的特權(quán)級(jí), 它的本意是用來(lái)代表它所描述的段的特權(quán)級(jí). 一個(gè)程序可以使用很多段(Data,Code,Stack)也可以只用一個(gè)code段等.在正常的情況下當(dāng)程序的環(huán)境建立好后,段描述符都不需要改變-----當(dāng)然DPL也不需要改變.??


? 一、對(duì)數(shù)據(jù)段和堆棧段訪問(wèn)時(shí)的特權(quán)級(jí)控制:?

要求訪問(wèn)數(shù)據(jù)段或堆棧段的程序的CPL≤待訪問(wèn)的數(shù)據(jù)段或堆棧段的DPL,同時(shí)選擇子的RPL≤待訪問(wèn)的數(shù)據(jù)段或堆棧段的DPL,即程序訪問(wèn)數(shù)據(jù)段或堆棧段要遵循一個(gè)準(zhǔn)則:只有相同或更高特權(quán)級(jí)的代碼才能訪問(wèn)相應(yīng)的數(shù)據(jù)段。這里,RPL可能會(huì)削弱CPL的作用,訪問(wèn)數(shù)據(jù)段或堆棧段時(shí),默認(rèn)用CPU和RPL中的最小特權(quán)級(jí)去訪問(wèn)數(shù)據(jù)段,所以max {CPL, RPL} ≤ DPL,否則訪問(wèn)失敗。?


? 二、對(duì)代碼段訪問(wèn)的特權(quán)級(jí)控制(代碼執(zhí)行權(quán)的特權(quán)轉(zhuǎn)移):?

? 讓我們先來(lái)記一些“定律”:?
所有的程序轉(zhuǎn)跳,CPU都不會(huì)把段選擇子的RPL賦給轉(zhuǎn)跳后程序的CS.RPL. .?

? 轉(zhuǎn)跳后程序的CPL(CS.RPL)只會(huì)有下面的倆種可能?
? 轉(zhuǎn)跳后程序的CPL(CS.RPL) = 轉(zhuǎn)跳前程序的CPL(CS.RPL)??
? 或?
? 轉(zhuǎn)跳后程序的CPL(CS.RPL) = 轉(zhuǎn)跳后程序的CodeDescriptor.DPL?

? 以 Call 為例(只能跳到等于當(dāng)前特權(quán)級(jí)或比當(dāng)前特權(quán)級(jí)更高的段):?
? 怎樣決定這兩種選擇,這就要首先知道轉(zhuǎn)跳后程序的段是一致代碼段還是非一致代碼段.其實(shí)也很簡(jiǎn)單,規(guī)則如下:?
? 如果能成功轉(zhuǎn)跳到一致代碼段, 轉(zhuǎn)跳后程序的CPL(CS.RPL) = 轉(zhuǎn)跳前程序的CPL(CS.RPL),(轉(zhuǎn)跳后程序的CPL繼承了轉(zhuǎn)跳前程序的CPL)?
? 如果能成功轉(zhuǎn)跳到非一致代碼段, 轉(zhuǎn)跳后程序的CPL(CS.RPL) =轉(zhuǎn)跳后程序的Descriptor.DPL。(轉(zhuǎn)跳后程序的CPL變成了該代碼段的特權(quán)級(jí).我在前面提到DPL是段描述符中的特權(quán)級(jí), 它的本意是用來(lái)代表它所描述的段的特權(quán)級(jí))怎樣才能成功轉(zhuǎn)跳啦??

? 這里有四個(gè)重要的概念:?

? 1).段的保護(hù)觀念是高特權(quán)級(jí)不找低特權(quán)級(jí)辦事,低特權(quán)級(jí)找高特權(quán)級(jí)幫忙,相同的一定沒(méi)問(wèn)題.(這樣想邏輯是沒(méi)錯(cuò),事實(shí)對(duì)不對(duì)就不知道.)也就是縣長(zhǎng)不找鄉(xiāng)長(zhǎng),鄉(xiāng)長(zhǎng)不求農(nóng)民,反過(guò)來(lái)農(nóng)民求鄉(xiāng)長(zhǎng),鄉(xiāng)長(zhǎng)找縣長(zhǎng).這個(gè)概念是最重要的。?
? 2) 一致代碼段的意義: 讓客人很方便的利用主人(一致代碼段)的東西為自己辦事.但客人這身份沒(méi)有改變NewCS.RPL=OldCS.RPL所以只能幫自己辦事。比方說(shuō)鄉(xiāng)長(zhǎng)有一頭牛,農(nóng)民可以借來(lái)幫自己種田,但不能種別人的田.但是如果你是鄉(xiāng)長(zhǎng)當(dāng)然可以種鄉(xiāng)里所有的田。?
? 3) 非一致代碼段的意義:主人(非一致代碼段)可以幫客人但一定是用自己的身份NewCS.RPL= DestinationDescriptorCode.DPL這里可能有安全的問(wèn)題, 搞不好很容易農(nóng)民變縣長(zhǎng)。主人太頑固了一定要堅(jiān)持自己的身份,有什么方法變通一下,來(lái)個(gè)妥協(xié)好不好。好的,它就是RPL的用處。?
? 4) RPL: 它讓程序有需要的時(shí)候可以表示一個(gè)特權(quán)級(jí)更低的身份Max(RPL,CPL)而不會(huì)失去本身的特權(quán)級(jí)CPL(CS.RPL),有需要的時(shí)候是指要檢查身份的時(shí)候。事實(shí)上RPL跟段本身的特權(quán)級(jí)DPL和當(dāng)前特權(quán)級(jí)CPL沒(méi)有什么關(guān)系,因?yàn)镽PL的值在成功轉(zhuǎn)跳后并不賦給轉(zhuǎn)跳后的CS.RPL。?
? 還是要問(wèn)怎樣才能成功轉(zhuǎn)跳啦?這里分兩種情況:?

? 普通轉(zhuǎn)跳(沒(méi)有經(jīng)過(guò)Gate 這東西):即JMP或Call后跟著48位全指針(16位段選擇子+32位地址偏移),且其中的段選擇子指向代碼段描述符,這樣的跳轉(zhuǎn)稱為直接(普通)跳轉(zhuǎn)。普通跳轉(zhuǎn)不能使特權(quán)級(jí)發(fā)生躍遷,即不會(huì)引起CPL的變化,看下面的詳細(xì)描述:?


目標(biāo)是一致代碼段:?
? 要求:CPL(CS.RPL)>=DestinationDescriptorCode.DPL ,其他RPL是不檢查的。?
? 轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = 轉(zhuǎn)跳前程序的CPL( OldCS.RPL)?
? 上面的安排就是概念1,2的意思,此時(shí),CPL沒(méi)有發(fā)生變化,縱使它執(zhí)行了特權(quán)級(jí)(DPL)較高的代碼。若訪問(wèn)時(shí)不滿足要求,則發(fā)生異常。?
目標(biāo)是非一致代碼段:?
? 要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL≤CPL(CS.RPL)?
? 轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL?
? 上面的安排就是概念3的意思和部分1的意思----主人(一致代碼段)只幫相同特權(quán)級(jí)的幫客人做事。因?yàn)榍疤崾荂PL=DPL,所以轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL不會(huì)改變CPL的值,特權(quán)級(jí)(CPL)也沒(méi)有發(fā)生變化。如果訪問(wèn)時(shí)不滿足前提CPL=DPL,則引發(fā)異常。


? 通過(guò)調(diào)用門(mén)的跳轉(zhuǎn):當(dāng)段間轉(zhuǎn)移指令JMP和段間轉(zhuǎn)移指令CALL后跟著的目標(biāo)段選擇子指向一個(gè)調(diào)用門(mén)描述符時(shí),該跳轉(zhuǎn)就是利用調(diào)用門(mén)的跳轉(zhuǎn)。這時(shí)如果選擇子后跟著32位的地址偏移,也不會(huì)被cpu使用,因?yàn)檎{(diào)用門(mén)描述符已經(jīng)記錄了目標(biāo)代碼的偏移。使用調(diào)門(mén)進(jìn)行的跳轉(zhuǎn)比普通跳轉(zhuǎn)多一個(gè)步驟,即在訪問(wèn)調(diào)用門(mén)描述符時(shí)要將描述符當(dāng)作一個(gè)數(shù)據(jù)段來(lái)檢查訪問(wèn)權(quán)限,要求指示調(diào)用門(mén)的選擇子的RPL≤門(mén)描述符DPL,同時(shí)當(dāng)前代碼段CPL≤門(mén)描述符DPL,就如同訪問(wèn)數(shù)據(jù)段一樣,要求訪問(wèn)數(shù)據(jù)段的程序的CPL≤待訪問(wèn)的數(shù)據(jù)段的DPL,同時(shí)選擇子的RPL≤待訪問(wèn)的數(shù)據(jù)段或堆棧段的DPL。只有滿足了以上條件,CPU才會(huì)進(jìn)一步從調(diào)用門(mén)描述符中讀取目標(biāo)代碼段的選擇子和地址偏移,進(jìn)行下一步的操作。?
? 從調(diào)用門(mén)中讀取到目標(biāo)代碼的段選擇子和地址偏移后,我們當(dāng)前掌握的信息又回到了先前,和普通跳轉(zhuǎn)站在了同一條起跑線上(普通跳轉(zhuǎn)一開(kāi)始就得到了目標(biāo)代碼的段選擇子和地址偏移),有所不同的是,此時(shí),CPU會(huì)將讀到的目標(biāo)代碼段選擇子中的RPL清0,即忽略了調(diào)用門(mén)中代碼段選擇子的RPL的作用。完成這一步后,CPU開(kāi)始對(duì)當(dāng)前程序的CPL,目標(biāo)代碼段選擇子的RPL(事實(shí)上它被清0后總能滿足要求)以及由目標(biāo)代碼選擇子指示的目標(biāo)代碼段描述符中的DPL進(jìn)行特權(quán)級(jí)檢查,并根據(jù)情況進(jìn)行跳轉(zhuǎn),具體情況如下:?


目標(biāo)是一致代碼段:?
? 要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL ,RPL不檢查,因?yàn)镽PL被清0,所以事實(shí)上永遠(yuǎn)滿足RPL≤DPL,這一點(diǎn)與普通跳轉(zhuǎn)一致,適用于JMP和CALL。?
? 轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = 轉(zhuǎn)跳前程序的CPL( OldCS.RPL),因此特權(quán)級(jí)沒(méi)有發(fā)生躍遷。?
???
目標(biāo)是非一致代碼段:?
當(dāng)用JMP指令跳轉(zhuǎn)時(shí):?
? 要求:CPL(CS.RPL)=DestinationDescriptorCode.DPL AND RPL<= CPL(CS.RPL)(事實(shí)上因?yàn)镽PL被清0,所以RPL≤CPL總能滿足,因此RPL與CPL的關(guān)系在此不檢查)。若不滿足要求則程序引起異常。?
? 轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL?
? 因?yàn)榍疤崾荂PL=DPL,所以轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL不會(huì)改變CPL的值,特權(quán)級(jí)也沒(méi)有發(fā)生變化。如果訪問(wèn)時(shí)不滿足前提CPL=DPL,則引發(fā)異常。?
當(dāng)用CALL指令跳轉(zhuǎn)時(shí):?
要求:CPL(CS.RPL)≥DestinationDescriptorCode.DPL(RPL被清0,不檢查),若不滿足要求則程序引起異常。?
轉(zhuǎn)跳后程序的CPL(NewCS.RPL) = DestinationDescriptorCode.DPL?
當(dāng)條件CPL=DPL時(shí),程序跳轉(zhuǎn)后CPL=DPL,特權(quán)級(jí)不發(fā)生躍遷;當(dāng)CPL>DPL時(shí),程序跳轉(zhuǎn)后CPL=DPL,特權(quán)級(jí)發(fā)生躍遷,這是我們當(dāng)目前位置唯一見(jiàn)到的使程序當(dāng)前執(zhí)行憂先級(jí)(CPL)發(fā)生變化的跳轉(zhuǎn)方法,即用CALL指令+調(diào)用門(mén)方式跳轉(zhuǎn),且目標(biāo)代碼段是非一致代碼段。?


? 總結(jié):以上介紹了兩種情況的跳轉(zhuǎn),分別是普通跳轉(zhuǎn)和使用調(diào)用門(mén)的跳轉(zhuǎn),其中又可細(xì)分為JMP跳轉(zhuǎn)和CALL跳轉(zhuǎn),跳轉(zhuǎn)成功已否是由CPL,RPL和DPL綜合決定的。所有跳轉(zhuǎn)都是從低特權(quán)級(jí)代碼向同級(jí)或更高特權(quán)級(jí)(DPL)跳轉(zhuǎn),但保持當(dāng)前執(zhí)行特權(quán)級(jí)(CPL)不變,這里有點(diǎn)難于區(qū)別為什么說(shuō)向高特權(quán)級(jí)跳轉(zhuǎn),又說(shuō)特權(quán)級(jí)沒(méi)變,這里“高特權(quán)級(jí)”是指目標(biāo)代碼段描述符的DPL,它規(guī)定了可以跳轉(zhuǎn)到該段代碼的最高特權(quán)級(jí);而后面的CPL不變才真正說(shuō)明了特權(quán)級(jí)未發(fā)生躍遷。我們可以看到,只有用CALL指令+調(diào)用門(mén)方式跳轉(zhuǎn),且目標(biāo)代碼段是非一致代碼段時(shí),才會(huì)引起CPL的變化,即引起代碼執(zhí)行特權(quán)級(jí)的躍遷,這是目前得知的改變執(zhí)行特權(quán)級(jí)的唯一辦法,如果各位讀者還知道其他方法請(qǐng)留言告訴我。

《Orange’s 一個(gè)操作系統(tǒng)的實(shí)現(xiàn)》3.保護(hù)模式5----特權(quán)級(jí)概述


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!?。?/p>

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 99热久久精里都是精品66 | 免费一级大毛片a一观看不卡 | 中文字幕一区二区三区精品 | 中文字幕久久久久久精 | 国产精品伊人 | 国产精品久久视频 | 性感美女一级毛片 | 亚洲国产成人成上人色 | 97影院不用| 久久久久久久久66精品片 | a级高清观看视频在线看 | 26uuu欧美日韩国产 | 亚洲a在线视频 | 香蕉久久成人网 | 久久99久久99小草精品免视看 | 久久久国产99久久国产一 | 国产欧美成人不卡视频 | 成年女人视频免费观看一 | 成人亚洲视频在线观看 | 综合欧美日韩 | 亚洲精品无人区一区二区三区 | 毛片视频网站在线观看 | 国产精品亚洲第一区二区三区 | 日韩国产精品99久久久久久 | 久久久久久免费精品视频 | 久久亚洲国产中v天仙www | 国产亚洲精品福利 | 一级特黄aa大片欧美小说 | 91久久综合 | 久久香蕉国产线看观看8青草 | 老子影院午夜理伦手机不卡 | 性欧美另类老妇高清 | 澳门久久精品 | 成人国产精品久久久免费 | 狠狠色丁香婷婷综合精品视频 | 欧美性天天影院欧美狂野 | 欧美伦禁片在线播放 | 中文字幕一区二区精品区 | 大学生不戴套毛片视频 | 久久亚洲综合 | 久章草在线 |