51Testing软件测试网,s!U r K.oCM-vm dotraplinkage void __kprobes T4_#fR%UrB0do_page_fault(struct pt_regs *regs, unsigned long error_code) )y*A.?9`[0{ q
j4{Dz7AF0 struct vm_area_struct *vma; alDX3j~(t0 struct task_struct *tsk; yLN?hgg0 unsigned long address;51Testing软件测试网GHV_$ejq struct mm_struct *mm;
Ai$g9j,c~}*N+Z8m0 int write; uo ~*LqNKB0 int fault; $tzJr2`;Fs7S#x0
51Testing软件测试网)Z:hz'uala tsk = current; //获取当前进程 &S\AOy2n-D:G0 mm = tsk->mm; //获取当前进程的地址空间51Testing软件测试网|c3XT-g { ~
51Testing软件测试网6j
txZa%X /* Get the faulting address: */51Testing软件测试网r7QT)};Hv address = read_cr2(); //读取CR2寄存器获取触发异常的访问地址 W1m'tFZ1gB%yP0
!w }i*AF9g0 ... }W#V)V
{z[+p
@0 ... 6lr2N\CCN0 ...51Testing软件测试网Jxa)zL.? ...51Testing软件测试网|w'c1PH
Tr
H#J U?Xw0 vma = find_vma(mm, address);//试图寻找到一个离address最近的vma,vma包含address或在address之后 ;j&q;C
f5n7u(Y`(b0
;Mw4p$l,qXx#a0 /*没有找到这样的vma则说明address之后没有虚拟内存区域,因此该address肯定是无效的, 5yA%z~Lsz0 通过bad_area()路径来处理,bad_area()的主体就是__bad_area()-->bad_area_nosemaphore()*/51Testing软件测试网P_s/fu~`1@H if (unlikely(!vma)) {51Testing软件测试网
n0J$qC5pB bad_area(regs, error_code, address);51Testing软件测试网~/v#se1Q|${9ZsI]9dd return; G/NS Rm8Q0 } E$j6h1Q:_0 /*如果该地址包含在vma之中,则跳转到good_area处进行处理*/51Testing软件测试网(Qw8\]@M if (likely(vma->vm_start <= address))51Testing软件测试网8K\Fb7umD*H goto good_area; O:W fb9l]+jL@!L|0
$E,W[v1i2]b
vs H5|0 /*不是前面两种情况的话,则判断是不是由于用户堆栈所占的页框已经使用完,而一个PUSH指令 ?2iUhf3n%p-M;S0 引用了一个尚未和页框绑定的虚拟内存区域导致的一个异常,属于堆栈的虚拟内存区,其VM_GROWSDOWN位 I7wxzoy
v0 被置位*/ U
fr#[j*jx(Q0 if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { e1@ f,W
K5l7K0 bad_area(regs, error_code, address);//不是堆栈区域,则用bad_area()来处理51Testing软件测试网&K#AY
[2l{gG*k-y return; ;Fz&d0n|E0 } 4B,rV:\!d ?0 if (error_code & PF_USER) {//必须处于用户空间51Testing软件测试网6y {C$BFh![2j /*51Testing软件测试网?8e$L'~s * Accessing the stack below %sp is always a bug. J%_a!c^F&j'bO4i0 * The large cushion allows instructions like enter51Testing软件测试网.GKl@~n~3a T * and pusha to work. ("enter $65535, $31" pushes ;Y%zT xO
a?4T1c_0 * 32 pointers and then decrements %sp by 65535.) %M#fCQ r$^8x2j0 */51Testing软件测试网"x&E
M wEil4O /*这里检查address,只有该地址足够高(和堆栈指针的差不大于65536+32*sizeof(unsigned long)),51Testing软件测试网_|X Qzm(D 才能允许用户进程扩展它的堆栈地址空间,否则bad_area()处理*/ +D+hsW dq(E/Mk0 if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) { pR@+F oxQ#n0 bad_area(regs, error_code, address);51Testing软件测试网$S2`s5|D ?0a*j7z return;51Testing软件测试网D7PWhM5L&u } W'Y)YFt1\([hZfq[0 }51Testing软件测试网oe-D%R4x9T if (unlikely(expand_stack(vma, address))) {//堆栈扩展不成功同样由bad_area()处理 )k1oH
~@0 bad_area(regs, error_code, address); V%DsyVoz }0 return; kt*@
l(W.n r&xA0 }51Testing软件测试网0E#W!nI0_-G2P*]
51Testing软件测试网z-l3fV3k{-yP /* N&f c'Z8MyQ2{0 * Ok, we have a good vm_area for this memory access, so51Testing软件测试网ky#L4X*?2_3K * we can handle it.. 5^*F3l^2BCv!`c3t0 */51Testing软件测试网z1XE!v4|Wb
N good_area:51Testing软件测试网Bg
F GI+z%PKI write = error_code & PF_WRITE; o1K#Z5c6?-z.A:j ik:G0
6XL+w%E)V fD0 /*访问权限不够则通过bad_area_access_error()处理,该函数是对__bad_area()的封装,只不过
|