在操作系统中,Ring 0和Ring 3是什么?

2021-03-03 16:06:40

我一直在学习有关Windows中驱动程序开发的基础知识,我一直在寻找术语Ring 0和Ring3。它们指的是什么? 它们与内核模式和用户模式是否相同? 1 en.wikipedia.org/wiki/Ring_%28computer_security%29-是的,它们与内核模式和用户模式相同,并且在某些Windows版本中,ring 1和ring 2有效地用于设备驱动程序 – dwarduk 了解环在Linux中的用法将使您对环的用途有个好主意。 在x86保护模式下,CPU始终处于4个振铃之一。 Linux内核仅使用0和3: 为什么Linux不使用环1和2:CPU特权环:为什么不使用环1和2? 全局描述符表:GDT条目的内存表,每个条目都有一个对环进行编码的字段Privl。 段寄存器CS,DS等指向GDT中某个条目的索引。

例如,CS = 0表示当前正在执行代码的GDT的第一个条目是活动的。 不能改变自己的戒指! 否则,它可能会将自己设置为振铃0,而振铃将毫无用处。 换句话说,不能修改CR3寄存器,并且分页本身会阻止页表的修改。 出于安全性/易于编程的原因,这可防止一个进程看到其他进程的内存。 无法注册中断处理程序。 通过写入存储位置来配置这些地址,这也可以通过分页来防止。 否则,例如,如果任何程序可以直接从磁盘读取,则文件权限将无用。 更准确地说,要感谢Michael Petch:操作系统实际上可能在环3上允许IO指令,这实际上是由任务状态段控制的。

如果环3首先没有获得许可,则无法授予其这样做的权限。

Linux始终不允许这样做。另请参阅:为什么Linux不能通过TSS使用硬件上下文切换?

当CPU开启时,它会在环0中开始运行初始程序(虽然不错,但是这是一个很好的近似值)。您可以认为此初始程序是内核(但通常是引导加载程序,然后仍在环0中调用内核)。

当用户级进程希望内核为其执行某些操作(例如写入文件)时,它会使用生成中断(例如int 0x80或syscall)的指令来向内核发出信号。 x86-64 Linux syscall你好世界示例:

.datahello_world:.ascii" hello world \ n" hello_world_len =。 -hello_world.text.global _start_start:/ *写入* / mov $ 1,%raxmov $ 1,%rdimov $ hello_world,%rsimov $ hello_world_len,%rdxsyscall

