苦李  

一 特权级

  简介

  特权级按照权力大小分为0、1、2、3四个级别,数字越小,权利越大。

  0级是操作系统内核所在层级,操作系统负责访问硬件、掌控核心数据等,权力最大。系统程序分别处于1、2级特权,一般是虚拟机、驱动程序等。用户程序处于3特权级。

 

  TSS简介

  TSS,即Task Status Segment,任务状态段。每个任务都有的结构,相当于任务的身份证。TSS最小有104字节,众多寄存器都囊括其中,我们目前只关注28字节以下部分。

 

   没有操作系统的情况下,我们可以认为进程就是任务。有了操作系统之后,一个任务被分为用户部分和内核部分。但是用户和内核特权级不同,所以一个任务会有两个特权级状态。在不同的特权级下,处理器应该使用不同的栈。

  每个任务每个特权级下只能有一个栈,一个任务最多有4个栈。

  为什么TSS只有ss0到ss2三个栈?因为这里存储的是代表0特权级、1特权级、2特权级的栈,3特权级的栈不需要存储,因为没有其他特权级要升级到3特权级。至于3特权级的栈如何获取,从上一级特权级栈中弹出。

 

  TSS是硬件支持的数据结构,由软件填写内容,硬件使用。TSS由TR寄存器加载。

 

  二 CPL和RPL

  CS寄存器中是指向当前执行的指令,即代码。RPL是用CS选择子中的RPL位。代表请求特权级,也称为处理器的当前特权级。 

  到底什么是处理器的当前特权级?CPU执行的指令肯定属于某个代码段,这个代码段描述扶的DPL字段即处理器的当前特权级,称为CPL。除了一致性代码段外,转移后的目标代码段的DPL代表将来的处理器当前特权级。

 

  上面说的都是访问内存的访问者的特权级。那么内存资源受访者的特权级在哪呢?其实就是段描述符中的DPL字段。

  访问者任何时候都不允许访问比自己特权级高的的资源。

  • 受访者为数据的情况下:访问者特权级大于等于受访者DPL即可访问。
  • 受访者为代码的情况下:只有访问者特权级等于受访者DPL才可以访问。

  只有一种情况下特权级会降低,即从中断处理程序返回时。

 

  如果处理器只能平移代码段的话,另外三个特权级代码将没有机会运行了。怎么穿过内存屏障呢?有很多种方法,下面先介绍一致性代码段。

  特权级升高后,代码想干什么都行,似乎还是有点不安全,有没有什么办法可以让我们执行了高特权级的代码,又不提升特权级的方式?一种方式是一致性代码段

  段描述符中,如果段是非系统段(S字段为0),可以用type字段中的C位为1代表一致性代码段。非一致性代码段只能平级转移,一致性代码段不用。

  一致性代码段的DPL一定要>=转移前的CPL。并且转移后不会用一致性代码段的DPL替换CPL。

 

  三 门、调用门RPL序

 

 

 

 

 

 

 

 

  这四个门都可以向高特权级转移。

 

  四 RPL

  既然有了CPL和DPL,为什么还要RPL呢?

  举个例子,我们在调用一个读取硬盘的调用门的时候,将参数(数据缓冲区数据段选择子)用内核数据段的选择子替代,这样就会把硬盘读取的内容替换掉内核数据段,破坏内核。

 

 

  问题出在哪?

  我们有两个必须要保证的条件:

  • 用户不能访问系统资源,用户程序要想做点"大事",必须要由操作系统出面。
  • 处理器必须要陷入内核才能帮助用户程序做“大事”,所以处理器的当前特权级会变成至高无上的 0 特权级。

  看似没办法解决上述问题,0特权级可以访问任何数据。其实问题的原因是:受访者不知道访问者的真实身份,在受访者看来,是0特权级的操作系统要数据,它还以为请求者是操作系统呢。实际情况是请求者为 3 特权级下的用户程序。即受访者不知道真正的访问者是谁。我们可以用RPL解决这个问题。

  在访问数据段的时候,还会带上RPL是否大于等于目标段描述符的DPL,如果不是,则触发异常,保护内核。

 

  五 IO特权级

  eflags寄存器如下:

 

   其中的IOPL负责控制所有65535个IO端口的使用,注意是所有。只有当当前特权级大于等于IOPL特权级,才可以访问所有的IO端口。一般只有操作系统可以访问所有的IO端口,即0特权级。

  但是在IOPL特权级大于当前特权级时,可以用IO位图来访问部分IO端口。

  IO位图位于TSS顶部,用一个bit代表一个端口,所以IO位图有65535/8=8192B=8KB大小。对应位为0代表该端口可以访问,1为不可访问。

posted on 2021-12-02 23:07  苦李  阅读(98)  评论(0)    收藏  举报