特权级

       操作系统的保护模式相对于实模式最大的改变之一就是安全性的提升,这是通过引入权限概念来实现的。如下图所示,操作系统内核作为直接控制硬件设备的底层软件,权限最高;而驱动程序、虚拟机等系统程序的权限则次于内核;用户程序的权限最低,位于特权级最外层。

特权级_第1张图片 特权级环形图

TSS任务状态栈 

       任务状态栈(Task-State Segment,TSS)是处理器在硬件上原生支持多任务的一种实现方式, Intel在硬件层面提供了多任务解决方案(操作系统使不使用是另一回事)。本质上TSS就是一种数据结构,在Intel的处理器中其占据内存的结构如下图:

特权级_第2张图片 Intel 32-bit Task-State Segment

       TSS是每个任务都有的结构,它用于一个任务的标识,相当于Task ID。其中涉及到三对栈指针,这是与特权级栈密切相关的东西。 一个任务的执行分为用户部分和内核部分,由于内核程序位于0特权级,而用户程序位于3特权级,所以一个任务按特权级来划分的话,实际上是被分为用户程序和系统程序两部分,两部分加在一起才是能让处理器完整执行一个任务的的程序。

       任务是由处理器执行的,任务在特权级变换时,本质上是处理器的当前特权级在变换。为了避免栈溢出和程序混乱,操作系统规定每个任务的每个特权级下都有且只有一个栈。而TSS中的三对栈指针分别代表了0~2的三个特权级栈(一对指针由段选择子和偏移量组成)。特权级在变换时,需要用到不同特权级的栈。至于特权级为3的栈为什么没有,在下面会提到。

       特权级转移分为两类,一类是由中断门、调用门等手段实现低特权级转向高特权级,另一类则是由调用返回指令从高特权级返回到低特权级。

       对于第一种——特权级由低到高的情况,需要提前把目标栈的地址记录在TSS中,当处理器向高特权级转移时再从中取出来加载到SS和ESP中以切换特权级栈。因此,除了返回调用的方式以外,处理器只能由低特权级向高特权级转移,TSS中所记录的栈是转移后的高特权级目标栈,而3特权级是最低的,因此不需要3特权级的栈。此外,不是每个任务都有4个栈,比如1特权级的程序,它可以提升一级,因此只需要0特权级的栈就够了。

       对于第二种——特权级由高到低的情况,处理器不需要在TSS中去寻找低特权级目标栈,TSS只会有比当前特权级高的特权级栈的地址信息。正常情况下,特权级由低转高在先,由高返回低在后,因此只有先向高特权级转移才谈得上从高特权级返回到低特权级。因此当处理器由低特权级栈向高特权级栈转移时,它自动把当时低特权级的栈地址压入转移后的高特权级目标栈中,所以返回时就可以从高特权级栈中获取低特权级栈的地址信息。

CPL、DPL和RPL

       保护模式下的内存段的属性由段描述符给出,段描述符的DPL字段就标识了该段的特权级,而段选择子的RPL(请求特权级)字段则标识了访问者的特权级。CPL表示处理器的当前特权级,其值为CS选择子中的RPL字段值。

       在CPU中运行的是指令,指令总会属于某个代码段,该代码段的特权级,也就是代码段描述符中的DPL,便是当前CPU所处的特权级,它表示处理器正在执行的代码的特权级。除一致性代码外,转移后的目标代码段的DPL是将来处理器的当前特权级CPL。当前正在执行的代码所在的代码段的DPL就是处理器的当前特权级CPL,当处理器从一个代码段跳到另一个代码段时就有可能发生特权级改变,CPL也要随之改变。

       在不考虑RPL的情况下,对于受访者是数据段来说,访问者的权限必须大于等于受访者的DPL才能够访问,而对于受访者是代码段来说,访问者的权限必须等于受访者的DPL才能访问,即必须平级访问(除了中断处理程序会让处理器返回到用户态)。

一致性代码段

       在段描述符中有一致性代码段的标志位,一致性代码段也称为依从性代码段(Conforming),用来实现从低特权级到高特权级的代码段转移。只有代码段才有一致性和非一致性之分,数据段没有。一致性代码段是指,如果自己是转移后的目标段,自己的特权级(DPL)一定要大于等于转移前的CPL,即数值上CPL≥DPL。一致性代码段的一大特点是转移后的特权级不与自己的特权级(DPL)为主,而是与转移前的低特权级一致,依从转移前的低特权级。也就是说,当处理器遇到目标段为一致性代码段时,并不会将CPL的数值替换为目标段的DPL。低特权级的代码段可以在不切换进程特权级的情况下执行高特权级的代码,这看似很不安全,但由于访问权限还受制于RPL(下文介绍),因此低特权级的程序并不能为所欲为。

RPL

       操作系统提供了一致性代码段和门结构来实现从低特权级到高特权级的代码段转移,这会给恶意攻击者用低特权级的程序访问高特权级资源,使攻击者有诸如篡改内核之类的危险操作的机会,因此必须在CPL和DPL的基础上增加条件。

       访问者穿越特权屏障是因为操作系统允许通过特定方式实现从低特权级代码段到高特权级代码段的转移,即通过高特权级代码段来间接获得自身无法拥有的权限。由于真正的资源请求者是低特权级代码段,因此需要标识出资源请求者的真实身份,这就是请求特权级(Request Privilege Level,RPL)的作用。

       RPL代表了真正资源请求者的特权级,因此在请求特权级为DPL的资源时,需要检查的不仅是CPL,还要加上RPL,CPL和RPL的特权级必须同时大于等于受访者的DPL。

       RPL引入的目的是避免低特权级的程序访问高特权级的资源,有了RPL后,访问内存段的特权检查规则如下(不通过调用门):

       ·如果目标为非一致性代码段,要求数值上:CPL=RPL=目标代码段DPL

       ·如果目标为一致性代码段,要求数值上:CPL≤目标代码段DPL && RPL≥目标代码段DPL

       ·如果目标为数据段时,要求数值上:CPL≤目标数据段DPL && RPL ≤ 目标数据段DPL

       栈段的特权级检查比较特殊,因为在各个特权级下处理器都有对应的栈,所以往段寄存器中赋予选择子时,要求CPL等于栈段选择子对应的数据段的DPL,即数值上CPL=RPL=用作栈的目标数据段DPL。

 

                                                                                                本文部分内容摘自《操作系统真象还原》,有改动

你可能感兴趣的:(操作系统)