编译并运行:as -o hello_world.o hello_world.S ld -o hello_world.out hello_world.o ./hello_world.out [GitHub上游](https://github.com/cirosantilli/x86-assembly-cheat/blob/ d221ebec3a87ad811bbab48c4073e0bb2cc0df58 / x86-64 / gas / linux / hello_world.S)。发生这种情况时,CPU会调用内核在启动时注册的中断回调处理程序。这是[注册处理程序并使用它的混凝土裸机示例](https://github.com/cirosantilli/x86-bare-metal-examples/blob/18772b1403133b2328d5ad44791445f9859de320/interrupt.S)。该处理程序在环0中运行,该环决定内核是否允许该操作,执行该操作并在环3中重新启动userland程序。x86_64

当使用exec系统调用时(或当内核将启动/ init时),内核准备新的userland进程的寄存器和内存,然后跳转到入口点并将CPU切换到第3环

如果程序试图做一些顽皮的事情,例如写入禁止的寄存器或内存地址(由于页面调度),则CPU还会在环0中调用某些内核回调处理程序。

但是由于用户空间很顽皮,内核这次可能会终止进程,或者发出警告并带有信号。

内核启动时,它将设置一个固定频率的硬件时钟,该时钟会定期产生中断。

该硬件时钟生成运行于环0的中断,并允许它安排要唤醒的用户区进程。

这样,即使进程未进行任何系统调用,调度也可能发生。

您可以肯定一个程序不会干扰另一个程序,因此制作程序更容易。例如,一个用户域进程不必担心由于页面调度而覆盖另一程序的内存,也不必担心将硬件置于另一进程的无效状态。

它更安全。例如。文件权限和内存分离可能会阻止黑客应用读取您的银行数据。当然,这假定您信任内核。

我创建了一个裸机设置,应该是直接操作戒指的好方法:https://github.com/cirosantilli/x86-bare-metal-examples

不幸的是,我没有耐心做一个用户区示例,但是我确实进行了页面设置,因此用户区应该是可行的。我很乐意看到拉取请求。

另外,Linux内核模块在环0中运行,因此您可以使用它们来尝试特权操作,例如读取控制寄存器:如何从程序访问控制寄存器cr0,cr2,cr3?获取细分错误

这是一个方便的QEMU + Buildroot设置,可以在不杀死主机的情况下进行尝试。

内核模块的缺点是其他kthreads正在运行,并且可能会干扰您的实验。但是从理论上讲,您可以使用内核模块来接管所有的中断处理程序并拥有系统,这实际上是一个有趣的项目。

尽管英特尔手册中并未实际提及负环,但实际上有一些CPU模式具有比环0本身更大的功能,因此非常适合“负环”。姓名。

在ARM中,这些环被称为“异常级别”,但主要思想保持不变。

与svc指令(SuperVisor调用)一起输入,在统一汇编之前,该指令以前称为swi,这是用于进行Linux系统调用的指令。您好世界ARMv8示例:

.text.global _start_start:/ *写* / mov x0,1 ldr x1,= msg ldr x2,= len mov x8,64 svc 0 / * exit * / mov x0,0 mov x8,93 svc 0msg:.ascii& #34; hello syscall v8 \ n" len =。 -味精

这是一个具体的裸机示例,该示例注册了SVC处理程序并进行了SVC调用。

例如,Xen允许您在同一系统上同时运行多个操作系统,例如Linux或Windows,并且为了安全性和调试的方便性,它们相互隔离,就像Linux对用户层程序所做的那样。

虚拟机管理程序是当今云基础架构的关键部分:它们允许多个服务器在单个硬件上运行,从而使硬件使用率始终接近100%,并节省了大量资金。

以AWS为例,直到2017年Xen成为新闻时才使用Xen。

ARMv8体系结构参考模型DDI 0487C.a-第D1章-AArch64系统级程序员模型-图D1-1很好地说明了这一点:

随着ARMv8.1虚拟化主机扩展(VHE)的出现,ARM情况发生了一些变化。此扩展允许内核有效地在EL2中运行:

创建VHE的原因是,Linux内核虚拟化解决方案(例如KVM)已经超越Xen(请参见上述的AWS'迁移到上述KVM),因为大多数客户端仅需要Linux VM,并且正如您所想象的那样,所有这些都包含在其中。一个单一的项目,KVM比Xen更简单,而且效率更高。因此,现在在这些情况下,主机Linux内核将充当管理程序。

从图中可以看到,当寄存器HCR_EL2的E2H位等于1时,则启用VHE,并且:

当HCR_EL2.TGE == 1时,我们是常规的主机用户态程序。使用sudo可以照常破坏主机。

当HCR_EL2.TGE == 0时,我们是一个来宾操作系统(例如,当您在主机Ubuntu内部的QEMU KVM中运行Ubuntu OS时。执行sudo不能销毁主机,除非存在QEMU /主机内核错误。

请注意,也许是由于事后观察的好处,ARM相对于x86具有更好的特权级别命名约定,而又不需要否定级别:0为最低级别,3为最高级别。较高的级别往往比较低的级别创建的频率更高。

可以使用MRS指令查询当前EL:当前执行模式/异常级别等是什么?

ARM不需要提供所有异常级别,以实现不需要此功能以节省芯片面积的实现。 ARMv8"异常级别"说:

一个实现可能不包括所有的异常级别。所有实现都必须包括EL0和EL1.EL2和EL3是可选的。

例如,QEMU默认为EL1,但是可以使用命令行选项启用EL2和EL3:qemu-system-aarch64在模拟a53通电时输入el1

2个

英特尔处理器(x86和其他处理器)允许应用程序使用有限的功能。为了限制(保护)IO,内存,端口等关键资源,与操作系统(在本例中为Windows)相关联的CPU提供了特权级别(0为最高特权,3为最低特权),分别映射到内核模式和用户模式。

因此,操作系统在环0(CPU提供的最高特权级别(0))中运行内核代码,并在环3中运行用户代码。

点击“发布答案”,即表示您同意我们的服务条款,隐私政策和Cookie政策

不是您要找的答案? 浏览标记的其他问题或提出自己的问题。