Linux内核情景源码分析笔记.docx
《Linux内核情景源码分析笔记.docx》由会员分享,可在线阅读,更多相关《Linux内核情景源码分析笔记.docx(15页珍藏版)》请在冰豆网上搜索。
![Linux内核情景源码分析笔记.docx](https://file1.bdocx.com/fileroot1/2022-11/15/44d0e344-6c1d-4c6c-b849-f3684dcf2a64/44d0e344-6c1d-4c6c-b849-f3684dcf2a641.gif)
Linux内核情景源码分析笔记
一、内存寻址
#include
greeting()
{
printf("Hello,world!
\n");
}
main()
{
greeting();
}
08048368:
8048368:
55push%ebp
8048369:
89e5mov%esp,%ebp
804836b:
83ec08sub$0x8,%esp
804836e:
83ec0csub$0xc,%esp
8048371:
6884840408push$0x8048484
8048376:
e835ffffffcall80482b0
804837b:
83c410add$0x10,%esp
804837e:
c9leave
37
804837f:
c3ret
08048380:
8048380:
55push%ebp
8048381:
89e5mov%esp,%ebp
8048383:
83ec08sub$0x8,%esp
8048386:
83e4f0and$0xfffffff0,%esp
8048389:
b800000000mov$0x0,%eax
804838e:
83c00fadd$0xf,%eax
8048391:
83c00fadd$0xf,%eax
8048394:
c1e804shr$0x4,%eax
8048397:
c1e004shl$0x4,%eax
804839a:
29c4sub%eax,%esp
804839c:
e8c7ffffffcall8048368
80483a1:
c9leave
80483a2:
c3ret
80483a3:
90nop
0x08048368是程序入口
1、从段寄存器开始取值,即段选择符
====================include/asm-i386/segment.h48====================
4#define__KERNEL_CS0x10
5#define__KERNEL_DS0x18
6
7#define__USER_CS0x23
8#define__USER_DS0x2B
2、然后根据__USER_CS0x23找全局描述符表,找到如下的东西
450ENTRY(gdt_table)
451.quad0x0000000000000000/*NULLdescriptor*/
452.quad0x0000000000000000/*notused*/
453.quad0x00cf9a000000ffff/*0x10kernel4GBcodeat0x00000000*/
454.quad0x00cf92000000ffff/*0x18kernel4GBdataat0x00000000*/
455.quad0x00cffa000000ffff/*0x23user4GBcodeat0x00000000*/
456.quad0x00cff2000000ffff/*0x2buser4GBdataat0x00000000*/
457.quad0x0000000000000000/*notused*/
458.quad0x0000000000000000/*notused*/
3、之后进行线性地址的页式转换
Linux实际将持续入口地址映射为自身0x08048368
00001000000001001000001101101000
二、越界访问
/*
*Thisroutinehandlespagefaults.Itdeterminestheaddress,
*andtheproblem,andthenpassesitofftooneoftheappropriate
*routines.
*
*error_code:
*bit0==0meansnopagefound,1meansprotectionfault
*bit1==0meansread,1meanswrite
*bit2==0meanskernel,1meansuser-mode
*/
asmlinkagevoiddo_page_fault(structpt_regs*regs,unsignedlongerror_code)
{
structtask_struct*tsk;
structmm_struct*mm;
structvm_area_struct*vma;
unsignedlongaddress;
unsignedlongpage;
intwrite;
siginfo_tinfo;
/*gettheaddress*/
__asm__("movl%%cr2,%0":
"=r"(address));
/*It'ssafetoallowirq'saftercr2hasbeensaved*/
if(regs->eflags&(X86_EFLAGS_IF|VM_MASK))
local_irq_enable();
tsk=current;
info.si_code=SEGV_MAPERR;
/*
*Wefault-inkernel-spacevirtualmemoryon-demand.The
*'reference'pagetableisinit_mm.pgd.
*
*NOTE!
WeMUSTNOTtakeanylocksforthiscase.Wemay
*beinaninterruptoracriticalregion,andshould
*onlycopytheinformationfromthemasterpagetable,
*nothingmore.
*
*Thisverifiesthatthefaulthappensinkernelspace
*(error_code&4)==0,andthatthefaultwasnota
*protectionerror(error_code&1)==0.
*/
if(unlikely(address>=TASK_SIZE)){
if(!
(error_code&5))
gotovmalloc_fault;
/*
*Don'ttakethemmsemaphorehere.Ifwefixupaprefetch
*faultwecouldotherwisedeadlock.
*/
gotobad_area_nosemaphore;
}
mm=tsk->mm;
/*
*Ifwe'reinaninterrupt,havenousercontextorarerunninginan
*atomicregionthenwemustnottakethefault..
*/
if(in_atomic()||!
mm)
gotobad_area_nosemaphore;
down_read(&mm->mmap_sem);
vma=find_vma(mm,address);
if(!
vma)
gotobad_area;
if(vma->vm_start<=address)
gotogood_area;
if(!
(vma->vm_flags&VM_GROWSDOWN))
gotobad_area;
if(error_code&4){
/*
*accessingthestackbelow%espisalwaysabug.
*The"+32"isthereduetosomeinstructions(like
*pusha)doingpost-decrementonthestackandthat
*doesn'tshowupuntillater..
*/
if(address+32esp)
gotobad_area;
}
if(expand_stack(vma,address))
gotobad_area;
/*
*Ok,wehaveagoodvm_areaforthismemoryaccess,so
*wecanhandleit..
*/
good_area:
info.si_code=SEGV_ACCERR;
write=0;
switch(error_code&3){
default:
/*3:
write,present*/
#ifdefTEST_VERIFY_AREA
if(regs->cs==KERNEL_CS)
printk("WPfaultat%08lx\n",regs->eip);
#endif
/*fallthrough*/
case2:
/*write,notpresent*/
if(!
(vma->vm_flags&VM_WRITE))
gotobad_area;
write++;
break;
case1:
/*read,present*/
gotobad_area;
case0:
/*read,notpresent*/
if(!
(vma->vm_flags&(VM_READ|VM_EXEC)))
gotobad_area;
}
survive:
/*
*Ifforanyreasonatallwecouldn'thandlethefault,
*makesureweexitgracefullyratherthanendlesslyredo
*thefault.
*/
switch(handle_mm_fault(mm,vma,address,write)){
caseVM_FAULT_MINOR:
tsk->min_flt++;
break;
caseVM_FAULT_MAJOR:
tsk->maj_flt++;
break;
caseVM_FAULT_SIGBUS:
gotodo_sigbus;
caseV