免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 955 | 回复: 0
打印 上一主题 下一主题

加密文件系统工作笔记 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-07-05 10:50 |只看该作者 |倒序浏览
这里是实现一个简单加密文件系统“写操作”的加密过程补充的代码
且只加密sd卡中的文件。
希望在commit_write执行之后就马上强行把这一页的页面数据加密后写到sd上
写完块设备后,将页中的数据再次解密以保证缓存中为明文
总体思想是,在generic_file_write中调用commit_write方法之后,
1. 首先看块设备是否是sd卡,是则加密
2. 加密page中的数据
3. unlock page
4. 调用ll_rw_block写page->buffers队列
5. lock page
6. 将页中的数据再次解密换成明文
注:加密出错机制还暂未考虑
代码如下:
在filemap.c中加入头文件,才能引用宏MAJOR
#include  
#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
下面的代码加到generic_file_write中
status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);之后
unsigned int major;
/*当通过宏MAJOR从b_dev求出bh对应主设备号
*major==60即为sd卡块设备时,进行加密操作
*/
major = MAJOR(page->buffers->b_dev);
if (major == 60) {
struct buffer_head *bh_encrypt, *head, *arr[MAX_BUF_PER_PAGE];
int nr,i;
nr = 0;
——————————————————————————————————
/*
*将page中的BH_Lock已置位选定写入块设备的脏buffers放入arr[]指针数组
*nr记录个数
*/
for(bh_encrypt = head = page->buffers;
bh_encrypt != head; bh_encrypt = bh_encrypt->b_this_page)
{
if(buffer_locked(bh_encrypt))
continue;
arr[nr] = bh_encrypt;
nr++;
}
——————————————————————————————————————
挑选page中的BH_Lock已置位的buffer..简直是大错特错!这个lock置位的问题是bdflush里的write_some_buffers做的。我这里是抢在bdflush之前,应该还是挑选BH_Dirty置位的脏缓冲区,而是由ll_rw_block来将这些bh加锁。

/*
*将page中的BH_Dirty已置位选定写入块设备的脏buffers放入arr[]指针数组
*nr记录个数
*/
for(bh_encrypt = head = page->buffers;
bh_encrypt != head; bh_encrypt = bh_encrypt->b_this_page)
{
if(buffer_dirty(bh_encrypt))
continue;
arr[nr] = bh_encrypt;
nr++;
}

————————————————
/*
*对于所有需要加密的缓冲区
*/
for(count=0;countb_data应该是值向长度为512的char型的字符串数组指针)
*/
for(i=0;ib_data));
printk("\n");
}
/*
*将bh对应的缓冲区数据块区的字符与0xff异或
*因为还是实验阶段,这里就没有用加解密算法,利用异或代替比较容易验证
*/
for(i=0;ib_data)^ = 0xff;
}
/*
*给page解锁
*利用ll_rw_block将缓冲区立即写入块设备
*给page加锁
*/
UnlockPage(page);
ll_rw_block(WRITE,nr,arr);
LockPage(page);
/*
*对于所有已经加密的缓冲区
*/
for(count=0;countb_data));
printk("\n");
}
/*
*将bh对应已加密的缓冲区数据块区的字符与0xff再次异或
*以保证在缓冲区中的数据为明文
*/
for(i=0;ib_data)^ = 0xff;
/*
*打印出bh对应的又再次解密的缓冲区数据块区的字符串
*/
for(i=0;ib_data));
printk("\n");
}
}
} // if (major == 60)

不过修改了也重新编译内核有错...

塑料袋的说法很值得考虑:
1)ll_rw_block返回后,buffer_head中的内容并没有写到磁盘上。
你的buffer_head都是挂在request中,而request挂在request_queue中,而request挂在tq_disk中。
但是ll_rw_block不会等待启动tq_disk后才返回,更不会等待写完成后才返回,所以返回时,buffer_head的内容还没写到磁盘上,但是你又进行了解密,很可能bottom_half启动tq_disk,tq_disk中真正开始写磁盘时,你已经解密了,真正写的是解密的内容。
2)ll_rw_block中间可能睡眠。在ll_rw_block->submit_bh->__make_request的时候,如果request结构暂时用光了,就会睡眠,等待有request结构被释放。
   
    在这个睡眠的过程中,其他进程换进来。虽然sys_write获得了inode->i_sem信号量,即使没有PG_Lock,其他进程也不能写这个page,但是page有可能是一个影射到其他进程用户空间的page,换进来的其他进程可以在用户空间修改这个page的内容,从而修改了buffer_head中的内容,既你加密的内容。
    等到有了空闲request时,buffer_head中的内容已经被修改了,ll_rw_block在返回前,buffer_head中的加密内容早就改变了。
我想了想,要实现你的目的,可行方法应该是直接修改驱动程序,而不是修改sys_write。

也是daemeon说的内存映射问题..

反正可能还是要修改驱动或者那个generic_make_request
最初引得那篇论文原文就是:
(1)在generic_make_request()函数中进行加密。Linux操作系统中generic_make_request()函数完成将实际的读写请求传递到下层的设备驱动的任务。
(2)在do_generic_file_read() 中将实际的数据解密

但是读写其实都是利用了submit_bh然后调用了generic_make_request()通过参数传送读写的方法,来实现对设备读写。可是为什么论文里中说"写"是修改generic_make_request(),而"读"是修改do_generic_file_read()呢?不太理解。
还有一个问题,就是在prepare_write中的一个问题。即是页没有缓冲的时候,需要新建一个空白、空闲页面, 为其新新建buffer对列后还会检查其buffer的BH_Uptodate标志,不一致的情况下需要调用ll_rw_block来从磁盘读入块的内容。那么就是写中有读了。这里还需要先把读出来的数据解密。修改一致后再是通过commit_write里面的bdflush进程 调用修改过的generic_make_request进行加密再写磁盘了

总之细节问题似乎还需要斟酌...救命!




本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/33412/showart_334698.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP