`
memorymyann
  • 浏览: 267670 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

linux学习三越界访问

阅读更多

之前看过了内存管理的数据结构,下面通过越界访问来熟悉下这些数据结构。(之前一直没有让大家去下载内核源代码,因为我列的比较详细,接下来的东西,大家自己去http://www.kernelnewbies.org/下载内核源代码,然后结合起来看)

页式存储管理通过页面目录和页面表将线性地址转换成物理地址。如果在这个过程中遇到某种阻碍。这种阻碍的情况有很多,我们举个实际例子,我们通过系统调用mmap()将一个已打开文件印射到内存,然后又撤销,在虚存空间上留下了个空洞,程序又再次访问这个内存,从而就会导致失败。出错后,会产生一个页面出错异常。CPU就运行到了页面出错异常程序的do_page_fault()的入口处。代码定义于arch/i386/mm/fault.c

代码很长,我就不贴了,我只贴我们所发生的情况而会执行到的代码。

fastcall void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)//越界访问,程序入口。reges中断前,CPU各寄存器副本,error_code详细原因,看英文注释
程序运行此函数,第一个执行的语句是address = read_cr2(); //也可能是__asm__("movl %%cr2, %0":"=r" (address));但2者效果都是将CPU的CR2寄存器的内容读取到address中,CPU将导致映射失败的线性地址放到了寄存器cr2,因此address便是导致映射失败的线性地址。

接下来执行的语句是:tsk = current;其中current是个宏操作,将当前进程的进程控制块(PCB)task_struct返回。有了失败的线性地址和进程这些信息后,我们就可以开始下面的操作了。

我们之前说过我们的映射失败是由于我们撤销了这个内存,之后又再次访问。该方法之间的很多代码是检测是否其它原因造成的映射失败,这里就不讨论了,我们代码将会执行到mm = tsk->mm;看上次数据结构我们便知道mm指向的是映射失败进程的虚存空间描述的数据结构mm_struct。接下来我们程序便会运行到if (!down_read_trylock(&mm->mmap_sem)),这里就是进程间互斥访问mm_struct,前面的数据结构中已经提到了mmap_sem 的作用,判断没人访问就进入mm_struct资源,同时对该资源加锁。

接下来运行到vma = find_vma(mm, address);这个便是寻找虚存空间中第一个地址大于给定地址address的区间。找到后返回虚存区间,对应的数据结构就是vm_area_struct。当然可能存在找不到的情况,不过我们目前这种情况不属于这种,暂不讨论。

接下来我们找到了虚存区间vma,说明我们的地址印射已经建立起来,那么代码就会执行到

if (!vma) //这个就是我们所说的没有找到虚存空间的情况了,我们目前不属于这种情况
        goto bad_area;
if (vma->vm_start <= address)   //已经找到了vma,且vma的起始地址小于等于映射失败地址,就表示该地址落在了这个虚存区间内,我们就进一步转向good_area中去查找原因。这种情况映射已经建立,不是我们目前发生的情况
        goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
        goto bad_area;

我们详细说下第3个 if条件,我们上面的数据结构说到了vm_flags这个项,用于保存区间权限和其它一些属性。vm->flags&VM_GROWSDOW为0表示找到的区间并非堆栈区,我们的情况属于这种情形。这里插下堆栈区,他是高地址上起始的,自上向下扩展。我们发生的情况目前处于读入文件内容,放到数据段,后来又撤销了。这样释放了内存。现在再去访问这个地址,地址很自然是在2个区间之间的那块空洞中。因此我们代码便进入了bad_area中。

bad_area:
    up_read(&mm->mmap_sem); //不需要对mm进行互斥操作了,因此,释放他

bad_area_nosemaphore:
    /* User mode accesses just cause a SIGSEGV */
    if (error_code & 4) {
        /*
         * Valid to do another page fault here because this one came
         * from user space.
         */
        if (is_prefetch(regs, address, error_code))
            return;

        tsk->thread.cr2 = address;
        /* Kernel addresses are always protection faults */
        tsk->thread.error_code = error_code | (address >= TASK_SIZE);
        tsk->thread.trap_no = 14;
        force_sig_info_fault(SIGSEGV, si_code, address, tsk);
        return;
    }

error_code中保存的是失败的详细信息,作者为它加了注释,我们看下注释:

/*
 * 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 kernel, 1 means user-mode
 *    bit 3 == 1 means use of reserved bit detected
 *    bit 4 == 1 means fault was an instruction fetch
 */

我们的情况是用户模式下发生的,因此bit2=1,因此我们的代码运行便会进入到 if (error_code & 4)内部,内部代码大致执行的情况是设置task_struct,向该进程发出一个软中断,至此,一次例外服务程序便结束了。

如果有错误或者问题的话,请留言指出。

分享到:
评论

相关推荐

    Linux C语言 内存越界问题总结

    内存越界问题是项目开发中比较难解决的问题,下面就简单的描述下内存越界的种类、现象及引起的原因。

    linux内存调试.pdf

    很多系统的稳定性问题与内存相关, 特别是内存的越界访问, 本节介绍几种kernel原生的内存调试技术

    Linux+C语言+内存越界问题总结[文].pdf

    内存越界可以分为三种: 1. 栈溢出:主要现象:某些全局变量被修改,某些任务不能正常工作,函数调用不正常,某些局部变量被修改。主要原因:线程堆栈开辟的太小,定义的太大的局部变量,函数调用太深。 2. 堆栈...

    基于机器学习的露天矿山越界开采智能预警研究与应用.pdf

    "基于机器学习的露天矿山越界开采智能预警研究与应用" 本文研究基于机器学习的露天矿山越界开采智能预警系统,旨在解决露天矿山开采监管中的人工方式存在的诸多问题。该系统基于双目摄像头以及图像处理技术,利用...

    (8.4)--越界访问和缓冲区溢出攻击1

    数组元素可使用指针来访问,因而对数组的引用没有边界约束越界访问和缓冲区溢出C语言程序中对数组的访问可能会有意或无意地超越数组存储区范围而无法发现。共24字节越界

    C++中new的越界访问问题

    越界访问指访问了不是程序申请的内存区域,比如申请了5个字节的char数组,结果读写数据的第六个元素,或者访问了释放后的内存等等。

    sprintf,vsprintf越界问题

    三、解决方法 要解决 sprintf 和 vsprintf 越界问题,可以采取以下几种方法: 1.仔细检查所有调用 sprintf 和 vsprintf 的地方,确保传入的参数不会超过目的地址的长度限制。 2.使用带有长度检查的字符串格式化...

    C/C++ 避免数组越界的方法

    主要介绍了C/C++ 避免数组越界的方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

    IOS防止数组越界

    移动开发中会经常遇到数组越界问题,导致程序闪退,导致应用界面不友好。我们可以从根本上解决数组越界导致的程序闪退

    Java数组越界问题实例解析

    主要介绍了Java数组越界问题实例解析,具有一定参考价值,需要的朋友可以了解下。

    java 字符串索引越界异常(StringIndexOutBounds)

    java 字符串索引越界异常(StringIndexOutBounds) java 字符串索引越界异常(StringIndexOutBounds)

    NSArray越界崩溃解决方法

    比较完美的解决了数组越界的问题, 在debug模式下会崩溃 , 在release不会崩溃 , 开发过程中 , 方便调试 , 正式环境中 减少崩溃.

    Linux下的段错误Segmentationfault产生的原因及调试方法经典.pdf

    段错误是 Linux 系统中的一种常见错误,它的产生非常常见,例如访问 0 地址、数组越界、变量类型不一致等。解决方法是通过 gdb 调试程序,并使用“bt”命令来查看调用堆栈,找到出错的位置。同时,我们也可以通过...

    基于视频的矿井行人越界检测系统

    针对目前矿井行人监测方法存在检测准确度不理想、报备信息少的问题,设计了基于视频的矿井行人越界检测系统。该系统以混合高斯背景建模为基础,利用行人越界检测算法识别出视频流中运动的行人目标,并在识别目标的基础...

    定位多线程内存越界问题实践总结

    最近定位了在一个多线程服务器程序...整个定位过程遇到的问题和解决办法对于多线程内存越界问题都很典型,简单总结一下和大家分享。只对终极组合秘技感兴趣的同学,请直接阅读最后一节,其他的章节写到这里是为了科普。

    走下神坛的内存调试器--定位多线程内存越界问题实践总结[整理].pdf

    mprotect 是一个 Linux 系统调用,用于保护内存区域。使用 mprotect 可以保护内存区域,使其不能被修改,从而防止多线程内存越界问题的发生。 知识点4:libsigsegv 的使用 libsigsegv 是一个信号处理库,用于捕捉...

    hive2.1.1中orc格式读取报数组越界错误解决方法

    hive2.1.1orc格式读取报数组越界错误,替换jar包。hive-exec-2.1.1-cdh6.3.2.jar、hive-orc-2.1.1-cdh6.3.2.jar。分发各个服务器即可。

    java 数组下标越界异常(ArrayIndexOutOfBoundsException)

    java 数组下标越界异常(ArrayIndexOutOfBoundsException) java 数组下标越界异常(ArrayIndexOutOfBoundsException)

    jiancha.rar_数组 越界 检查

    设计一个用于检查数组在使用时下标是否越界的类,如越界给出提示。(知识点:下标运算符的重载)。

Global site tag (gtag.js) - Google Analytics