Chinaunix

标题: 关于在64位系统中进行内核内存隔离保护的问题 [打印本页]

作者: mordorw    时间: 2012-11-02 14:08
标题: 关于在64位系统中进行内核内存隔离保护的问题
大家都知道,用户态程序间内存有隔离,同一个进程内部的内存块间glibc也可能做了隔离。
在X86 32bits系统中,内核ZONE_NORMAL内存区是连续的整块内存(32bits系统内核内存虚拟地址空间有限),而vmalloc不同内存区之间有空白页面隔离

那么在64bits系统中,内核内存虚拟地址空间大小不再是问题,为何不在内存区间增加空白页面隔离和保护?除了必须要连续的物理地址比如驱动,其它比如内核栈,进程数据结构等,
都可以空白页面隔离和保护,一旦有内存越界,很容易检测到。

尤其是对于写越界,在ZONE_NORMAL内存区写越界时根本不会出现问题,而是在随后的某个时间访问被越界写的内存时才出问题(死机等),很随机,这时已经很难查了。比如内核栈溢出
作者: amarant    时间: 2012-11-03 09:53
内核大部分的地址都是物理-虚拟直接映射的。你的意思是给虚拟地址中做一片空白页面做保护吗?那么相应的物理地址也不能直接用了。你觉得这样的损失算不算大
作者: smalloc    时间: 2012-11-03 13:30
什么是越界?这是个问题
作者: lenky0401    时间: 2012-11-04 19:40
LZ的想法不错
作者: mordorw    时间: 2012-11-05 09:18
本帖最后由 mordorw 于 2012-11-05 09:20 编辑
amarant 发表于 2012-11-03 09:53
内核大部分的地址都是物理-虚拟直接映射的。你的意思是给虚拟地址中做一片空白页面做保护吗?那么相应的物理 ...


那只有连续的映射(线性映射)才有这个障碍。
实际上,只有驱动才需要(线性映射)。象内核的数据结构,比如threadinfo,根本不需要线性映射,所以可以在其中插入空白虚拟页面


内核内存越界比用户态进程越界难查得多,影响也大得多
作者: stephen_du    时间: 2012-11-05 11:07
mordorw 发表于 2012-11-02 14:08
大家都知道,用户态程序间内存有隔离,同一个进程内部的内存块间glibc也可能做了隔离。
在X86 32bits系统中 ...


你说的是内存的hole技术,但是这个只在特殊的场合应用。
作者: mordorw    时间: 2012-11-05 12:11
stephen_du 发表于 2012-11-05 11:07
你说的是内存的hole技术,但是这个只在特殊的场合应用。


哪些特殊的场合应用,为何要限定特殊的场合
作者: stephen_du    时间: 2012-11-05 13:02
mordorw 发表于 2012-11-05 12:11
哪些特殊的场合应用,为何要限定特殊的场合


Hole术是 通 过 在 内存 区 之 间 保 留一 个 空 洞 来捕获非法越界访问 , 而保证各个 内存区之间的安全从隔离 。

我记得内核直接映射的896M~896+16M就是一个hole,用于保护low memory与high memory之间的越界问题。
有点模糊了,数字可能不精确
作者: mordorw    时间: 2012-11-05 13:19
stephen_du 发表于 2012-11-05 13:02
Hole术是 通 过 在 内存 区 之 间 保 留一 个 空 洞 来捕获非法越界访问 , 而保证各个 内存区之间的安全 ...



vmalloc分配的内存区之间都有个空 洞页面 来捕获非法越界访问 。我的问题是为何不把这个技术也用到kmalloc,以及各种cache/buffre,内核栈分配, 进程数据结构分配(64位地址空间情况下)。
作者: stephen_du    时间: 2012-11-05 13:36
mordorw 发表于 2012-11-05 13:19
vmalloc分配的内存区之间都有个空 洞页面 来捕获非法越界访问 。我的问题是为何不把这个技术也用到km ...


