【OS学习笔记】二十四 保护模式七:调用门与依从的代码段----特权级保护
发布日期:2021-07-01 00:05:48 浏览次数:3 分类:技术文章

本文共 3418 字,大约阅读时间需要 11 分钟。

学习交流加

  • 个人qq:
    1126137994
  • 个人微信:
    liu1126137994
  • 学习交流资源分享qq群:
    962535112

上一篇文章学习了保护模式下的任务与任务隔离,以及简单介绍了保护模式下的特权级的概念。点击链接查看上一篇文章:

今天具体来学习一下保护模式下的特权级保护。

主要学习以下内容;

  • 描述符特权级(目标对象的特权级)DPL

  • 当前特权级CPL

  • 低特权级的应用调用高特权级的操作系统代码的两种方法

    • 第一种方法是将高特权级的代码段定义为依从的
    • 第二种方法是使用调用门
  • 请求特权级RPL

文章目录

1、描述符特权级DPL

实施特权级保护的第一步,是为所有可管理的对象赋予一个特权级,以决定谁能访问它们。在这篇文章中,我们学习了描述符的格式,如下图。

在这里插入图片描述

每个描述符都有一个两比特的DPL字段。可取值为0,1,2,3 。DPL是每个描述符都有的字段,称为描述符特权级,而描述符总是指向它所描述的目标的对象,代表着该对象,因此,该字段实际上是目标对象的特权级。

比如对于数据段来说,DPL决定了访问它们所应具备的最低特权级别。如果一个描述符的DPL字段为2,那么能够访问该数据段的只有特权级为0,1,2的程序。当一个特权级为3的程序访问该数据段的时候,将会被处理器阻止,并引发异常中断。

对任何段的访问都要先把该段的描述符加载到段寄存器,所以这种保护手段很容易实现。

2、当前特权级CPL

在实模式下,段寄存器存放的是段地址;而在保护模式下,段寄存器存放的是段选择子与描述符高速缓存器。当处理器正在一个代码段中取指令和执行指令时,那个代码段的特权级叫做当前特权级CPL。

正在执行的这个代码段,其选择子位于段寄存器CS中,其最低两位就是当前特权级的数值。

在一个任务中,有全局空间和局部空间。一般来说任务的全局空间是操作系统的函数,特权级是0。任务的局部空间一般是任务自己的函数,特权级是3。

那些只能在当前特权级CPL为0的时候才能执行的指令,称为特权指令。典型的特权指令如加载全局描述符表的lgdt、加载局部描述符表的指令lldt、停机指令hlt等。

3、如何将代码段转移到另一个代码段

代码段的特权级检查是很严格的,一般来说,控制转移只允许发生在两个特权级相同的代码段之间。

不过为了让特权级低的用户程序可以调用特权级高的内核程序,处理器也提供了相应的解决办法。

  • 第一种办法是将高特权级的代码定义为依从的
  • 使用调用门

3.1 将高特权级的代码段定义为依从的

在这篇文章里,我们学习了段描述符,有一个TYPE字段。代码段的TYPE字段有一个C位,如果C=0,这样的代码段只能供同特权级的代码段调用;否则如果C=1,则这样的代码段称为依从的代码段,可以从特权级比它低的程序调用并进入。

注意,即使是将控制转移到依从的代码段,也必须是低特权级的程序调用高特权级的代码并进入。而不能是从高特权级的代码转移到低特权级的代码。内核的代码已经很牛逼了,它是不会想要调用你的用户程序的代码的,就是这个道理。

上述转移到依从代码段的要求可以用一个表达式来传达:

CPL>=目标代码段描述符的DPL

依从的代码段不是在它的DPL特权级上运行,而是在调用程序的特权级上运行。也就是说,当控制权转移到依从的代码段后,不改变当前特权级CPL,段寄存器CS的CPL不发生变化,被调用过程的特权级依从于调用者的特权级。这就是为什么它被称为依从的代码段。

3.2 调用门

除了依从大代码段,另一种在特权级之间转移控制的方法是使用门。

门是另一种形式的描述符。称为门描述符,简称门。和段描述符不同,段描述符用于描述内存段。门用于描述可执行代码,比如一段程序,一个过程,或者一个任务。

实际上,门的类型有好几种。不同特权级之间的过程调用可以使用调用门;中断门/陷阱门是作为中断处理过程使用的;任务门对应单个的任务,用来执行任务切换。在本文,我们重点学习调用门。

所有的描述符都是64位的,调用门描述符也不例外。在调用门的描述符中,定义了目标过程(例程)所在代码段的选择子,以及段内偏移。要想使用调用门进行控制转移,可以使用jmp far或者call far指令,并把调用门的=描述符的选择子作为操作数。

使用jmp far指令,可以将控制通过门转移到比当前特权级高的代码段,但不改变当前特权级别。但是如果使用call far 指令,则当前特权级会提升到目标代码段的特权级。

在继续学习调用门前,我们有一个知识点需要补充。那就是请求特权级RPL。

我们知道,要将一个控制从一个代码段转移到另一个代码段,通常是使用jmp或者call指令,并在指令中提供目标代码的段选择子,以及段内偏移量。而为了访问内存中的数据,也必须将段选择子加载到寄存器DS、ES、FS或者GS。不管是实施控制转移,还是访问数据,这都可以看成是一个请求,请求者提供一个段选择子,请求访问指定的段。从这个意义上来讲,RPL也就是指请求者的特权级别。

在绝大多数情况下,请求者都是当前程序自己,因此CPL=RPL。要判断请求者是谁,最简单的方法是看谁提供的选择子,谁就是请求者。

但是在一些并不多见的情况下,RPL和CPL并不相同。如下图,特权级为3的应用程序,希望从硬盘读一个扇区,并传送到自己的数据段,因此数据段的DPL是3.

在这里插入图片描述

上图中,应用程序通过调用门调用内核例程,请求者是用户程序,即RPL=3.但是真正读硬盘的是内核例程,通过调用门会改变当前特权级,进入内核示例后,CPL=0. 此时RPL与CPL就不相同。

不过,上面的例子只是表明RPL有可能与CPL不同,但是并没有说明引入RPL到底有什么必要性。

我们再看下面的一个例子:

在这里插入图片描述

假设用户程序不知道从哪里得知了操作系统内核的数据段的选择子。而且该用户程序想要改变该内核数据段的内容。它虽然不可以直接读写内核的数据段,但是它可以通过调用门,调用操作系统例程,当前特权级变为0,可以从硬盘读数据,并将他们写到操作系统的数据段。这下就糟糕了,这肯定会破坏操作系统。

怎么办????

看的出来,单纯依靠处理器硬件的检查机制无法解决这个难题,但它可以在原来的基础上做增加一种检查机制,并把如何通过这种检查的规则交给软件(编写者)

那么此时RPL就派上用场了。每当处理器执行一个将段选择子传送给段寄存器的指令时,会检查以下两个条件是否满足。

  • 当前特权级CPL高于或者和数据段描述符的DPL相同。即在数值上有:CPL<=数据段描述符的DPL。
  • 请求特权级RPL高于或者和数据段描述符的DPL相同。即在数值上有:RPL<=数据段描述符的DPL。

如果以上两个条件不能同时成立,处理器会阻止这种操作,并引发异常中断。

所以在上图所示的例子中,当用户程序想要写内核的数据段,通过调用门调用内核例程后,当前特权级CPL与数据段描述符的DPL都是0,满足第一个条件。但是RPL=3,数据段的DPL=0,不满足第二个条件,所以处理器引发异常中断。

以上就是引入RPL的作用。它也是特权级保护的重要特性之一。

4、总结

最后我们来总结一下基本的特权级检查规则。

  • 首先,将控制直接转移到非依从的代码段,要求当前特权级CPL和请求特权级RPL都等于目标代码段的描述符的DPL。即在数值上有:

    CPL=目标代码段描述符的DPL

    RPL=目标代码段描述符的DPL

一个典型的例子就是jmp指令进行控制转移(jmp指令不改变当前特权级)

  • 其次,要将控制转移到依从的代码段,要求当前特权级CPL和请求特权级RPL都低于或者和目标代码的DPL相等。即在数值上有:

    CPL>=目标代码段描述符的DPL

    RPL>=目标代码段描述符的DPL

控制转移后,当前特权级保持不变。

  • 第三,高特权级别的程序可以访问低特权级别的数据段,但是低特权级别的程序不能访问高特权级别的数据段。访问数据段之前,肯定会修改数据段寄存器,在这个时候,要求当前特权级与请求特权级都必须高于或者和目标数据段的DPL相等。即在数值上有:

    CPL<=目标数据段描述符的DPL

    RPL<=目标数据段描述符的DPL

  • 最后,在任何时候,处理器要求栈段的特权级别必须和当前特权级CPL相同。

详细的内容还是要参考原书籍,这里只是做一个简单的总结。

学习探讨加个人:

qq:1126137994
微信:liu1126137994

转载地址:https://lyy-0217.blog.csdn.net/article/details/85019982 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【OS学习笔记】二十五 保护模式七:任务和特权级保护对应的汇编源代码
下一篇:【OS学习笔记】二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月23日 20时40分38秒