疯狂代码 http://CrazyCoder.cn/ ĵ:http:/CrazyCoder.cn/Linux/Article28335.html
看了LINUX代码,感觉其对内核内存保护做得不是很好,还有感觉大家有些地方理解不对(主要是 LINUX代码看起来样子和实际样子不太样),所以谈谈我对LINUX系统内核空间保护和用户空间和系统空间数据传递代码看法注意我说都是I386体系结构,别体系结构可以看相应代码,不敢保证结果是否是如我所说
LINUX建立进程时候建立了两套段描述符,在文件Segmenth有介绍说明
#ndef _ASM_SEGMENT_H
# _ASM_SEGMENT_H
# __KERNEL_CS 0x10
# __KERNEL_DS 0x18
# __USER_CS 0x23
# __USER_DS 0x2B
#end
个用于内核代码,个用于用户代码运行内核代码时候用内核段描述符号就可以直接访问用户空间,但运行用户代码时候用户段描述符不能访问内核空间,这是用保护模式些机制,具体代码不再介绍不懂就得看看介绍保护模式些书籍了
在用户代码系统时候,进入了系统内核代码,描述符也已经切换到了内核描述符,这时可以直接访问用户空间或者内核空间两者参数数据传递也很简单可以直接拷贝等但看了LINUX代码都知道系统代码里面用户空间和内核空间参数传递是没有这么直接拷贝那是为什么呢?大家想想用户些指针参数等可以指向内核空间如果不加以检测直接拷贝那么用户空间代码就可以通过系统读写内核空间了这显然是不准许所以内核代码里面就采用了统些:copy_from_user/copy_to_user和 __generic_copy_from_user/__gerneric_copy_to_user等而在这些里面实现用户传递指针合法性检测用户参数提供指针等不能指向系统空间这样编写内核代码时候只要这些就能实现了对内核空间保护编写也比较方便这就提醒大家自己编写内核代码时候千万不要图方便直接用户空间和内核空
间参数拷贝其实那些COPY并不是说用户空间和内核空间要如何切换才能拷贝这点我看很多人都没有真正理解
我们再仔细看看那些COPY是如何实现内核空间保护呢原来是在每个进程进程数据结构里面保存了个用户空间范围 current- >addr_limit内核空间在用户空间上面所以只要简单检测用户传递参数访问空间是不是小于等于这个范围就是了下面是相关几个文件相关内容
文件 uaccess:
# MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
# KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
# USER_DS MAKE_MM_SEG(PAGE_OFFSET)
# get_ds (KERNEL_DS)
// 取得内核空间范围
# get_fs (current->addr_limit)
// 取得用户空间范围
# _fs(x) (current->addr_limit = (x))
// 设置用户空间范围
文件 processorh :
typedef struct {
unsigned long seg;
} mm_segment_t;
文件 pageh :
# __PAGE_OFFSET (PAGE_OFFSET_RAW)
# PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
文件page_offh:
#
#def CONFIG_1GB
# PAGE_OFFSET_RAW 0xC0000000
#el d(CONFIG_2GB)
# PAGE_OFFSET_RAW 0x80000000
#el d(CONFIG_3GB)
# PAGE_OFFSET_RAW 0x40000000
#end
// 这个显然可以配置用户空间和系统空间大小
大家看那get_ds、get_fs、_fs等可能不是你刚看到时想那么回事吧?他们看来好象是访问或者设置段其实只是访问或者设置个进程变量罢了
你看那些COPY使得传递些参数只能是指向用户空间那么内核代码对系统些如何办呢那时参数都在内核空间里面呀你仔细看看上面不是有个_fs(x)吗那就是设置这个用户空间只要临时设置用户空间为内核空间范围完了过后恢复就是了你再看下面代码就对那几个_fs作用清楚了吧
->filename is in our kernel space
unsigned long old_fs_value = get_fs;
_fs(get_ds); /* after this we can access the user space data */
open(filename, O_CREAT|O_RDWR|o_EXCL, 00);
_fs(old_fs_value); /* restore fs */
好了原理讲完了代码大家也看明白了我们再看看这种编程好不好呢?其实这种编程显然不好 缺点如下:
1、还没有形成统保护方式对内核空间保护不好内核代码编程不注意话就可能使得用户突破内核空间保护这点编写内核代码同志定得注意用户空间和系统空间拷贝定得用那些COPY不要自己简单直接拷贝
2、内核代码对系统时设置用户空间不好这点如果设置了哪个进程用户空间还没有设置回去时候如果进程用户代码得到运行(应该不太可能吧)那么就突破了内核空间还有如果内核代码不注意忘了恢复用户空间那么也使得内核空间保护失效
其实有好办法实现也很简单就是用个内核全局变量保存用户空间范围这个启动时候根据配置计算好内核时候可以很方便引用这个变量对用户代码参数实现检测用另个内核全局变量来区分是在内核态还是用户态运行如果在内核态再系统就可以不用检测系统参数是在内核空间还是用户空间这样就可以避免修改那个全局变量麻烦
2009-2-12 4:15:45
疯狂代码 http://CrazyCoder.cn/
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.com 版权所有 湘ICP备2023021991号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务