特权级--ring0到ring3

内核要和用户程序分开,内核一定要安全,不能被用户程序干涉,但是有时候用户程序也需要读取内核的某些数据,怎么办呢?x86就引入了访问特权等级(0-3)的机制,x86 cpu共有4个特权级 level0 到 level3 其中level0特权级最高,level3特权级最高。处理器通过识别CPL、DPL、RPL这3中种特权级进行特权级检验。
CPL(Current Privilege Level)是当前执行的程序或任务的特权级。它被存储在CS和SS的第0位和第1位上。
DPL(Descriptor Privilege Level)表示段或者门的特权级。它被存储在段描述符或者门描述符的DPL字段中。
RPL(Requessted Privilege Level)是通过段选择子的第0位和第1位表现出来的。
jmp和call所能进行的代码间转移是非常有限的,对于非一致代码段,只能在相同特权级代码间转移;对于一致代码段,可以从低到高,且CPL不会改变。
我们一般用调用门和lcall指令实现特权级由低到高的转移,通过lret指令实现特权级由高到低的转移。

其实我们一直在特权级0下工作,下面我们就用lret实现特权级由高到低的转移,ring0--->ring3

  1. #define Descriptor(base,lim,attr)\  
  2. .word lim&0xffff;\  
  3. .word base&0xffff;\  
  4. .byte (base>>16)&0xff;\  
  5. .word ((lim>>8)&0xf00)|(attr&0x0f0ff);\  
  6. .byte ((base>>24)&0xff)    
  7.     
  8. /*    
  9. *InitDescrptor(Descriptor,SegBase)初始化描述符函数    
  10. *Descriptor:要初始化的描述符    
  11. *SegBase:段基址    
  12. */    
  13. #define InitDescrptor(Descriptor,SegBase)\  
  14. xor     %eax,%eax; \  
  15. mov     %cs,%ax  ; \  
  16. shl     $4,%eax  ; \  
  17. addl    $(SegBase), %eax ;\  
  18. movw    %ax, (Descriptor + 2);\  
  19. shr     $16, %eax;\  
  20. movb    %al, (Descriptor + 4);\  
  21. movb    %ah, (Descriptor + 7)    
  22.   
  23. #define Gate(Selector,Offset,PCount,Attr)\  
  24. .2byte (Offset&0xffff);\  
  25. .2byte (Selector);\  
  26. .2byte (PCount&0x1f)|((Attr<<8)&0xff00);\  
  27. .2byte ((Offset>>16)&0xffff)    
  28.   
  29. DA_386CGate = 0x8c  
  30. DA_C   = 0x98    
  31. DA_32  = 0x4000    
  32. DA_DRW = 0x92   
  33. DA_DRWA=0x93   
  34. SA_TIL = 0x4    
  35. DA_LDT = 0x82   
  36.   
  37. SA_RPL3 = 3  
  38. DA_DPL0=0x00  
  39. DA_DPL1=0x20  
  40. DA_DPL2=0x40  
  41. DA_DPL3=0x60   
  42.     
  43. .text    
  44. .globl start    
  45. .code16    
  46. start:    
  47.  jmpl $0x0, $code     
  48.      
  49. /**-----------------------------------------------------------------    
  50.  * 全局描述符表: GDT    
  51.  *-------------------------------*/         
  52. GDT_START:      
  53. Descriptor_DUMMY: Descriptor(0x0,0x0,0x0)    
  54. Descriptor_CODE32:Descriptor(0x0,0xffffffff,DA_C+DA_32)    
  55. Descriptor_VIDEO: Descriptor(0xb8000,0x0ffff,DA_DRW + DA_DPL3)    
  56. Descriptor_CODE_GATE:Descriptor(0x0,CodeGLen,DA_C+DA_32)  
  57. Descriptor_LDT:   Descriptor(0x0,LDTLen - 1, DA_LDT)  
  58. Descriptor_CODE3:Descriptor(0x0,0xffffffff,DA_C+DA_32+DA_DPL3)  
  59. Descriptor_STACKR3:Descriptor(0,TopOfStackR3, (DA_DRWA + DA_32 + DA_DPL3))  
  60.   
  61. /*门描述符*/   
  62. Descriptor_Gate_Call:Gate(Selector_Code_Gate,0,0,(DA_386CGate+DA_DPL0))    
  63. GDT_END:    
  64.     
  65. GdtPtr:    
  66.     .word (GDT_END-GDT_START)-1 # so does gdt     
  67.     .long GDT_START     # This will be rewrite by code.    
  68.   
  69. /**-----------------------------------------------------------------    
  70.  * GDT中的选择子  
  71.  *-------------------------------*/   
  72. .set    selector_Code32,(Descriptor_CODE32-GDT_START)  
  73. .set    Selector_Video,(Descriptor_VIDEO-GDT_START)       
  74. .set  Selector_Code_Gate,(Descriptor_CODE_GATE-GDT_START)  
  75. .set    SelectorLDT,(Descriptor_LDT-GDT_START)  
  76. .set    selector_CodeR3,(Descriptor_CODE3-GDT_START+SA_RPL3)  
  77. .set    SelectorStackR3,(Descriptor_STACKR3- GDT_START + SA_RPL3)  
  78. /*调用门选择子*/  
  79. .set    Selector_Gate_Call,(Descriptor_Gate_Call-GDT_START)  
  80.   
  81. /**-----------------------------------------------------------------  
  82.  * 局部描述符表: LDT  
  83.  *-------------------------------*/  
  84. LDT_START:  
  85. /*                       段基址    段界限      属性*/  
  86. Descriptor_LDT_CODEA: Descriptor(0, CodeALen - 1, DA_C + DA_32)# Code, 32 位  
  87.   
  88. .set    LDTLen,(. - LDT_START)  
  89.   
  90. #LDT 选择子  
  91. .set  SelectorLDTCodeA,(0x0 + SA_TIL)  
  92.   
  93.   
  94.   
  95. /* 32-bit ring 3 stack segment. */  
  96. .align  4  
  97. LABEL_STACKR3:  
  98. .space  10, 0  
  99. .set    TopOfStackR3, (. - LABEL_STACKR3)  
  100. msg:    
  101.  .string "Hello world!"    
  102.      
  103.      
  104. code:    
  105.     mov     %cs,%ax       
  106.     mov     %ax,%ds     
  107.     mov     %ax,%es        
  108.     mov     %ax,%ss      
  109.     mov  $0x8000,%sp      
  110.     /*显示HelloWorld字符串*/    
  111.     mov $msg   ,%ax    
  112.     mov %ax    ,%bp    
  113.     mov $12    ,%cx    
  114.     mov $0x1301,%ax    
  115.     mov $0x000c,%bx    
  116.     mov $0     ,%dl    
  117.         
  118.     int $0x10    
  119.         
  120.     
  121. /*初始全局描述符Descriptor_CODE32*/    
  122. InitDescrptor(Descriptor_CODE32,LABEL_SEG_CODE32);   
  123.   
  124. /*初始全局描述符Descriptor_LDT*/  
  125. InitDescrptor(Descriptor_LDT,LDT_START);  
  126.     
  127. /*初始全局描述符Descriptor_CODE_GATE*/    
  128. InitDescrptor(Descriptor_CODE_GATE,LABEL_CODE_G);    
  129. /*初始全局描述符LABEL_STACKR3 */  
  130. InitDescrptor(LABEL_STACKR3,Descriptor_STACKR3);  
  131.   
  132. /*初始LDT 中的描述符Descriptor_LDT_CODEA*/  
  133. InitDescrptor(Descriptor_LDT_CODEA,LABEL_CODE_A);  
  134.   
  135. /*初始全局描述符Descriptor_CODE3*/    
  136. InitDescrptor(Descriptor_CODE3,LABEL_CODE_3);  
  137.   
  138. /*加载gdtr即将全局描述符表gdt的首地址和gdt的界限赋给gdtr寄存器*/           
  139.     lgdt GdtPtr    
  140.     
  141. /*关中断*/    
  142.     cli    
  143.     
  144. /*打开地址线A20*/    
  145.     inb $0x92,%al    
  146.     or  $0x02,%al    
  147.     outb %al,$0x92    
  148.     
  149. /*设置cr0寄存器,切换到保护模式*/    
  150.     movl %cr0,%eax    
  151.     or   $1,%eax    
  152.     movl %eax,%cr0    
  153.     
  154.     
  155. /*真正进入保护模式,执行此命令后CS=0x8,IP=0*/    
  156.     ljmp $selector_Code32,$0    
  157.     
  158.   
  159.   
  160. LABEL_SEG_CODE32:    
  161. .align  32    
  162. .code32    
  163.     
  164.     movw $Selector_Video,%ax    
  165.     movw %ax,%gs/* 视频段选择子(目的)*/    
  166.     movl $((80*11+79)*2),%edi/*第11行,79列*/    
  167.     movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/    
  168.     movb $'P',%al/*显示的字符*/    
  169.     movw %ax,%gs:(%edi)    
  170.       
  171.     #ljmp $selector_CodeR3,$0   
  172.       
  173.     pushl $SelectorStackR3  
  174.     pushl $TopOfStackR3  
  175.     pushl $selector_CodeR3  
  176.     pushl $0  
  177.     lret    
  178.       
  179.     lcall $Selector_Gate_Call,$0    
  180.     
  181.     #ljmp  $Selector_Code_Gate,$0  
  182.     movw $SelectorLDT,%ax  
  183.     lldt %ax/*加载lgtr*/  
  184.   
  185.     ljmp    $SelectorLDTCodeA,$0    /* 跳入局部任务 LABEL_CODE_A*/  
  186.    
  187.         
  188. jmp .    
  189.         
  190. LABEL_CODE_G:  
  191.   
  192.     movl $((80*12+0)*2),%edi/*第10行,0列*/    
  193.     movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/    
  194.     movb $'G',%al/*要显示的字符*/    
  195.     movw %ax,%gs:(%edi)    
  196.           
  197.         lret  
  198. .set CodeGLen,(. - LABEL_CODE_G)    
  199.   
  200. LABEL_CODE_A:  
  201.     movw $0x10,%ax  
  202.     movw %ax,%gs/* 视频段选择子(目的)*/  
  203.     movl $((80*12+10)*2),%edi/*第10行,0列*/  
  204.     movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/  
  205.     movb $'A',%al/*要显示的字符*/  
  206.     movw %ax,%gs:(%edi)  
  207.   
  208. jmp .  
  209. .set CodeALen,(. - LABEL_CODE_A)  
  210.   
  211. LABEL_CODE_3:  
  212.     movw $0x10,%ax  
  213.     movw %ax,%gs/* 视频段选择子(目的)*/  
  214.     movl $((80*12+10)*2),%edi/*第10行,0列*/  
  215.     movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/  
  216.     movb $'3',%al/*要显示的字符*/  
  217.     movw %ax,%gs:(%edi)  
  218.   
  219. jmp .  
  220. .set Code3Len,(. - LABEL_CODE_3)  
  221.     
  222. .org 0x1fe, 0x90     
  223. .word 0xaa55   


 

