1、Linux内核情景源码分析笔记一、内存寻址#include greeting()printf(Hello, world!n);main()greeting();08048368 : 8048368: 55 push %ebp 8048369: 89 e5 mov %esp,%ebp 804836b: 83 ec 08 sub $0x8,%esp 804836e: 83 ec 0c sub $0xc,%esp 8048371: 68 84 84 04 08 push $0x8048484 8048376: e8 35 ff ff ff call 80482b0 804837b: 83 c4 10
2、 add $0x10,%esp 804837e: c9 leave37 804837f: c3 ret08048380 : 8048380: 55 push %ebp 8048381: 89 e5 mov %esp,%ebp 8048383: 83 ec 08 sub $0x8,%esp 8048386: 83 e4 f0 and $0xfffffff0,%esp 8048389: b8 00 00 00 00 mov $0x0,%eax 804838e: 83 c0 0f add $0xf,%eax 8048391: 83 c0 0f add $0xf,%eax 8048394: c1 e8
3、 04 shr $0x4,%eax 8048397: c1 e0 04 shl $0x4,%eax 804839a: 29 c4 sub %eax,%esp 804839c: e8 c7 ff ff ff call 8048368 80483a1: c9 leave 80483a2: c3 ret 80483a3: 90 nop0x08048368是程序入口1、从段寄存器开始取值,即段选择符= include/asm-i386/segment.h 4 8 =4 #define _KERNEL_CS 0x105 #define _KERNEL_DS 0x1867 #define _USER_CS
4、 0x238 #define _USER_DS 0x2B2、然后根据_USER_CS 0x23找全局描述符表,找到如下的东西450 ENTRY(gdt_table)451 .quad 0x0000000000000000 /* NULL descriptor */452 .quad 0x0000000000000000 /* not used */453 .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */454 .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at
5、0x00000000 */455 .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */456 .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */457 .quad 0x0000000000000000 /* not used */458 .quad 0x0000000000000000 /* not used */3、之后进行线性地址的页式转换Linux实际将持续入口地址映射为自身0x080483680000 1000 0000 0100 100
6、0 0011 0110 1000二、越界访问/* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. * * error_code: * bit 0 = 0 means no page found, 1 means protection fault * bit 1 = 0 means read, 1 means write * bit 2 = 0 means ke
7、rnel, 1 means user-mode */asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; unsigned long page; int write; siginfo_t info; /* get the address */ _asm_(movl %cr2,%0:=r (addre
8、ss); /* Its safe to allow irqs after cr2 has been saved */ if (regs-eflags & (X86_EFLAGS_IF|VM_MASK) local_irq_enable(); tsk = current; info.si_code = SEGV_MAPERR; /* * We fault-in kernel-space virtual memory on-demand. The * reference page table is init_mm.pgd. * * NOTE! We MUST NOT take any locks
9、for this case. We may * be in an interrupt or a critical region, and should * only copy the information from the master page table, * nothing more. * * This verifies that the fault happens in kernel space * (error_code & 4) = 0, and that the fault was not a * protection error (error_code & 1) = 0. *
10、/ if (unlikely(address = TASK_SIZE) if (!(error_code & 5) goto vmalloc_fault; /* * Dont take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. */ goto bad_area_nosemaphore; mm = tsk-mm; /* * If were in an interrupt, have no user context or are running in an * atomic
11、region then we must not take the fault. */ if (in_atomic() | !mm) goto bad_area_nosemaphore; down_read(&mm-mmap_sem); vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma-vm_start vm_flags & VM_GROWSDOWN) goto bad_area; if (error_code & 4) /* * accessing the stack below %esp is always a bug
12、. * The + 32 is there due to some instructions (like * pusha) doing post-decrement on the stack and that * doesnt show up until later. */ if (address + 32 esp) goto bad_area; if (expand_stack(vma, address) goto bad_area;/* * Ok, we have a good vm_area for this memory access, so * we can handle it. *
13、/good_area: info.si_code = SEGV_ACCERR; write = 0; switch (error_code & 3) default: /* 3: write, present */#ifdef TEST_VERIFY_AREA if (regs-cs = KERNEL_CS) printk(WP fault at %08lxn, regs-eip);#endif /* fall through */ case 2: /* write, not present */ if (!(vma-vm_flags & VM_WRITE) goto bad_area; wr
14、ite+; break; case 1: /* read, present */ goto bad_area; case 0: /* read, not present */ if (!(vma-vm_flags & (VM_READ | VM_EXEC) goto bad_area; survive: /* * If for any reason at all we couldnt handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ switch (handle_mm_fault(mm, vma, address, write) case VM_FAULT_MINOR: tsk-min_flt+; break; case VM_FAULT_MAJOR: tsk-maj_flt+; break; case VM_FAULT_SIGBUS: goto do_sigbus; case V
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1