Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Linux內核系列—5.操作系統開發之特權級及特權級的轉移,linux特權

Linux內核系列—5.操作系統開發之特權級及特權級的轉移,linux特權

編輯:關於android開發

Linux內核系列—5.操作系統開發之特權級及特權級的轉移,linux特權


CPL——當前執行的程序或任務的特權級,它被存儲在cs和ss的第0位和第1位上。

DPL——段或者門的特權級,如果是數據段DPL則規定了可以訪問此段的最低特權級

RPL——通過段選擇子的第0位和第1位表現出來的。處理器通過檢查RPL和CPL來確認一個訪問請求是否合法。RPL保證了操作系統不會越俎代庖地代表一個程序去訪問一個段。

我們先來展示一下特權級錯誤訪問版本。

先把LABEL_DESC_DATA對應的段描述符的DPL修改為1:

LABEL_DESC_DATA:   Descriptor    0,      DataLen-1, DA_DRW+DA_DPL1    ; Data

繼續修改,把選擇子的RPL改為3:

SelectorData		equ	LABEL_DESC_DATA		- LABEL_GDT + SA_RPL3

運行結果如下:

虛擬機崩潰。因為RPL & CPL 必須 <= DPL

下面就演示一下從低特權轉到高特權的方法:

通過jmp和call所能進行的代碼段間轉移是非常有限的,對於非一致代碼段,只能在相同特權級代碼段之間轉移。遇到一致代碼段也最多能從低到高,而且CPL不會改變。如果想自由地進行不同特權級之間的轉移,顯然需要其他幾種方式,即運用門描述符或者TSS。調用門描述符格式如下:

一個門描述了由一個選擇子和一個偏移所指定的線性地址,程序正是通過這個地址進行轉移的。

以下是通過調用門轉移的目標段:

[SECTION .sdest]; 調用門目標段
[BITS	32]

LABEL_SEG_CODE_DEST:
	;jmp	$
	mov	ax, SelectorVideo
	mov	gs, ax			; 視頻段選擇子(目的)

	mov	edi, (80 * 12 + 0) * 2	; 屏幕第 12 行, 第 0 列。
	mov	ah, 0Ch			; 0000: 黑底    1100: 紅字
	mov	al, 'C'
	mov	[gs:edi], ax

	retf

SegCodeDestLen	equ	$ - LABEL_SEG_CODE_DEST
; END of [SECTION .sdest]

下面是代碼段描述符,選擇子及初始化描述符的代碼:

LABEL_DESC_CODE_DEST: Descriptor 0,SegCodeDestLen-1, DA_C+DA_32; 非一致代碼段,32

SelectorCodeDest	equ	LABEL_DESC_CODE_DEST	- LABEL_GDT

; 初始化測試調用門的代碼段描述符
	xor	eax, eax
	mov	ax, cs
	shl	eax, 4
	add	eax, LABEL_SEG_CODE_DEST
	mov	word [LABEL_DESC_CODE_DEST + 2], ax
	shr	eax, 16
	mov	byte [LABEL_DESC_CODE_DEST + 4], al
	mov	byte [LABEL_DESC_CODE_DEST + 7], ah

現在添加調用門:

LABEL_CALL_GATE_TEST: Gate SelectorCodeDest,   0,     0, DA_386CGate+DA_DPL0

宏Gate的定義在pm.inc中

描述符的屬性是DA_386CGate表明是一個調用門。裡面指定的選擇子是SelectorCodeDest,表明目標代碼段是剛剛新添加的代碼段。偏移地址是0,表示將跳轉到目標代碼段的開頭處。另外,我們把其DPL指定為0.

現在調用門准備就緒,它指向的位置是SelectorCodeDest:0,即標號LABEL_SEG_CODE_DEST處的代碼。

假設我們想由代碼A轉移到代碼B,運用一個調用門G,即調用門G中的目標選擇子指向代碼B的段。代碼B的DPL記做DPL_B,在用call指令時,要求目標代碼DPL_B<=CPL;在用jmp指令時,只能是DPL_B=CPL。

現在添加一個低特權的代碼段ring3和堆棧:

LABEL_DESC_CODE_RING3: Descriptor 0,SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3
LABEL_DESC_STACK3:     Descriptor 0,      TopOfStack3, DA_DRWA+DA_32+DA_DPL3

; 堆棧段ring3
[SECTION .s3]
ALIGN	32
[BITS	32]
LABEL_STACK3:
	times 512 db 0
TopOfStack3	equ	$ - LABEL_STACK3 - 1
; END of [SECTION .s3]

; CodeRing3
[SECTION .ring3]
ALIGN	32
[BITS	32]
LABEL_CODE_RING3:
	mov	ax, SelectorVideo
	mov	gs, ax

	mov	edi, (80 * 14 + 0) * 2
	mov	ah, 0Ch
	mov	al, '3'
	mov	[gs:edi], ax

	jmp	$
SegCodeRing3Len	equ	$ - LABEL_CODE_RING3
; END of [SECTION .ring3]

執行如下:

打印了紅色的3,表明我們由ring0到ring3的轉移成功。接下來試驗一下調用門的使用。

把調用門的描述符和選擇子改成特權等級為3.還有從低特權級到高特權級轉移的時候,需要用到TSS,我們來准備一個TSS。

LABEL_DESC_TSS:        Descriptor 0,          TSSLen-1, DA_386TSS

; TSS
[SECTION .tss]
ALIGN	32
[BITS	32]
LABEL_TSS:
		DD	0			; Back
		DD	TopOfStack		; 0 級堆棧
		DD	SelectorStack		;
		DD	0			; 1 級堆棧
		DD	0			;
		DD	0			; 2 級堆棧
		DD	0			;
		DD	0			; CR3
		DD	0			; EIP
		DD	0			; EFLAGS
		DD	0			; EAX
		DD	0			; ECX
		DD	0			; EDX
		DD	0			; EBX
		DD	0			; ESP
		DD	0			; EBP
		DD	0			; ESI
		DD	0			; EDI
		DD	0			; ES
		DD	0			; CS
		DD	0			; SS
		DD	0			; DS
		DD	0			; FS
		DD	0			; GS
		DD	0			; LDT
		DW	0			; 調試陷阱標志
		DW	$ - LABEL_TSS + 2	; I/O位圖基址
		DB	0ffh			; I/O位圖結束標志
TSSLen		equ	$ - LABEL_TSS

我們需要在特權級變換之前加載它

	mov	ax, SelectorTSS
	ltr	ax

運行結果如下:

 

看到字母C表明從低特權級到高特權級的轉移。

 

一個碼農的日常 

源碼

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved