提问人:OSdev 提问时间:2/17/2022 最后编辑:DarkAtomOSdev 更新时间:11/17/2023 访问量:604
用户模式进程的 I/O 指令
I/O instructions by user-mode process
问:
有两种方法可以访问硬件:
- 通过内存映射 I/O (MMIO)
- 通过 I/O 端口
如果用户模式进程直接想要在不使用系统调用的情况下访问 I/O,并且它知道特定的硬件,则无法通过内存映射 I/O 访问它,因为它不在其地址空间中,因此将发生分段错误。但是,使用 I/O 端口来执行此操作呢?由于 I/O 端口不在内存地址空间中,而是由处理器直接执行的指令访问的,会发生什么,进程是否可以访问它们?
答:
短版
不。例如,在 x86 体系结构中,并且是只能在环 0 中运行的特权指令。由于用户模式应用程序在环 3 上运行,因此 CPU 在尝试执行该指令时会出现故障。in
out
加长版
通常,在强制执行内存保护和进程分离的操作系统(如 Windows、Linux、Mac OS,但不包括 DOS)中,用户模式应用程序无法直接访问硬件,并使用系统调用要求内核代表它们执行所需的操作。然后,内核可以决定应用程序是否有权执行上述操作,该操作是否安全等。
如果用户模式应用程序能够做任何通常只能由内核完成的事情,那么它就是一个错误/后门,并且是内核(有时是 CPU 本身)中的巨大安全漏洞。
在 x86 体系结构上,I/O 端口指令在除实模式之外的所有操作模式下都具有特权。尝试执行任何特权指令都会产生故障(具体来说,General-Protection Fault,对应于 )。#GP
INT 0xD
为了允许用户模式驱动程序等进程正常工作,OS 能够通过 2 种方式覆盖 I/O 指令的此特权状态:
- 使用寄存器中的(I/O 权限级别)字段(位 12 和 13)。这是一个介于 0 到 3 之间的数字,用于指定可以运行 I/O 指令的最低特权环。设置为 3 将允许所有进程访问任何 I/O 端口,这是不安全的,并且违背了保护内存等其他所有内容的目的。因此,操作系统通常将此字段设置为 0。
IOPL
FLAGS
IOPL
- 使用任务状态段 (TSS) 结构中的 (I/O 权限位图) 位字段。这只是一个 65536 位的集合,每个位指定是否可以访问 I/O 端口 () 或不能访问 ()。如果用户模式驱动程序需要访问端口,则操作系统可以清除 TSS 中的相应位,并允许用户模式代码仅访问该端口,即使 .如果操作系统不包括所有 65536 位,则 CPU 会假定缺少的位是特权位,因此无法访问。
IOPB
0
1
0xAB
IOPL=0
确定。访问 I/O 端口的权限位于标志寄存器的两个位中。由于每个任务都有自己唯一的标志寄存器副本,因此每个任务可以具有不同的访问权限或 I/O 权限级别 ()。主要功能是执行 I/O(内核模式或用户模式驱动程序)的任务可以从 of 中受益,从而允许任务的所有过程执行 I/O。其他任务通常将 IOPL 设置为 或 ,保留对最特权过程执行 I/O 指令的权限。因此,如果要访问特定任务的 I/O 端口,则应为此任务设置为 I/O 端口。IOPL
IOPL
3
0
1
IOPL
3
在旧版本的 Windows 中,如 Windows XP,可以通过调用并设置为 来完成。NtSetInformationProcess
ProcessInformationClass.ProcessUserModeIOPL
3
不知道更新的版本。
下面是一个示例。
评论