Linux内核情景分析_内存管理_越界访问

情景假设:

在堆内存中申请了一块内存,然后释放掉该内存,然后再去访问这块内存。也就是所说的野指针访问。

情景分析:

Cpu使用页面目录和页表把一个线性地址转化成一个物理地址失败时,就会产生一个缺页中断。经过一系列的调用,最后转换到缺页中断的处理程序/arch/i386/mm/fault.cdo_page_fault()函数中。

下面分析下 do_page_fault函数

 

asmlinkage  do_page_fault(pt_regs  regs,  unsigned long  errorcode )

{

//根据i386的架构,当缺页中断产生时,会把映射错误的地址放到Cr2寄存器中。

//先取得地址

unsigned 
long address;

__asm__(
"movl %%cr2,%0":"=r" (address));


//下面判断映射错误造成的原因

task_struct  
*tsk;

mm_struct  
* mm;

tsk 
= current;

mm  
= tsk.mm;


if(!mm  || in_interupt()) goto  no_context;


vma_area  vma 
= find_vma(mm, address);

//如果没有找到,必属于越界访问。因为堆栈是从3G高地址向下扩展,如果在堆 //栈中都不存在一个地址空间的结束地址高于address,那么该地址必定在于系统空 //间空间,从用户空间访问系统空间必定属于越界访问。

If(
!vma)  goto bad_area;


//如果找到了一块虚拟地址空间并且起始地址小于address,说明这块地址被映射 //了,那么继续调查映射失败的原因。

If(vma
->startaddress <= address )  goto  good_area;


 
//如果找到了一块虚拟地址空间,那么判断这块地址上方的空洞是否是堆栈区,  //判断方法是堆栈区的虚拟地址空间都存在一个VM_GROWDOWN,如果不是说  //明空洞是由于地址映射撤销导致的,所以属于越界访问,也就是我们讨论的情  //景。

If(
!(vma->vm_flags & VM_GROWDOWN)) goto bad_area;



//如果上方空洞地址是堆栈区,那么说明堆栈需要扩展。

if (expand_stack(vma, address))

goto bad_area;



bad_area:

// 设置task_struct的一些变量。然后发送一个SIGSEGV信号

up(
&mm->mmap_sem);


bad_area_nosemaphore:

/* User mode accesses just cause a SIGSEGV */

if (error_code & 4) {

tsk
->thread.cr2 = address;

tsk
->thread.error_code = error_code;

tsk
->thread.trap_no = 14;

info.si_signo 
= SIGSEGV;

info.si_errno 
= 0;

/* info.si_code has been set above */

info.si_addr 
= (void *)address;

force_sig_info(SIGSEGV, 
&info, tsk);

return;

}


}

 

posted @ 2010-04-28 14:14  甜甜嘟嘟  阅读(1543)  评论(0编辑  收藏  举报