首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
Linux内核空间保护与空间数据传递分析
来源:http://www.unix5.com 作者:riechelr_hl 发布时间:2007-07-02  

看了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函数并不是说用户空间与内核空间要怎么切换才能拷贝,这点我看很多人都没有真正的理解。

我们再仔细看看那些COPY函数是怎么实现的内核空间保护呢。原来是在每个进程的进程数据结构里面保存了一个用户空间范围, current- >addr_limit,因为内核空间在用户空间上面,所以只要简单检测用户传递参数访问的空间是不是小于等于这个范围就是了。下面是相关的几个文件的相关内容。

 

   
  文件 uaccess:    

 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 

 #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) 

 #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) 

 #define get_ds() (KERNEL_DS) 

  // 取得内核空间范围 

 #define get_fs() (current->addr_limit) 

 // 取得用户空间范围 

 #define set_fs(x) (current->addr_limit = (x)) 

 // 设置用户空间范围 

  文件 processor.h : 

 typedef struct { 

 unsigned long seg; 

 } mm_segment_t; 

 文件 page。h : 
 
 include        

 #define __PAGE_OFFSET (PAGE_OFFSET_RAW) 

 #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) 

 文件page_offset。h: 

 #include 

 #ifdef CONFIG_1GB 

 #define PAGE_OFFSET_RAW 0xC0000000 

 #elif defined(CONFIG_2GB) 

 #define PAGE_OFFSET_RAW 0x80000000 

 #elif defined(CONFIG_3GB) 

 #define PAGE_OFFSET_RAW 0x40000000 

  #endif 

 // 这个显然可以配置用户空间与系统空间大小

大家看那get_ds()、get_fs()、set_fs()等函数可能不是你刚看到时想的那么一回事吧?他们看来好象是访问或者设置段,其实只是访问或者设置一个进程变量罢了。

你看那些COPY函数使得传递的一些参数只能是指向用户空间,那么内核代码对系统一些函数的调用怎么办呢,因为那时的参数都在内核空间里面呀。你仔细看看上面不是有个set_fs(x)调用吗,那就是设置这个用户空间限制的调用,只要临时设置用户空间限制为内核空间的范围,调用完了过后恢复就是了。你再看下面代码就对那几个set_fs()的作用清楚了吧。

 

       
 ->filename is in our kernel space 

 unsigned long old_fs_value = get_fs(); 

 set_fs(get_ds()); /* after this we can access the user space data */ 

 open(filename, O_CREAT|O_RDWR|o_EXCL, 0640); 
 
 set_fs(old_fs_value); /* restore fs... */

共2页: 上一页 1 [2] 下一页
 
如果您对本文有任何疑问或者建议,请到论坛讨论区发表您的意见: >> 论坛入口
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
  热点文章
·使用 Linux 系统调用的内核命令
·Linux 2.6.11内核文件IO系统调用
·Linux操作系统的源代码目录树结
·Linux用户态与内核态的交互讲解
·Linux内核对I/O端口的管理实现(
·深入分析 Linux操作系统的内核链
·Linux内核可装载模块对设备驱动
·概述Linux系统的驱动框架及驱动
·详解Linux 2.6内核新文件系统变
·Linux系统可卸载内核模块完全指
·FreeBSD手册讲解(一)--配置FreeB
·编译Linux操作系统的内核讲解
  相关文章
·Linux系统内核:修改TCP/IP调优参
·Linux系统内核研究之可执行文件
· Linux操作系统内核指导——虚拟
·Linux操作系统的内核模块全面解
·Linux内核和核心OS组件的测试与
·Linux系统内核模块函数调用及命
·关于Linux内核版本稳定性能测试
·浅谈解析Linux操作系统的内核空
·浅谈关于Linux系统内核的源代码
·借助异常表处理Linux内核态缺页
·编译Linux操作系统的内核讲解
·Linux系统内核网络参数意义以及

本站信息源至:互联网络,均为学习,交流所用,如有版权问题,请联系我们.
站长QQ:397422079 E_mail:riechelr_hl@unix5.com
转载本站内容请注明原作者名.谢谢!