庐山归来,终于有些空闲,见缝插针,今天赶紧把没有写完的“猫蛇之战”补齐。

如果没有读过前两篇或者想复习一下的,请点击:

从猫蛇之战看内核戏CPU

从猫蛇之战再看内核戏CPU

先说明一下,“连续剧”的成本有点高,无论如何,这一篇会把这个问题写完。

回顾一下,最初的问题是“为什么在调试器里读写空指针不会崩溃?” 第一篇通过读源代码的方法揭示了调试器会使用特殊的probe函数:

probe_kernel_read

probe_kernel_write

上一篇通过试验证实,使用probe函数时CPU也会发怒报异常。本篇继续介绍CPU报了异常之后,内核是如何处理这个事件,将其“摆平”的。

在著名的《幽梦影》一书中有很多妙语,其中有不少是关于写作技巧的,比如:

“作文之法: 意之曲折者,宜写之以显浅之词; 理之显浅者,宜运之以曲折之笔; ”

因为这个系列讨论的问题有点复杂和曲折,所以我们是遵循“意之曲折者,宜写之以显浅之词”的原则来写的。

继续贯彻这个原则,直接回答刚才的问题,“摆平”CPU靠的是LINUX内核里一种基于表的异常处理机制,这个机制一般被称为“异常表(Exception Table)”,简称extable。

下面继续结合我们故意访问地址880的例子来理解extable机制。

在CPU查找页表发现线性地址0x880无效而发怒后,它通过IDT表中登记地址跳转到LINUX中处理异常的入口函数,这个入口函数是以汇编语言编写的,名为page_fault,在arch/x86/entry/entry_64.S中。

汇编函数不适合做太多逻辑,只是保存寄存器等信息后便调用C语言编写的do_page_fault。

do_page_fault内部获取CR2的值后便调用__do_page_fault。

__do_page_fault内部的逻辑错综复杂,一个条件判断接着另一个,我们只挑与我们有关的说。

与try{}catch等异常捕捉机制类似,extable机制也是需要编译期就做好准备的。

仔细观察probe函数所调用的拷贝函数,可以看到在它的末尾是有些特别机关的。

注意上图中的两个_ASM_EXTABLE宏,它们就是给危险代码增加保险(异常处理)的“安全带”。

这个宏定义在asm.h,如下图所示。

阅读上面的宏,其作用是在专门描述异常处理器的异常表(__extable)里增加一行,这一行包含三个信息:

from

to

handler

简单来说,前两个都是代码地址,一个是触发异常的,一个是处理异常的,最后一个是函数指针。最后一个是4.6版本内核新增的,为了支持更复杂的处理策略。在_ASM_EXTABLE宏中,使用的是ex_handler_default,选择这个的处理器的效果是:如果from处发生异常,那么就跳转到to处执行,不要panic,也不要发信号,封锁信息,低调处理,像什么都发生一样。

异常表表项的结构体定义在extable.h中,即:

struct exception_table_entry {

int insn, fixup, handler;

};

在extable.c文件中,有ex_handler_default函数的代码,摘录如下:

__visible bool ex_handler_default(

const struct exception_table_entry *fixup,

struct pt_regs *regs, int trapnr)

{

regs->ip = ex_fixup_addr(fixup);

return true;

}

EXPORT_SYMBOL(ex_handler_default);

各位看官请睁大眼睛,到关键地方了。请特别注意加粗的那一行代码,左边写的是regs结构体中的程序指针(ip),右边是处理异常代码的位置(即to参数)。

进一步说,这个regs结构体是在栈上形成的,报告异常时,CPU在准备起飞前先压入当时的执行位置,也就是段寄存器和程序指针,跳到page_fault后,内核中的代码继续把其它寄存器也压入栈,于是就在栈上形成了一个数据结构。对于熟悉NT内核的朋友来说,这相当于那个著名的陷阱帧(TRAP_FRAME)。

这种直接修改程序指针的方法是内核处理危机的杀手锏。经过这样飞针后,__do_page_fault就直接返回了,do_page_fault也返回,到了汇编写的page_fault函数后,就开始恢复寄存器了,也就是把保存在栈上的regs结构体中的寄存器弹出栈,加载到CPU中的物理寄存器。

软件保存的寄存器都恢复好后,执行iret指令。

执行iret指令时,CPU从栈上弹出已经被修改了的ip寄存器,跳过去执行。于是便开始执行to指定的异常处理代码了。这个代码在Linux内核中,被称为fixup,意思是“修修补补”。下图记录了这个特别飞跃的过程。

上面是CPU执行iret前的栈内容,最上面便是IP和CS。单步一下后,CPU执行iret,从栈上弹出CS:IP,跳转到修补代码。

好一个飞跃,这一跃,从随时可能跌入深渊的do_page_fault中跳出,告别了敏感的异常处理上下文,化险为夷了。

这一跳跃,很像是猫蛇之战时小猫的紧急后退。小猫伸爪挑逗毒蛇是为了消耗蛇的体力,被激怒的毒蛇举头袭击,很是危险,小猫巧妙躲闪,灵活后退,华丽转身。

在源代码中,修补函数是有特别标注的,放在特殊的.fixup段中,比如:

.section .fixup,"ax"

.L_fixup_4x8b_copy:

shll $6,%ecx

addl %ecx,%edx

jmp .L_fixup_handle_tail

执行好修补代码片段后,因为保存在栈上的copy函数的返回地址并没有变化,所以当修补函数返回时,线程会返回到probe函数中继续执行。并且,从probe函数看来,copy函数的返回值不为0,代表剩下的字节数,正常copy时,copy函数返回前会将ax寄存器置零,代表完成所有复制任务。因此,probe函数便可以根据copy函数的返回值不为0而返回-EFAULT了,也就是我们在第一篇文章中曾经解释过的这个代码。

讲到这里,第三个问题(Q3)的答案也有了。那么第二个问题呢?如果充分理解了上面描述的过程,那么也可以回答了,留着给大家思考吧。

最后分享一张老雷在庐山所拍的照片吧。

上了很多次庐山,第一次遇上山上的白玉兰盛开,高大的树木上挂满花朵,远远就可以望见。走到近处,花香袭人,坐在石阶上,透过鲜花和树干,还可以欣赏不远处的瀑布,来自庐山主峰汉阳峰的一股清泉,奔流直下,拍击岩石,溅出水珠无数......

***********************************************************

正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生。

欢迎关注格友公众号