具体改动点如下:
DA_DRWA=0x93
SA_RPL3 = 3
DA_DPL3=0x60

我们将的描述符Descriptor_VIDEO设为DA_DPL3,添加描述符Descriptor_CODE3和Descriptor_STACKR3
Descriptor_VIDEO: Descriptor(0xb8000,0x0ffff,DA_DRW + DA_DPL3)
Descriptor_CODE3:Descriptor(0x0,0xffffffff,DA_C+DA_32+DA_DPL3)
Descriptor_STACKR3:Descriptor(0,TopOfStackR3, (DA_DRWA + DA_32 + DA_DPL3))

添加选择子selector_CodeR3和SelectorStackR3
.set selector_CodeR3,(Descriptor_CODE3-GDT_START+SA_RPL3)
.set  SelectorStackR3,(Descriptor_STACKR3- GDT_START + SA_RPL3)

ring3下的堆栈
.align  4
LABEL_STACKR3:
.space  10, 0
.set    TopOfStackR3, (. - LABEL_STACKR3)

/*初始全局描述符LABEL_STACKR3 */
InitDescrptor(LABEL_STACKR3,Descriptor_STACKR3);

/*初始全局描述符Descriptor_CODE3*/  
InitDescrptor(Descriptor_CODE3,LABEL_CODE_3);

在ring3下打印'3'
LABEL_CODE_3:
 movw $0x10,%ax
 movw %ax,%gs/* 视频段选择子(目的)*/
 movl $((80*12+10)*2),%edi/*第10行,0列*/
 movb $0x0c,%ah/*高四位0000表示黑底,低四位1100表示红字*/
 movb $'3',%al/*要显示的字符*/
 movw %ax,%gs:(%edi)

jmp .
.set Code3Len,(. - LABEL_CODE_3)

实现从ring0到ring3的跳转
pushl $SelectorStackR3      //ss入栈
    pushl $TopOfStackR3      //esp入栈
    pushl $selector_CodeR3//cs入栈
    pushl $0                              //ip入栈
    lret                                        //将栈中的内容弹出   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值