完善系统内存安全部分.

Signed-off-by: chen.yang <chen.yang@yuzhen-iot.com>
This commit is contained in:
chen.yang 2022-04-26 15:10:31 +08:00
parent 3caa338f53
commit 8208ffa597
9 changed files with 43 additions and 9 deletions

View File

@ -19,22 +19,56 @@ Intel 引入段寄存器的另一个好处是能够将内粗数据段、代码
![逻辑地址转换](./imgs/8.11_内核内存管理/001.drawio.png)
## 分页机制
## 系统内存安全
Intel 分页机制的实现采用了页目录、页表和页的机制同时将线性地址拆分成不同的区域用于实现页目录、页表、页的寻址。Intel 4k 页分页机制如下:
### 分段管理的内存安全
![分页机制](./imgs/8.11_内核内存管理/002.png)
* DPLDescriptor Privilege Level段描述符的 DPL 域。
* CPLCurrnet Privilege LevelCS 或 SS 寄存器的 Bit0 和 Bit1 位。
* RPLRequest Privilege Level段选择子的 Bit0 和 Bit1。
页可以在真实物理内存中,也可以被换出到外部存储器中。如果程序需要访问该页,则被标记为“脏”,从而引起操作系统内核将改页唤入到物理内存中。
段选择子只是一个带有固定结构的数据,它被加载到对应的段寄存器之后才有实际意义
![Code-Segment Descriptor](./imgs/8.11_内核内存管理/002.png)
Intel x86/64 体系结构下,对应的 CPU 寄存器、段选择子、GDT、LDT、IDT、PDT 和 PT 中包含了许多长度、类型、权限等数据项这些项目由内核设置。当需要访问特定资源时操作系统和内核密切配合决定了访问能否继续下去。如果访问权限不正确或其他检查出错则该访问将被拒绝。这样就保证了内核的安全也保证了进程间内存的相互独立。这部分的具体内容可参考《x86 x64体系探索及编程》邓志或 《Intel 64 and IA32 Architectures Software Developers Manual 3》中的 Paging 部分及 Protection 部分。也就是说,内存的安全访问,由分段机制和分页机制组成。另外,系统的运行级别、指令的特权级别,也是硬件实现系统安全和保护的重要组成机制。
段选择子指定了将要使用 GDT 或 LDT 表中的那一项,段寄存器指定了正在使用的表项。而 GDTR 和 LDTR 指定了当前所用 GDT 和 LDT 所在内存的起始位置。
![Code-Segment Descriptor](./imgs/8.11_内核内存管理/003.png)
## 系统内存安全
段寄存器和段描述符组合形成了线性地址。
![Code-Segment Descriptor](./imgs/8.11_内核内存管理/004.png)
***注x86/64 系列处理器进入保护模式时必须开启段式管理机制;进入长模式时必须开启分页机制。***
程序运行时,必然有需要修改段寄存器的需求,此时需要将载段选择子加载到段寄存器,而段选择子的 RPL 代表了请求的操作级别。Intel 有 4 个操作级别(运行级别/安全级别),数字越大,运行级别越低:
![Code-Segment Descriptor](./imgs/8.11_内核内存管理/005.png)
处理器加载段选择子到段寄存器之前,会检查 CPL、RPL 以及 DPL 的权限,只有当 DPL 同时大于或等于 CPL 和 RPL 时,才允许将段选择子加载进段寄存器。否则将产生通用保护异常。
***注与内存类似的Intel 架构下还有一组为中断和任务准备的数据结构,用于保证中断和任务安全。***
段描述符不仅包含了该段允许的访问级别,也包含了段长度等信息,从而避免越界访问高权限内存的可能,这些机制共同起到了内存保护的作用。
通过段保护机制,可以将内核代码段与用户代码段分割开来。用户代码只有经过特殊的门调用,并进行足够的安全检查后,才能够提升权限,进入内核空间。
### 分页管理的内存安全
Intel 分页机制的实现采用了页目录、页表和页的机制同时将线性地址拆分成不同的区域用于实现页目录、页表、页的寻址。Intel 4k 页分页机制如下:
![分页机制](./imgs/8.11_内核内存管理/006.png)
页可以在真实物理内存中,也可以被换出到外部存储器中。如果程序需要访问该页,则被标记为“脏”,从而引起操作系统内核将改页唤入到物理内存中。
x86/64 分页机制实现了内存的以下权限的管理:
* 只读权限
* 读写权限
该权限由页目录和页表的 RW 域决定:
![Code-Segment Descriptor](./imgs/8.11_内核内存管理/007.png)
## Linux 内存空间的划分
@ -46,7 +80,7 @@ Intel x86/64 体系结构下,对应的 CPU 寄存器、段选择子、GDT、LD
换句话说就是, 最高 1G 的内核空间是被所有进程共享的!
![Linux 虚拟内存空间划分](./imgs/8.11_内核内存管理/004.drawio.png)
![Linux 虚拟内存空间划分](./imgs/8.11_内核内存管理/008.drawio.png)
用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。用户进程只有通过系统调用(代表用户进程在内核态执行)等方式才可以访问到内核空间。
@ -60,7 +94,7 @@ Linux 中 1GB 的内核地址空间又被划分为:
* 固定内存映射区
* 系统保留映射区
![Linux 内核内存映射](./imgs/8.11_内核内存管理/005.drawio.png)
![Linux 内核内存映射](./imgs/8.11_内核内存管理/009.drawio.png)
### 直接映射区与高端内存

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB