- 論壇徽章:
- 0
|
第9章
+---------------------------------------------------+
| 寫一個塊設(shè)備驅(qū)動 |
+---------------------------------------------------+
| 作者:趙磊 |
| email: zhaoleidd@hotmail.com |
+---------------------------------------------------+
| 文章版權(quán)歸原作者所有。 |
| 大家可以自由轉(zhuǎn)載這篇文章,但原版權(quán)信息必須保留。 |
| 如需用于商業(yè)用途,請務(wù)必與原作者聯(lián)系,若因未取得 |
| 授權(quán)而收起的版權(quán)爭議,由侵權(quán)者自行負(fù)責(zé)。 |
+---------------------------------------------------+
在本章中我們來討論一下這個驅(qū)動程序的數(shù)據(jù)安全,
因?yàn)樽罱囊恍┦虑樽屪髡哂l(fā)地感覺到數(shù)據(jù)泄漏對當(dāng)事人來說是麻煩的。
我們開門見山的解釋一下數(shù)據(jù)安全問題:
內(nèi)核常常會向用戶態(tài)傳遞數(shù)據(jù),而作為內(nèi)核程序的開發(fā)者,我們必須意識到不能把包含意料內(nèi)容之外的數(shù)據(jù)隨便透露給用戶態(tài),
因?yàn)槿绻@些數(shù)據(jù)不巧被別有用心者利用,就會帶來不少麻煩。
比如陳冠希就犯了這樣的錯誤。新余市出國考察團(tuán)也沒有在陳冠希身上吸取教訓(xùn),把單據(jù)也不當(dāng)回事兒。
單據(jù)對于考察團(tuán)而言并不是什么重要的玩意兒,但一旦落到“別有用心”的人手中被加以利用,就不得不當(dāng)一回事了。
由此我們發(fā)現(xiàn)了單據(jù)的商業(yè)價值。
今后在旅游公司干過的員工拿著手頭攢到的大量單據(jù),可能會比KIRA更有前途。
因此公務(wù)員確實(shí)屬于高風(fēng)險職業(yè),加薪也是情理當(dāng)中的了。
對于內(nèi)核而言,其中的數(shù)據(jù)也是如此。
即使一些數(shù)據(jù)對內(nèi)核而言沒有價值,但也不能隨意地向用戶態(tài)傳遞,因?yàn)檫@段內(nèi)存中可能不巧包含了不能隨意讓用戶獲取的數(shù)據(jù),
比如用戶A使用linux整理他女友的裸照文件,裸照的數(shù)據(jù)很可能存在于用戶A的進(jìn)程的虛存中,也可能還存在于文件緩存中,
A的進(jìn)程結(jié)束后,系統(tǒng)回收了進(jìn)程的內(nèi)存,這時內(nèi)存中的數(shù)據(jù)被系統(tǒng)認(rèn)定為無效數(shù)據(jù),但系統(tǒng)并沒有清空這段數(shù)據(jù)。
A打開的文件的緩存也類似,緩存被系統(tǒng)回收后,內(nèi)存中的數(shù)據(jù)并沒有被清除。
隨后用戶B使用了我們的塊設(shè)備驅(qū)動程序。驅(qū)動程序初始化時需要獲取足夠的內(nèi)存以存儲塊設(shè)備中的數(shù)據(jù),
系統(tǒng)很可能將用戶A使用過的那段包含裸照數(shù)據(jù)的內(nèi)存分配給我們的塊設(shè)備驅(qū)動程序。
這時如果用戶B老老實(shí)實(shí)分區(qū)、創(chuàng)建文件系統(tǒng)、寫入文件,這當(dāng)然沒事,
但如果用戶B別有用心的上來就直接去讀塊設(shè)備中的數(shù)據(jù),那么他可能很幸運(yùn)的看到不該看的東西。
因此我們咬牙切齒,嫉妒心促使我們修改這個塊設(shè)備驅(qū)動,我們都沒遇到的好事兒,也決不允許用戶B遇到。
修改的方法很簡單,我們申請內(nèi)存時使用了__get_free_pages()函數(shù),
這個函數(shù)的第一個參數(shù)是gfp_mask,原先我們傳遞的是GFP_KERNEL,表示用于內(nèi)核中的一般情況。
現(xiàn)在我們只要向gfp_mask中添加__GFP_ZERO標(biāo)志,以提示需要申請清0后的內(nèi)存。
這樣驅(qū)動程序加載后,塊設(shè)備中數(shù)據(jù)的初始值全為0,這就避免了上文中提到的安全問題。
詳細(xì)來說,就是把a(bǔ)lloc_diskmem()函數(shù)中的
p = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
這一行改成
p = (void *)__get_free_pages(GFP_KERNEL,
安全方面的改動已經(jīng)完成了,但為了避免讀者認(rèn)為本章偷工減料,我們再多改一些代碼。
塊設(shè)備中每扇區(qū)的數(shù)據(jù)長度為512字節(jié),我們在驅(qū)動程序經(jīng)常遇到與此相關(guān)的轉(zhuǎn)換。
為了快速運(yùn)算,我們經(jīng)常用到9這個常數(shù),比如:
乘以512就是左移9、除以512就是右移9、除以512的余數(shù)就是& ((1ULL<<9) - 1)、
向上對齊到512的倍數(shù)就是加上(1<<9) - 1再& ~((1ULL<<9) - 1)。
不過現(xiàn)在我們決定通過定義幾個宏來吧這些操作寫得好看一些。
先定義:
#define SIMP_BLKDEV_SECTORSHIFT (9)
#define SIMP_BLKDEV_SECTORSIZE (1ULL<<SIMP_BLKDEV_SECTORSHIFT)
#define SIMP_BLKDEV_SECTORMASK (~(SIMP_BLKDEV_SECTORSIZE-1))
然后使用這幾個宏來進(jìn)行扇區(qū)相關(guān)的轉(zhuǎn)換工作。
詳細(xì)來說,就是把simp_blkdev_make_request()函數(shù)中的:
if ((bio->bi_sector << 9) + bio->bi_size > simp_blkdev_bytes) {
改成
if ((bio->bi_sector << SIMP_BLKDEV_SECTORSHIFT) + bio->bi_size
> simp_blkdev_bytes) {
dsk_offset = bio->bi_sector << 9;
改成
dsk_offset = bio->bi_sector << SIMP_BLKDEV_SECTORSHIFT;
把simp_blkdev_getgeo()函數(shù)中的:
geo->cylinders = simp_blkdev_bytes>>9/geo->heads/geo->sectors;
改成
geo->cylinders = simp_blkdev_bytes >> SIMP_BLKDEV_SECTORSHIFT
/ geo->heads / geo->sectors;
把getparam()函數(shù)中的:
simp_blkdev_bytes = (simp_blkdev_bytes + (1<<9) - 1) & ~((1ULL<<9) - 1);
改成
simp_blkdev_bytes = (simp_blkdev_bytes + SIMP_BLKDEV_SECTORSIZE - 1)
& SIMP_BLKDEV_SECTORMASK;
把simp_blkdev_init()函數(shù)中的:
set_capacity(simp_blkdev_disk, simp_blkdev_bytes>>9);
改成
set_capacity(simp_blkdev_disk,
simp_blkdev_bytes >> SIMP_BLKDEV_SECTORSHIFT);
如果運(yùn)氣不算太背的話,程序應(yīng)該是能夠運(yùn)行的,讓我們試試:
# make
make -C /lib/modules/2.6.18-53.el5/build SUBDIRS=/root/test/simp_blkdev/simp_blkdev_step09 modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
CC [M] /root/test/simp_blkdev/simp_blkdev_step09/simp_blkdev.o
Building modules, stage 2.
MODPOST
CC /root/test/simp_blkdev/simp_blkdev_step09/simp_blkdev.mod.o
LD [M] /root/test/simp_blkdev/simp_blkdev_step09/simp_blkdev.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
# insmod simp_blkdev.ko
#
看一看驅(qū)動程序剛剛加載時里面的數(shù)據(jù):
# hexdump /dev/simp_blkdev -vn512
0000000 0000 0000 0000 0000 0000 0000 0000 0000
0000010 0000 0000 0000 0000 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0000 0000 0000
0000040 0000 0000 0000 0000 0000 0000 0000 0000
0000050 0000 0000 0000 0000 0000 0000 0000 0000
0000060 0000 0000 0000 0000 0000 0000 0000 0000
0000070 0000 0000 0000 0000 0000 0000 0000 0000
0000080 0000 0000 0000 0000 0000 0000 0000 0000
0000090 0000 0000 0000 0000 0000 0000 0000 0000
00000a0 0000 0000 0000 0000 0000 0000 0000 0000
00000b0 0000 0000 0000 0000 0000 0000 0000 0000
00000c0 0000 0000 0000 0000 0000 0000 0000 0000
00000d0 0000 0000 0000 0000 0000 0000 0000 0000
00000e0 0000 0000 0000 0000 0000 0000 0000 0000
00000f0 0000 0000 0000 0000 0000 0000 0000 0000
0000100 0000 0000 0000 0000 0000 0000 0000 0000
0000110 0000 0000 0000 0000 0000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 0000
0000130 0000 0000 0000 0000 0000 0000 0000 0000
0000140 0000 0000 0000 0000 0000 0000 0000 0000
0000150 0000 0000 0000 0000 0000 0000 0000 0000
0000160 0000 0000 0000 0000 0000 0000 0000 0000
0000170 0000 0000 0000 0000 0000 0000 0000 0000
0000180 0000 0000 0000 0000 0000 0000 0000 0000
0000190 0000 0000 0000 0000 0000 0000 0000 0000
00001a0 0000 0000 0000 0000 0000 0000 0000 0000
00001b0 0000 0000 0000 0000 0000 0000 0000 0000
00001c0 0000 0000 0000 0000 0000 0000 0000 0000
00001d0 0000 0000 0000 0000 0000 0000 0000 0000
00001e0 0000 0000 0000 0000 0000 0000 0000 0000
00001f0 0000 0000 0000 0000 0000 0000 0000 0000
0000200
#
對比一下修改前的效果:
# hexdump /dev/simp_blkdev -vn512
0000000 f300 0800 1200 0000 b804 1200 0000 0500
0000010 501a 6930 1806 246a bf0a 7700 256a bf0b
0000020 1f80 256b bf0b 47a0 266b bf0b 0ff0 246a
0000030 bf0a 1708 ffff 00ff 5028 256b bf0b 00a8
0000040 ffff 00ff 04b8 ffff 00ff 10c8 256b bf0b
0000050 00e8 246a bf0a 0229 ffff 00ff 1339 ffff
0000060 00ff 0059 246a bf0a 1669 ffff 00ff 12a9
0000070 256b bf0b 02c9 ffff 00ff 12d9 246a bf0a
0000080 215a ffff 00ff 302c 256b bf0b 03ac ffff
0000090 00ff 10cc 256b bf0b 03ec 246a bf0a 522d
00000a0 256b bf0b 32bd 2318 266b bf0c 2700 266c
00000b0 bf0c 2730 276c bf0c 1f60 276c bf0d 3580
00000c0 276d bf0d 1bc0 286d bf0d 05e0 286d bf0e
00000d0 04f0 ffff 00ff 07f5 276c bf0d 0186 ffff
00000e0 00ff 1596 276c bf0d 01b6 ffff 00ff 15e6
00000f0 266b bf0c 0708 266b bf0c 0018 ffff 00ff
0000100 0428 ffff 00ff 1038 266c bf0c 0058 ffff
0000110 00ff 3088 ffff 00ff 1219 266c bf0c 0239
0000120 ffff 00ff 1249 276c bf0d 0689 276c bf0d
0000130 02b9 266b bf0c 031c ffff 00ff 103c 266c
0000140 bf0c 035c 276c bf0d 039c ffff 00ff 20ac
0000150 276d bf0d 03dc 286d bf0d 03ec 266b bf0c
0000160 022d 266c bf0c 223d 276c bf0d 12ad 276d
0000170 bf0d 12cd 286d bf0e 02fd 2b18 286d bf0e
0000180 4400 296e bf0e 1450 296e bf0f 4470 2a6e
0000190 bf0f 14c0 2a6f bf0f 04e0 2a6f bf10 04f0
00001a0 ffff 00ff 2005 286d bf0e 1035 ffff 00ff
00001b0 5055 296e bf0f 0ab5 ffff 00ff 30c5 286d
00001c0 bf0e 1006 ffff 00ff 1426 286d bf0e 0946
00001d0 ffff 00ff 1056 296e bf0f 0176 ffff 00ff
00001e0 1186 296e bf0f 14a6 2a6e bf0f 05c6 ffff
00001f0 00ff 16d6 2a6f bf10 05f6 286d bf0e 0007
0000200
#
本章到此結(jié)束,讀者是不是感覺我們的教程越來越簡單了?
<未完,待續(xù)> |
|