LINUX块设备驱动<9>

第 9章

+---------------------------------------------------+ 
|                 写一个块设备驱动                   | 
+---------------------------------------------------+ 
| 作者:赵磊                                         | 
| email: [email protected]                      | 
+---------------------------------------------------+ 
| 文章版权归原作者所有。                             | 
| 大家可以自由转载这篇文章,但原版权信息必须保留。   | 
| 如需用于商业用途,请务必与原作者联系,若因未取得   | 
| 授权而收起的版权争议,由侵权者自行负责。           | 
+---------------------------------------------------+

在本章中我们来讨论一下这个驱动程序的数据安全,

因为最近的一些事情让作者愈发地感觉到数据泄漏对当事人来说是麻烦的

我们开门见山的解释一下数据安全问题:

内核常常会向用户态传递数据,而作为内核程序的开发者,我们必须意识到不能把包含意料内容之外的

数据随便透露给用户态,

因为如果这些数据不巧被别有用心者利用,就会带来不少麻烦

比如***就犯了这样的错误 新余市出国考察团也没有在***身上吸取教训,把单据也不当回事儿

单据对于考察团而言并不是什么重要的玩意儿,但一旦落到“别有用心”的人手中被加以利用,就不得不当

一回事了

由此我们发现了单据的商业价值

今后在旅游公司干过的员工拿着手头攒到的大量单据,可能会比KIRA更有前途

因此公务员确实属于高风险职业,加薪也是情理当中的了

对于内核而言,其中的数据也是如此

----------------------- Page 66-----------------------

即使一些数据对内核而言没有价值,但也不能随意地向用户态传递,因为这段内存中可能不巧包含了不

能随意让用户获取的数据,

比如用户A使用 linux整理他女友的裸照文件,裸照的数据很可能存在于用户A的进程的虚存中,也可

能还存在于文件缓存中,

A的进程结束后,系统回收了进程的内存,这时内存中的数据被系统认定为无效数据,但系统并没有清空

这段数据

A打开的文件的缓存也类似,缓存被系统回收后,内存中的数据并没有被清除 
随后用户B使用了我们的块设备驱动程序。驱动程序初始化时需要获取足够的内存以存储块设备中的数

据,

系统很可能将用户A使用过的那段包含裸照数据的内存分配给我们的块设备驱动程序 
这时如果用户B老老实实分区、创建文件系统、写入文件,这当然没事, 
但如果用户B别有用心的上来就直接去读块设备中的数据,那么他可能很幸运的看到不该看的东西

因此我们咬牙切齿,嫉妒心促使我们修改这个块设备驱动,我们都没遇到的好事儿,也决不允许用户B

遇到

修改的方法很简单,我们申请内存时使用了__get_free_pages()函数, 
这个函数的第一个参数是 gfp_mask ,原先我们传递的是 GFP_KERNEL ,表示用于内核中的一般情况 
现在我们只要向gfp_mask中添加__GFP_ZERO标志,以提示需要申请清 后的内存

这样驱动程序加载后,块设备中数据的初始值全为                  ,这就避免了上文中提到的安全问题

详细来说,就是把alloc_diskmem()函数中的 
p = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,

这一行改成

