在kernel中对文件操作为什么需要get_fs()?
时间:2008-11-02
来源:互联网
例如如下代码:
mm_segment_t old_fs; if(file == NULL) file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644); sprintf(buf,"%s", "The Messages."); old_fs = get_fs(); set_fs(KERNEL_DS); file->f_op->write(file, (char *)buf, sizeof(buf), &file->f_pos); set_fs(old_fs); |
其中,
typedef struct { unsigned long seg; } mm_segment_t; #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL) #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) |
不太了解mm_segment_t这个字段的含义,请指教!
谢谢!
作者: new_learner 发布时间: 2008-11-02
系统调用本来是提供给用户空间的程序访问的,所以,对传递给它的参数(比如上面的buf),它默认会认为来自用户空间,在->write()函数中,为了保护内核空间,一般会用get_fs()得到的值来和USER_DS进行比较,从而放置用户空间程序“蓄意”破坏内核空间;
而现在你要在内核空间使用系统调用,此时传递给->write()的参数地址就是内核空间的地址了,在USER_DS之上(USER_DS ~ KERNEL_DS),如果不做任何其它处理,在write()函数中,会认为该地址超过了USER_DS范围,所以会认为是用户空间的“蓄意破坏”,从而不允许进一步的执行; 为了解决这个问题; set_fs(KERNEL_DS);将其能访问的空间限制扩大到KERNEL_DS,这样就可以在内核顺利使用系统调用了!
good luck!
作者: bshawk 发布时间: 2008-11-02
可能是我说得不太清楚,实际上这个例子中并没有用到系统调用。
这个问题出自保留的帖子:http://linux.chinaunix.net/bbs/thread-738197-1-2.html
源码如下:
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/syscalls.h> #include <asm/unistd.h> #include <asm/uaccess.h> #define MY_FILE "/root/LogFile" char buf[128]; struct file *file = NULL; static int __init init(void) { mm_segment_t old_fs; printk("Hello, I'm the module that intends to write messages to file.\n"); if(file == NULL) file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644); if (IS_ERR(file)) { printk("error occured while opening file %s, exiting...\n", MY_FILE); return 0; } sprintf(buf,"%s", "The Messages."); old_fs = get_fs(); set_fs(KERNEL_DS); file->f_op->write(file, (char *)buf, sizeof(buf), &file->f_pos); set_fs(old_fs); return 0; } static void __exit fini(void) { if(file != NULL) filp_close(file, NULL); } module_init(init); module_exit(fini); MODULE_LICENSE("GPL"); |
并没有用到系统调用,buf也是属于内核空间的。
所以,我还是不太明白这里为什么要get_fs()和set_fs()
还请指教,谢谢!
作者: new_learner 发布时间: 2008-11-02
>>并没有用到系统调用,buf也是属于内核空间的。
但是file->f_op->write的流程可能会调用access_ok->__range_ok
而__range_ok会判断访问的buf是否在0~addr_limit之间,如何是就ok,否则invalid,这显然是为用户准备的检查。
addr_limit一般设为__PAGE_OFFSET,在内核空间,buf肯定>__PAGE_OFFSET,必须修改addr_limit,这就是set_fs的由来。
作者: qtdszws 发布时间: 2008-11-02
搞明白了:)
作者: new_learner 发布时间: 2008-11-03
谢谢LS兄弟的解释!
可能是我说得不太清楚,实际上这个例子中并没有用到系统调用。
这个问题出自保留的帖子:http://linux.chinaunix.net/bbs/thread-738197-1-2.html
源码如下:
#include
#includ ...
如qtdszws 所说,此处虽然不是系统调用,但是顺着file->op->write()进入会进行用户空间参数检查access_ok.
假设是ext3文件系统,ext3_file_operations里面的两个操作函数字段:
(fs/ext3/file.c)
const struct file_operations ext3_file_operations = {
...
.write = do_sync_write,
...
.aio_write = ext3_file_write,
...
}
顺着这个线下去(2.6.20),
file->fop->write() =>do_sync_write() => ext3_file_write() => generic_file_aio_write() =>__generic_file_aio_write_nolock() ,
会在__generic_file_aio_write_nolock()函数中对刚开始file->f_op->write()传进来的参数进行access_ok()检查
作者: kissGNU 发布时间: 2008-11-03
The value of the addr_limit.seg field can be dynamically changed by the get_fs and set_fs macros; this allows the kernel to bypass the security checks made by access_ok( ), so that it can invoke system call service routines, directly passing to them addresses in the kernel data segment.
作者: new_learner 发布时间: 2009-04-22
Kernel System Calls
~linux/include/asm-x86_64/uaccess.h 有关get_fd() get_fs() set_fs()的定义
- /*
- * The fs value determines whether argument validity checking should be
- * performed or not. If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons, these macros are grossly misnamed.
- */
-
- #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-
- #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFFFFFFFFFUL)
- #define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
-
- #define get_ds() (KERNEL_DS)
- #define get_fs() (current_thread_info()->addr_limit)
- #define set_fs(x) (current_thread_info()->addr_limit = (x))
-
- #define segment_eq(a,b) ((a).seg == (b).seg)
-
- #define __addr_ok(addr) (!((unsigned long)(addr) & (current_thread_info()->addr_limit.seg)))
作者: zzyhrb 发布时间: 2010-08-02
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28