一致代码段与非一致代码段
首先,我們先來看幾個問題:
-
一致代碼段和非一致代碼段是什么?
-
為什么要有一致代碼段和非一致代碼段?
-
系統(tǒng)提供怎樣的機制來使用戶程序訪問內(nèi)核數(shù)據(jù)?
-
程序如何在段與段之間跳轉(zhuǎn)?
接下來,我們將討論上述這些問題。
特權級
為了更好的理解之后的問題,我們先來討論一個概念:特權級。
-
特權級是一種機制來保護數(shù)據(jù)和防止惡意行為,特權級分4種:0,1,2,3。0為最高特權級,4為最低。(在 Linux 中只使用了0和3)
-
這些特權級是通過三個標志來表示的:CPL,DPL,RPL
- CPL 是存放于如 CS、SS 寄存器中的,表示當前特權級
- DPL 是在 GDT(全局描述符表)/LDT(局部描述符表)中的,靜態(tài)的
- RPL是代碼中根據(jù)不同段跳轉(zhuǎn)而確定,用于刷新 CPL
-
CPL(Current Privilege Level)是表示當前執(zhí)行程序的特權級,它被存放在CS 和 SS 的第0位和第1位。通常情況下,CPL等于代碼的段的特權級。在遇到一致代碼段時,一致代碼段可以被相同或者更低特權級的代碼段訪問。當處理器訪問一個與 CPL特權級不同的代碼段時,CPL 不會改變。
-
DPL(Descriptor Privilege Level)表示段或者門的特權級,它被存儲在段描述符或門描述符的 DPL 字段中。當當前代碼段要訪問一個段或門時,DPL 會和 CPL 以及段選擇子或門選擇子的 RPL 進行比較,根據(jù)段或門的不同類型,DPL 將會被區(qū)別對待
- 數(shù)據(jù)段:DPL 規(guī)定了可以訪問該段的最低特權級,如果 DPL 為1,那么只有運行在CPL 為0或者1的程序才有權訪問它。
- 非一致代碼段(不使用調(diào)用門的情況下):DPL 規(guī)定了可以訪問該段的特權級,如果 DPL 為1,那么只有運行在 CPL 為1的程序才有權訪問它。
- 調(diào)用門:DPL 規(guī)定了當前運行程序可以訪問調(diào)用門的最低特權級(和數(shù)據(jù)段訪問規(guī)則相同)
- 一致代碼段和通過調(diào)用門訪問的非一致代碼段:DPL 規(guī)定了有權訪問該段的最高特權級。例,一個一致代碼段的 DPL 為2,那么運行在 CPL 為0,1的程序無權訪問此段。
-
RPL(Request Privilege Level):RPL 是通過選擇子的第0,1位表現(xiàn)出來的,處理器通過檢查 CPL 和 RPL來確認一個訪問請求是否合法。
一致代碼段與非一致代碼段
-
一致代碼段:通俗的講,一致代碼段就是系統(tǒng)用來共享、提供給低特權級的程序使用調(diào)用的代碼。
-
非一致代碼段:為了避免被低特權級程序訪問而被系統(tǒng)保護起來的代碼。
一致代碼段限制
-
特權級高的程序不允許訪問特權級低的數(shù)據(jù),即核心態(tài)程序不能訪問用戶態(tài)數(shù)據(jù)。
-
特權級低的程序可以訪問特權級高的程序,但是特權級不會因此而改變。
非一致代碼段限制
-
只允許同級之間訪問
-
不允許不同級之間訪問,核心態(tài)不能訪問用戶態(tài),用戶態(tài)也不能訪問核心態(tài)
通常低特權值代碼必須通過『門』來完成對高特權值代碼的調(diào)用
為什么要定義一致代碼段與非一致代碼段?
定義這個概念主要是為了系統(tǒng)安全:內(nèi)核要和用戶程序分開,內(nèi)核一定要安全不能被用戶程序干涉。但有時候用戶程序也需要讀取內(nèi)核的某些數(shù)據(jù)。于是操作系統(tǒng)內(nèi)核程序開辟一些可以供用用戶程序訪問的段,但是不允許用戶程序?qū)懭霐?shù)據(jù)。內(nèi)核不用知道用戶程序的數(shù)據(jù),內(nèi)核不用調(diào)用用戶程序的數(shù)據(jù),內(nèi)核不用轉(zhuǎn)移到用戶程序中來。用戶程序只能訪問到內(nèi)核的某些共享的段,我們稱這些段為一致代碼段。用戶程序不能訪問內(nèi)核不共享的段。
門描述符
門描述符結(jié)構(gòu)
調(diào)用門的使用方式
門描述符的實現(xiàn)
<code class="hljs perl has-numbering">; 門描述符 ; <span class="hljs-number">4</span>個參數(shù): ; <span class="hljs-number">1</span>.選擇子:<span class="hljs-number">16</span>位 ; <span class="hljs-number">2</span>.偏移量:<span class="hljs-number">32</span>位 ; <span class="hljs-number">3</span>.DCount ; <span class="hljs-number">4</span>.屬性 <span class="hljs-variable">%macro</span> Gate <span class="hljs-number">4</span>dw (<span class="hljs-variable">%2</span> & 0FFFFh) ;取參數(shù)<span class="hljs-number">2</span>的低<span class="hljs-number">16</span>位填充一個 WORDdw <span class="hljs-variable">%1</span> ;取參數(shù)<span class="hljs-number">1</span>填充一個 WORDdw (<span class="hljs-variable">%3</span> & <span class="hljs-number">1</span>Fh) | ((<span class="hljs-variable">%4</span> << <span class="hljs-number">8</span>) & 0FF00h) ; 屬性dw ((<span class="hljs-variable">%2</span> >> <span class="hljs-number">16</span>) & 0FFFFh) ; 偏移<span class="hljs-number">2</span> <span class="hljs-variable">%endmacro</span> ; 共 <span class="hljs-number">8</span> 字節(jié)</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>不同特權級代碼段的轉(zhuǎn)移
使用 jmp 和 call 可以實現(xiàn)下列4種轉(zhuǎn)移:
-
目標操作數(shù)包含目標代碼段的段選擇子
-
目標操作數(shù)指向包含目標代碼段段選擇子的門描述符
-
目標操作數(shù)指向包含目標代碼段段選擇子的 TTS(Task-State Stack)
-
目標操作數(shù)指向一個任務門,這個任務門指向包含目標代碼段段選擇子對 TTS
這四種方式可以分為兩類:一是,通過 call 或 jmp 的直接轉(zhuǎn)移,二是,通過某個描述符的間接轉(zhuǎn)移
通過 call 和 jmp 直接轉(zhuǎn)移
| 非一致代碼段 | CPL=DPLRPL<=DPL | 當轉(zhuǎn)移到目標代碼段時,CPL=DPL |
| 一致代碼段 | CPL>DPL,RPL 不做檢查 | 當轉(zhuǎn)移到目標代碼段時,CPL 會延續(xù)下來 |
通過門描述符的轉(zhuǎn)移
假設我們想由代碼A轉(zhuǎn)移到代碼B,運用一個調(diào)用門G,即調(diào)用門G中的目標選擇子指向代碼B的段。實際上,這個問題主要涉及這幾個元素:CPL、RPL、代碼B的DPL(記做DPL_B),調(diào)用門G的DPL(記做DPL_G)。
| 非一致代碼段 | CPL<=DPL_GRPL<=DPL_GDPL_B<=CPL | CPL<=DPL_GRPL<=DPL_GDPL_B=CPL |
| 一致代碼段 | CPL<=DPL_GRPL<=DPL_GDPL_B<=CPL | CPL<=DPL_GRPL<=DPL_GDPL_B<=CPL |
通過調(diào)用門和 call 指令,可以實現(xiàn)低特權級到高特權級的轉(zhuǎn)移,無論目標代碼段是一致的還是非一致的
通過門調(diào)用和 jmp 指令,如果目標代碼段是一致的,則可以實現(xiàn)低特權級到高特權級的轉(zhuǎn)移;如果是非一致的,那么只能實現(xiàn)相同特權級的轉(zhuǎn)移
總結(jié)
以上是生活随笔為你收集整理的一致代码段与非一致代码段的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 统一代码段与非一致代码段
- 下一篇: 门描述符