系统物理内存大于896M的时候vmalloc分配的是经过remap后的高于896M的内存即高端内存,这种内存往往不是物理上连续的内存;
如果系统物理内存小于896M,那么vmalloc与kmalloc分配的内存都是物理上连续的,即二者是等价的。

你所说的“vmalloc的内存区间之间有个空洞页面”, 这个我不知道
作者: amarant    时间: 2012-11-05 21:27
mordorw 发表于 2012-11-05 09:18
那只有连续的映射(线性映射)才有这个障碍。
实际上,只有驱动才需要(线性映射)。象内核的数据结构,比 ...


你确定只有驱动需要线性映射吗?
据我所知,驱动访问IO口是通过ioremap,恰好是通过非线性映射的。
那么你认为线性映射的作用是什么呢?为什么要把大多数的地址用做线性映射呢?
既然把大多数的地址用做线性映射,那为什么你觉得大部分时候都在使用非线性映射的地址呢?
而且,再据我所知,在非线性映射的地址管理中,即vmalloc区域,已经使用了内存页分割的机制。
作者: mordorw    时间: 2012-11-06 09:23
本帖最后由 mordorw 于 2012-11-06 09:35 编辑
amarant 发表于 2012-11-05 21:27
你确定只有驱动需要线性映射吗?
据我所知,驱动访问IO口是通过ioremap,恰好是通过非线性映射的。
那 ...



我的看法,线性映射效率高点(当然内核启动可能还是需要线性映射,但是像启动之后的部分可以不使用线性映射)
但是可靠性往往比性能更为重要,且性能往往可以通过硬件发展来提升。所以使用 非线性映射+空洞页 来隔离内存区域



正如你所说,vmalloc区域正是这么做的。

是否可以把vmalloc区域的这个做法进行推广。

即便是使用了线性映射,那么像内核栈、thread_info这样的东西也可以使用空白页面隔离来保护内核栈等关键数据结构,为了系统的可靠性和可维护性,浪费一点便宜的物理内存真不算什么

大拿, 你怎么看
作者: 懂医术的厨师    时间: 2012-11-06 10:12
回复 12# mordorw

至少在目前kernel的实现中,线性映射部分,虚拟地址有hole就意味着物理内存的浪费
再讨论就是上升到学院派和工程派的争论了,没意思。
   
作者: amarant    时间: 2012-11-06 20:39
mordorw 发表于 2012-11-06 09:23
我的看法,线性映射效率高点(当然内核启动可能还是需要线性映射,但是像启动之后的部分可以不使用线 ...


其实还有一个可能性,你可能没有考虑到。在直接映射的这些地址中,并不是只有内核才访问他们的。如果按照你这么实现的话,那么用户分配物理地址将会非常纠结。对不对?
关于你说的安全性,其实那样做并不会不安全。因为栈溢出第一结果就是把threadinfo给覆盖了。那么很容易就panic了。
非大拿,一点拙见,还请指正
作者: mordorw    时间: 2012-11-07 13:09
amarant 发表于 2012-11-06 20:39

其实还有一个可能性,你可能没有考虑到。在直接映射的这些地址中,并不是只有内核才访问他们的。如果按 ...


那就把敏感数据区的物理内存锁死,不给用户进程用

越界踩到thread_info可能不会立马就panic,你可以做个试验看。如果总是立马就panic,就不需要讨论这个话题了
作者: amarant    时间: 2012-11-07 19:07
回复 15# mordorw


如果把thread_info都冲了,要设隔断区干吗呢?这种情况是一定不能发生的。一般来说thread_info冲了,因为访问这个进程的数据就是根据这个基础上的。不出意外是很快就panic了。如果没有的话,就算有隔断区,难道能让危险减少一点吗?还不如把隔断区用来扩大栈的空间呢。你觉得呢?
作者: mordorw    时间: 2012-11-08 08:47
目的不是去减少危险,而是去实时地检测到错误的发生




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2