首页 > 其他 > 详细

JOS 用户态page fault保护处理机制分析

时间:2015-04-25 19:52:05      阅读:302      评论:0      收藏:0      [点我收藏+]

JOS 用户态page fault保护处理机制分析


常常会在用户态触发page fault,如果直接让其因为page fault跌入内核触发panic目测是不是"太残忍了"

你想想,一个刚学会写C程序的童鞋,就经常干 *(int *)0x00.

当然,我只是比较赤果果的表现而已,这位同学可能经常用各种指针,然后指针为初始化亦或等于NULL的时候,对其进行赋值或解引用.总不至于让一个刚学C的人就把整个系统都给挂了吧?恩.我们需要一种保护机制.


可以在用户态触发page fault,跌入内核时,我们可以做点"手脚",不要让他触发panic.

内核稍作处理,程序执行流返回到用户,并提示用户"同学,对非法的地址这么读写都是不对的哇"[ core dump大家一定都很熟悉了...哈哈]


好吧需求背景说完了,进入正题.

faultdie.c用户程序

技术分享

集中精力关注,umain函数.

无非就是在对一个非法地址赋值前进行了一点"小动作"--set_pgfault_handler.


这里传入了一个普通的函数地址handler.我们看看set_pgfault_handler 做了什么

全局变量 _pgfault_handler是个函数指针.初始全局变量被初始化为0.

技术分享

这个函数第一次运行的时候,会为当前进程 thisenv申请一页的内存,把这一页内存,映射到虚拟地址 va.

而后,通过sys_env_set_pgfault_upcall设置了_pgfault_upcall(一个汇编代码的入口)为返回地址.

最后把 _pgfault_handler设置为 handler.


用户触发page fault异常之后,跌入内核态,

struct Trapframe储存在内核栈上

_alltraps会把寄存器各种压栈,然后调用trap(),进而调用trap_dispatch()

于是就会根据触发trap的是什么类型的异常来进行相依的处理,这里是Page fault.

技术分享

于是,开始调用page_fault_handler. 

tf指针还是指向刚刚我们压栈好的内核栈上struct Trapframe的首地址处. 


在page_fault_handler内部.首先会检测我们是不是已经申请了用户异常栈的地址(翻到这篇博客看前面set_pgfault_handler里怎么申请的).

技术分享

只要申请好了用户异常栈,于是就开始各种寄存器的拷贝.把当前内核栈上面的struct Trapframe拷贝到异常栈上去.

反正内核态有权限嘛~

细心的话你会发现,这里的拷贝是夸段的,内核堆栈段的数据拷贝到用户的异常栈上.因为内核有读写权限~


技术分享

把utf指向的用户异常栈的栈顶指针赋值给当前内核栈内struct Trapframe的tf_esp成员,这个家伙会在之后内核弹栈切换进程的时候赋值给esp寄存器,进而设置好用户态的栈顶指针!那时候栈的切换就完成了.


env_run开始重新运行当前进程.env_run会调用 env_pop_tf()把内核栈上的struct Trapframe弹栈.切换进程!


我们来测试,就是切换进程后的栈顶是不是在UXSTACKTOP ( 0xeec00000)下面


测试:

我们把断点设置在handler的入口.看 esp在 UXSTACKTOP下面.

技术分享





JOS 用户态page fault保护处理机制分析

原文:http://blog.csdn.net/cinmyheart/article/details/45271455

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!