一,、linux內(nèi)核,、用戶空間的內(nèi)存劃分:
如下圖:內(nèi)核空間劃分0~3G為用戶空間,,3~4G為內(nèi)核空間,。詳細(xì)請(qǐng)參考《Linux用戶空間與內(nèi)核空間》
注意:內(nèi)核地址空間的范圍是 0xC0000000
~ 0xFFFFFFFF 二,、異常內(nèi)存訪問(wèn)導(dǎo)致的oops:1、Unable to handle kernel paging request at virtual address 00000000 =====》越出內(nèi)核地址空間范圍,,原因是由于使用空NULL指針 2,、Unable to handle kernel paging request at virtual address 20100110 =====》越出內(nèi)核地址空間范圍,原因是的內(nèi)存越界導(dǎo)致該指針 所在內(nèi)存被破壞了,。 接下來(lái)的困難是在什么地方這個(gè)內(nèi)存被修改,?為什么被修改,? 3、Unable
to handle kernel paging request at virtual address c074838c =====》沒(méi)有越出內(nèi)核地址空間范圍,,為什么也oops,? 這種情況我稱(chēng)之為:試圖篡改受限制內(nèi)存。比如:聲明為const的變量,! 還有其它形式的受限制內(nèi)存嗎? 三,、訪問(wèn)受限制內(nèi)存導(dǎo)致oops:const在C語(yǔ)言當(dāng)中聲明一個(gè)變量為只讀,,
如果試圖直接修改const變量,build階段編譯器,,就檢查出來(lái),,并報(bào)read
only錯(cuò)誤,
如下:
const int i = 1;
i = 10; build error: assignment of read-only variable 'i' //只讀變量賦值錯(cuò)誤 但是如果通過(guò)指針間接修改const變量,,編譯器是檢查不出來(lái)的,。
如下:
const
int i = 1;
int *p = &i; *p = 10; 不出所料地編譯成功了! 但不要高興,,這樣的代碼是有隱患的,!
因?yàn)椋茱@然,,我們將變量聲明為const,,是希望它能受到保護(hù)的!
既然編譯器檢查不出這種隱患,,由誰(shuí)負(fù)責(zé)保護(hù)它呢,?
我想,linux只有運(yùn)行時(shí),,由mm模塊來(lái)保護(hù)聲明為const的變量了!!!???
但遺憾的是,,linux 3.4.5以前的版本一直沒(méi)有這個(gè)保護(hù)功能,應(yīng)該老版本linux自身的漏洞吧,!
直到約linux 3.4.67 (android
4.4)才有運(yùn)行時(shí)保護(hù)受限制內(nèi)存的功能,。
如果這么簡(jiǎn)直地直接使用指針顯示地間接修改一個(gè)某const變量,還是很容易查出來(lái)的,。
下面舉一個(gè)掩蔽的例子: 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的一個(gè)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)中運(yùn)行導(dǎo)致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是如何保護(hù)受限制內(nèi)存的呢,? 還有待進(jìn)一步研究,。 |
|
來(lái)自: 點(diǎn)點(diǎn)閱 > 《linux內(nèi)核》