日期:2014-05-16  浏览次数:20654 次

看过linux情景分析的请进,有关用户堆栈扩展的问题
看完用户堆栈的扩展,觉得除了find_vma名称容易误导初学者而不敢苟同外,其实现方式确实很巧妙:找出第一个比addr大的vm_end所在的vm_area_struct结构,有助于用户堆栈的扩展。 然而感觉用户堆栈的扩展还是有点问题:
  情景分析第58页上的源代码可以告诉我们,1、当一个被访问的地址A位于堆栈基址B正下方2、且B—A的值小于等于32时,还得再加上一个限定条件:3、A和B之间没有另外一个虚存区间,满足这3个条件,linux就认为用户堆栈应当被扩展,将A包含其中。
  现在来分析源代码,来证明我刚才得出的结论:
  第58页源码中的151行中使用的vma是find_vma返回的结果(参考55页源码),而find_vma返回的是第一个比A地址要大的vm_end所在的vm_area_struct(昨天讨论的结果),根据上面的第一、三两个限定条件,可以得出结论:此时find_vma返回的地址是堆栈中的一个虚存区间。那么回到58页的151行,则if的判断条件(!(vma->flags & VM_GROWSDOWN))为假,跳过152行。进入153和160行,又根据第二个限定条件跳过161行,执行163行的扩展堆栈的相关代码。
从而证明要使linux扩展堆栈,必须同时满足上述三个条件。
  然而问题也随之而来:
  1、我认为B-A也有可能是为了想扩展堆栈,众所周知,c语言中的参数传递就是通过用户堆栈来进行的,如果刚好此时堆栈已满,而系统再调用一个包含9个(或以上)的int类型的参数,那么堆栈基址B和压栈后的栈顶A的差距肯定大于32,那么此时岂不是达不到扩展堆栈的效果,因为没有满足第2个限定条件。
  2、如果用户程序无意中突然访问了一个恰好符合以上3个条件的地址空间,而并非是进行入栈操作,仅仅访问而已,那么岂不是反而被linux认为要进行堆栈扩展了?
  请高手提示。

------解决方案--------------------
1.首先C中的参数传递并非全靠堆栈,前4个参数在可能的情况靠寄存器传递.第2,通常系统调用的参数数量会被尽可能限制数量,以靠寄存器提高速度
如果真的为9个参数,这时堆栈满,且不用寄存器优化的情况,也么问题.因为参数是1个个进栈的,当然先是函数的返回地址,再是函数参数,所以即使参数
很多,但压入1个进栈后,就会发现堆栈空间满,此时判断条件满足,进行堆栈的扩展.
2.用户程序除了出栈入栈怎么会访问到这个空间呢?程序只会访问堆栈空间内的数据,超出堆栈的对用户程序来说,现在还是空洞,在堆的上方,是不会访问到的