一、linux内核、用户空间的内存划分:
如下图:内核空间划分0~3G为用户空间,3~4G为内核空间。详细请参考《Linux用户空间与内核空间》
注意:内核地址空间的范围是0xC0000000 ~ 0xFFFFFFFF
二、异常内存访问导致的oops:
1、Unabletohandlekernelpagingrequestatvirtualaddress00000000
=====》越出内核地址空间范围,原因是由于使用空NULL指针
2、Unabletohandlekernelpagingrequestatvirtualaddress0110
=====》越出内核地址空间范围,原因是的内存越界导致该指针
所在内存被破坏了。接下来的困难是在什么地方这个内存被修改?为什么被修改?
3、Unable to handle kernel paging request at virtual address c074838c
=====》没有越出内核地址空间范围,为什么也oops?
这种情况我称之为:试图篡改受限制内存。比如:声明为const的变量!
还有其它形式的受限制内存吗?
三、访问受限制内存导致oops:
const在C语言当中声明一个变量为只读,
如果试图直接修改const变量,build阶段编译器,就检查出来,并报read only错误,
如下:
const int i = 1;
i = 10;
build error: assignment of read-only variable "i" //只读变量赋值错误
但是如果通过指针间接修改const变量,编译器是检查不出来的。
如下:
const int i = 1;
int *p = &i;
*p = 10;
不出所料地编译成功了! 但不要高兴,这样的代码是有隐患的!
因为,很显然,我们将变量声明为const,是希望它能受到保护的!
既然编译器检查不出这种隐患,由谁负责保护它呢?
我想,linux只有运行时,由mm模块来保护声明为const的变量了!!!???
但遗憾的是,linux 3.4.5以前的版本一直没有这个保护功能,应该老版本linux自身的漏洞吧!
直到约linux 3.4.67 (android 4.4)才有运行时保护受限制内存的功能。
如果这么简直地直接使用指针显示地间接修改一个某const变量,还是很容易查出来的。
下面举一个掩蔽的例子:
static struct file_operations *new_file_operations = NULL;
static struct file_operations original_file_operations = {0};
ssize_t new_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
if(!isCanWrite(filp))
{
return -ENOSPC;
}
return original_file_operations.write(filp, buf, len, ppos);
}
static int __init lowmemdetect_init(void)
{
myfile = filp_open("/data", O_WRONLY | O_CREAT, 0);
if (!IS_ERR(myfile) && (myfile->f_op != NULL))
{
original_file_operations.write = myfile->f_op->write; //it point to do_sync_write()
original_file_operations.aio_write = myfile->f_op->aio_write; //it point to ext4_file_write()
new_file_operations = myfile->f_op; //it point to ext4_file_operations
//这句掩蔽地间接将new_file_operations指针指向kernel\fs\ext4\file.c的一个const变量ext4_file_operations
new_file_operations->write = new_file_write; //modify ext4_file_operations->write
//这句掩蔽地间接修改const变量ext4_file_operations,它在新版本linux 3.4.67 (android 4.4)中运行导致oops 。
filp_close(myfile, NULL);
}
}
/* 声明const变量:
kernel\fs\ext4\file.c
const struct file_operations ext4_file_operations = {
.llseek = ext4_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = ext4_file_write,
*/
linux 3.4.67 (android 4.4)版本kernel是如何保护受限制内存的呢? 还有待进一步研究。