从猫蛇之战三看内核戏CPU相关推荐

  1. 从猫蛇之战再看内核戏CPU

    连续写了几天的代码,有些疲倦,吃过晚饭,换个工作方式,继续和大家聊猫蛇之战. 蛇不仅丑陋,而且可能伤人害命,是邪恶的象征.猫与蛇战,代表着讨伐奸邪,是正义之战.猫与蛇战,技艺娴熟,举重若轻,叫人拍手叫 ...

  2. 攻防世界base除4_CCTV5周末看点:周六!女足世界杯1/4决赛连战三场;周日!中超15轮国安碰鲁能...

    这个周末(6.28-6.30),CCTV-5 精彩节目与您相伴,激烈赛事邀您观看,本周末频道看点: ❶女足世界杯1/4决赛,本周六将连战三场 2019年女足世界杯愈演愈烈,本周末1/4决赛将先后迎来三 ...

  3. 张萍萍山东大学计算机科学系毕业生,并行驰骋,放“码”来战!看先导杯大奖赛上山大风采...

    原标题:并行驰骋,放"码"来战!看先导杯大奖赛上山大风采 近日,山东大学计算机科学与技术学院2018级硕士研究生杨林.2020级硕士研究生李威宇组成的团队获得中科院"先导 ...

  4. NR polar Code 三 极化内核(克罗克内积)

    前言: 最近在YooTube 上面看到一个印度教授NPTEL 项目中关于这块的一个公开课. 他的MIMO 也讲的非常棒,推荐看看 https://www.youtube.com/watch?v=rB0 ...

  5. keras_猫狗分类案例(三)_卷机神经网络的可视化(可视化卷积神经网络的中间输出)

    keras_猫狗分类案例(三)_卷积神经网络的可视化 参考: https://blog.csdn.net/Einstellung/article/details/82832872 卷积神经网络的可视化 ...

  6. controller调用controller的方法_SpringCloud Alibaba微服务实战三 - 服务调用

    导读:通过前面两篇文章我们准备好了微服务的基础环境并让accout-service 和 product-service对外提供了增删改查的能力,本篇我们的内容是让order-service作为消费者远 ...

  7. Windows驱动开发学习笔记(三)—— 内核空间内核模块

    Windows驱动开发学习笔记(三)-- 内核空间&内核模块 内核空间 实验 第一步:编译如下代码 第二步:将 .sys 文件拷贝到虚拟机中 第三步:部署 .sys 文件并运行 第四步:创建一 ...

  8. 北京,三看三核对,读懂社保对账单

    转自:http://www.gov.cn/fwxx/sh/2009-06/05/content_1332703.htm 看不懂,怎么对?对什么?在社会保险个人缴费信息对账单(以下简称对账单)陆续寄到个 ...

  9. 各位集美兄得看过来! 利用AI给青春有你2的选手们做数据分析挖掘(三):看图像识选手

    各位集美兄得看过来! 利用AI给青春有你2的选手们做数据分析挖掘(一):爬虫选手信息 各位集美兄得看过来! 利用AI给青春有你2的选手们做数据分析挖掘(二):统计并展示数据 各位集美兄得看过来! 利用 ...

最新文章

  1. FineUI经典项目展示(1)生产在线管理系统
  2. CentOS 下 rpm包与 yum 安装与卸载
  3. java中写入文件的方法
  4. 2017年天津市大学生数学竞赛试题 (理工类)
  5. 线程安全存储以及pthread_getspecific/pthread_setspecific
  6. linux中pad命令,1.1Linux初级命令(附例子)
  7. 【树叶识别】基于matlab BP神经网络树叶类别【含Matlab源码 799期】
  8. 优化后亲测可用!免费下载QQ音乐大部分资源
  9. 吉林大学前卫南区计算机宿舍,睡过双一流学生宿舍后,把宿舍照片分享给你们,看看你们想去的学校宿舍长啥样!...
  10. Python Turtle绘图基础(一)——Turtle简介、绘图窗体与绘图区域
  11. Hackintosh_guide黑苹果
  12. Qt For Android 屏幕常亮
  13. 林格斯添加真人语音库
  14. 【win】系统工具Win PE
  15. bw_mem 内存_TCP:内存不足—考虑调整tcp_mem
  16. 程序员玩‘附近的人’,妹子还没泡,先学会了个专业技能!
  17. MAC 打开所有来源的程序
  18. go实践二十 web开发--表单唯一token 表单验证 防止xss攻击 上传文件 cookie处理
  19. 阿里云服务器安装Clamav免费杀毒工具
  20. 关于mysql出现delete from student where `stu_id` = '1' Error Code: 1175. You are using safe update错误

热门文章

  1. Centos配置DNS服务
  2. 小学起码常识凸显发散级数1-1+1-1+...=0 ——配对图让几百年都无人能识的N最大元一下子浮出水面
  3. 华为od机试真题 JS 实现【热点网站统计】
  4. 工程师、程序员、码农有什么区别?
  5. ubuntu一般命令
  6. WEB应用防火墙与数据库应用防火墙有什么区别
  7. 可以500%提高开发效率的前端UI框架!QUI!
  8. java OOP面向对象编程—2
  9. 人类始终无法抗拒的十种心理
  10. Java判断身份证号码是否正确