Protection 3 ---- Type Checking

CPU的保护机制不仅仅表现在对于表限和段限的检查,还要进行各种各样的Type Cheking。类型检查的种类繁多,检查的时机以及涉及到的结构和寄存器也很多,这篇文章中仅仅介绍以前学习过的结构和寄存器的检查,像LDT,TSS这样的结构和寄存器的检查会在后面继续学习。

CPU在不同的时机进行类型检查,这些时机主要有:

  • 将段选择子加载到段寄存器中
  • 指令通过段寄存器访问段
  • 运行一个带有段选择子的操作数的指令
  • 在某些内部操作的时候
这些检查主要针对两个区域:
  • S(descriptor type) flag
  • Type field
S flag表示段是系统段还是代码/数据段,Type根据S的不同有不同的含义。


加载段

当将一个段选择子加载到段寄存器的时候,CPU只允许某种类型的段寄存器包含特定类型段描述符类型,Intel官方文档中给出了几种情况,我们按照Intel给出的情况写出了一些例子代码:

  • %cs寄存器仅能够加载代码段的选择子
这个例子很好构造,只要给%cs加载其他段的选择子就会产生#GP:
    # load data segment selector into code segment register.
    # trigger #GP exception
    movw $data_selector, %ax
    movw %ax, %cs
  • 只读的代码段和系统段不能够加载到数据段寄存器(%ds, %es, %fs和%gs)
为了构造这个例子,我们需要在GDT中添加一个系统段描述符:
system_descriptor:
    .quad 0x00cf82000000ffff
系统段描述符的S==0,在保护模式代码中将系统段选择子加载到%ds,就会产生#GP:
    # load system segment selector into data segment register.
    # trigger #GP exception
    movw $system_selector, %ax
    movw %ax, %ds
  • 只有可写数据段才能加载到堆栈段寄存器
我们把原来的数据段编程只读的:
data_descriptor:
    .quad 0x00cf90000000ffff
然后在保护模式代码中将它加载给%ss,这样就会产生#GP:
    # load read-only data segment selector into stack segment register.
    # trigger #GP exception
    movw $data_selector, %ax
    movw %ax, %ss
上述三个例子运行结果是相同的:


访问段

当指令通过段寄存器访问段的时候,CPU规定指令只可以使用预定义的方式访问某些段,Intel官方文档中也给出了一些例子:

  • 不可以向可执行段中写数据

这个例子很好构造,代码段是可执行段,我们只要向代码段中写数据就可以触发#GP异常:

    # write into executable segment.
    # trigger #GP exception
    xorl %eax, %eax
    movl %ebx, %cs:(%eax)

  • 不可以向只读数据段中写数据
首先将数据段改成只读的:

data_descriptor:
    .quad 0x00cf90000000ffff
然后再向数据段中写入数据就可以触发#GP异常:
    # write into read-only data segment.
    # trigger #GP exception
    xorl %eax, %eax
    movl %ebx, %ds:(%eax)

  • 当可读标志没有设置的时候不可以读取可执行段
先把代码段设置成只可运行的:

code_descriptor:
    .quad 0x00cf98000000ffff
然后从代码段中读取数据就会触发#GP异常:
    # read into executable-only segment.
    # trigger #GP exception
    xorl %eax, %eax
    movl %cs:(%eax), %ebx
这三个例子的运行结果也是一样的:


运行带有段选择子的指令

  • lcall或者ljmp指令只能够访问代码段,调用门,任务门或者TSS
这个#GP很好触发,我们可以让ljmp跳转到数据段:
    # a far jmp instruction access data segment.
    # trigger #GP exception
    ljmp $data_selector, $0x00
这个例子的运行结果:


其他

Intel文档中给出了很多检查类型的时机以及例子,不过很多都涉及到了我们没有学习到的数据结构和寄存器,这里就不再举例了。


参考

《Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B & 3C): System Programming Guide》
《自己动手写操作系统》
《x86/x64体系探索与编程》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值