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