p = (void *)__get_free_pages(GFP_KERNEL,

安全方面的改动已经完成了,但为了避免读者认为本章偷工减料,我们再多改一些代码

块设备中每扇区的数据长度为 512字节,我们在驱动程序经常遇到与此相关的转换 
为了快速运算,我们经常用到 9这个常数,比如: 
乘以 512就是左移9、除以 512就是右移9、除以 512的余数就是& ((1ULL<<9) - 1)、 
向上对齐到 512的倍数就是加上 (1<<9) - 1再& ~((1ULL<<9) - 1)

不过现在我们决定通过定义几个宏来吧这些操作写得好看一些

先定义:

#define SIMP_BLKDEV_SECTORSHIFT        (9) 
#define SIMP_BLKDEV_SECTORSIZE        (1ULL<<SIMP_BLKDEV_SECTORSHIFT) 
#define SIMP_BLKDEV_SECTORMASK        (~(SIMP_BLKDEV_SECTORSIZE-1))

然后使用这几个宏来进行扇区相关的转换工作

详细来说,就是把simp_blkdev_make_request()函数中的: 
if ((bio->bi_sector << 9) + bio->bi_size > simp_blkdev_bytes) {

改成

----------------------- Page 67-----------------------

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()函数中的: 
geo->cylinders = simp_blkdev_bytes>>9/geo->heads/geo->sectors;

改成

geo->cylinders = simp_blkdev_bytes >> SIMP_BLKDEV_SECTORSHIFT 
        / geo->heads / geo->sectors;

把getparam()函数中的: 
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()函数中的: 
set_capacity(simp_blkdev_disk, simp_blkdev_bytes>>9);

改成

set_capacity(simp_blkdev_disk, 
        simp_blkdev_bytes >> SIMP_BLKDEV_SECTORSHIFT);

如果运气不算太背的话,程序应该是能够运行的,让我们试试:

# 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 
#

看一看驱动程序刚刚加载时里面的数据:

# hexdump /dev/simp_blkdev -vn512 
                                                 
      10                                         
      20                                        

----------------------- Page 68-----------------------

          30                                                            
          40                                                            
          50                                                            
          60                                                            
          70                                                            
          80                                                            
          90                                                            
        a0                                                              
        b0                                                              
        c0                                                              
        d0                                                              
        e0                                                              
        f0                                                              
         1                                                              
         110                                                            
         120                                                            
         130                                                            
         140                                                            
         150                                                            
         160                                                            
         170                                                            
         180                                                            
         190                                                            
       1a0                                                              
       1b0                                                              
       1c0                                                              
       1d0                                                              
       1e0                                                              
       1f0                                                              
       2 
#

对比一下修改前的效果:

# hexdump /dev/simp_blkdev -vn512 
             f3   08   12                     b804 12                  05 
        10 501a 6930 1806 246a bf0a 77   256a bf0b 
        20 1f80 256b bf0b 47a0 266b bf0b 0ff0 246a 
        30 bf0a 1708 ffff   ff 5028 256b bf0b   a8 
        40 ffff   ff 04b8 ffff   ff 10c8 256b bf0b 
        50   e8 246a bf0a 0229 ffff   ff 1339 ffff 
        60   ff   59 246a bf0a 1669 ffff   ff 12a9 
        70 256b bf0b 02c9 ffff   ff 12d9 246a bf0a 
        80 215a ffff   ff 302c 256b bf0b 03ac ffff 
        90   ff 10cc 256b bf0b 03ec 246a bf0a 522d 
        a0 256b bf0b 32bd 2318 266b bf0c 27   266c

----------------------- Page 69-----------------------

      b0 bf0c 2730 276c bf0c 1f60 276c bf0d 358 
      c0 276d bf0d 1bc0 286d bf0d 05e0 286d bf0e 
      d0 04f0 ffff   ff 07f5 276c bf0d 0186 ffff 
      e0   ff 1596 276c bf0d 01b6 ffff   ff 15e6 
      f0 266b bf0c 0708 266b bf0c   18 ffff   ff 
     1   0428 ffff   ff 1038 266c bf0c   58 ffff 
     110   ff 3088 ffff   ff 1219 266c bf0c 0239 
     120 ffff   ff 1249 276c bf0d 0689 276c bf0d 
     130 02b9 266b bf0c 031c ffff   ff 103c 266c 
     140 bf0c 035c 276c bf0d 039c ffff   ff 20ac 
     150 276d bf0d 03dc 286d bf0d 03ec 266b bf0c 
     160 022d 266c bf0c 223d 276c bf0d 12ad 276d 
     170 bf0d 12cd 286d bf0e 02fd 2b18 286d bf0e 
     180 44   296e bf0e 1450 296e bf0f 4470 2a6e 
     190 bf0f 14c0 2a6f bf0f 04e0 2a6f bf10 04f 
     1a0 ffff   ff 2  5 286d bf0e 1035 ffff   ff 
     1b0 5055 296e bf0f 0ab5 ffff   ff 30c5 286d 
     1c0 bf0e 1  6 ffff   ff 1426 286d bf0e 0946 
     1d0 ffff   ff 1056 296e bf0f 0176 ffff   ff 
     1e0 1186 296e bf0f 14a6 2a6e bf0f 05c6 ffff 
     1f0   ff 16d6 2a6f bf10 05f6 286d bf0e           7 
     2 
#

本章到此结束,读者是不是感觉我们的教程越来越简单了 ?

<未完,待续>

LINUX块设备驱动<9>,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。