关于linux内核空间保护的问题
在网上看到一篇文章,择选如下:
“看了LINUX代码,感觉其对内核内存的保护做得不是很好,还有感觉大家有些地方理解不对(主要是LINUX的代码看起来的样子和实际的样子不太一样),所以谈谈我对LINUX系统内核空间的保护和用户空间与系统空间数据传递的代码看法.注意我说的都是I386体系结构,别的体系结构可以看相应的代码,不敢保证结果是否是如我所说.
LINUX建立进程的时候建立了两套段描述符,在文件Segment.h有说明.
#ifndef _ASM_SEGMENT_H
#define _ASM_SEGMENT_H
#define __KERNEL_CS 0x10
#define __KERNEL_DS 0x18
#define __USER_CS 0x23
#define __USER_DS 0x2B
#endif
一个用于内核代码,一个用于用户代码.运行内核代码的时候用内核的段描述符号就可以直接访问用户空间,但运行用户代码的时候用户段描述符不能访问内核空间,这是用的保护模式一些机制,具体代码不再介绍.不懂的就得看看介绍保护模式的一些书籍了.
在用户代码调用系统函数的时候,程序进入了系统内核代码,描述符也已经切换到了内核的描述符,这时可以直接访问用户空间或者内核空间,两者的参数数据传递也很简单,可以直接拷贝等。但看了LINUX代码的都知道,系统函数代码里面的用户空间与内核空间参数传递是没有这么直接拷贝的,那是为什么呢?大家想一想,用户调用的一些指针参数等,可以指向内核空间,如果不加以检测直接拷贝,那么用户空间代码就可以通过系统调用读写内核空间了,这显然是不准许的。所以内核代码里面就采用了统一的一些函数:
copy_from_user/copy_to_user和__generic_copy_from_user/__gerneric_copy_to_user等
,而在这些函数里面实现用户调用传递的指针合法性检测,用户参数提供的指针等不能指向系统空间,这样编写内核代码的时候只要调用这些函数就能实现了对内核空间的保护,编写也比较方便。这就提醒大家自己编写内核代码的时候,千万不要图方便直接用户空间与内核空间的参数拷贝,其实那些COPY函数并不是说用户空间与内核空间要怎么切换才能拷贝,这点我看很多人都没有真正的理解。”
想问的是:
“大家想一想,用户调用的一些指针参数等,可以指向内核空间,如果不加以检测直接拷贝,那么用户空间代码就可以通过系统调用读写内核空间了,这显然是不准许的。所以内核代码里面就采用了统一的一些函数: ”------即便能阻止用户空间通过一次指针访问内核空间,那么怎么能够防止通过二次、三次指针访问内核空间?