boxcounter
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
阅读:3657回复:24

Lazy write导致的内容丢失问题

楼主#
更多 发布于:2008-05-20 11:28
各位,我现在在做一个加解密的minifilter驱动,现在遇到一个问题:
我的加密头在文件首部。我在Write、read中,都会跳过这个首部(512B),通常情况下,这种情况都OK。但是发现当system进行延缓写的时候,会出现最后一部分WriteBuffer中的内容丢失,具体如下:

一个Write请求,Offset是0,WriteLength是8KB,
经过我的minifilter时,我修改offset为512,这样就跳过了我的加密头。然后发现写后返回的结果是只写了7.5KB,最后512字节没写进去,这导致文件中的512字节为随机脏数据,破坏了我的文档。
其中FileSize,AllocationSize都是足够大的,出现这个现象的原因不是因为空间不足而被截断。

我想请教各位朋友,这是因为什么,如何解决。
先多谢各位 :)

最新喜欢:

snoxsnox
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-06-24 17:04
引用第23楼qianjunhua于2008-06-24 14:04发表的  :
应该是在fcb里面直接修改文件的大小,这样ntfs 在适当的时候会用fbc里面的值来调用ccsetcachefilesize 这个函数,来通知cache 这个时候文件的大小


fcb里面直接修改文件的大小? 呵呵  好想法
这样可以吗?你试验过没

如果直接修改FCB的话 ,还不如 自己下发 setfileinformation来修改FCB
这样似乎能更好一些
栀子花驿站 www.zhizihua.com
qianjunhua
驱动小牛
驱动小牛
  • 注册日期2003-12-08
  • 最后登录2013-02-27
  • 粉丝11
  • 关注0
  • 积分712分
  • 威望1052点
  • 贡献值1点
  • 好评度57点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-06-24 14:04
应该是在fcb里面直接修改文件的大小,这样ntfs 在适当的时候会用fbc里面的值来调用ccsetcachefilesize 这个函数,来通知cache 这个时候文件的大小
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-06-24 10:21
引用第20楼qianjunhua于2008-06-22 12:15发表的  :
是的!cache的大小 从他驱动中得到的是明文的大小,也就是,那么cache的 lazy write 就是在写的时候就要比较offset 和得到的明文的大小,所以一旦=>明文大小的时候就停止写了!而且文件驱动规定了lazy write 的写的时候是不能改变文件大小的,也不能在文件尾添加。改变文件大小的时候是在一开始app 写的时候,fsd要检查是不是超过endoffile,如果超过就会setcachefile size 的这个函数来通知,然后明确的让cache 调用setimforationfile 改变大小


qianjunhua,你说 当 offset=>明文大小 时就会停止写, 这个确实能够解释,应用报告的 “磁盘已满”或“延迟写失败”的这种错误,
并且你说 “文件大小的时候是在一开始app 写的时候”也就是说要想解决这个问题必须在app的写的时候就改变其大小,
这个改变大小 改如何处理了?是在直接在setimforationfile处理 还是除了setimforationfile 以外的地方也要进行处理?
 qianjunhua 请你给个详细点的说明 ,谢谢!
栀子花驿站 www.zhizihua.com
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-06-23 13:19
引用第20楼qianjunhua于2008-06-22 12:15发表的  :
是的!cache的大小 从他驱动中得到的是明文的大小,也就是,那么cache的 lazy write 就是在写的时候就要比较offset 和得到的明文的大小,所以一旦=>明文大小的时候就停止写了!而且文件驱动规定了lazy write 的写的时候是不能改变文件大小的,也不能在文件尾添加。改变文件大小的时候是在一开始app 写的时候,fsd要检查是不是超过endoffile,如果超过就会setcachefile size 的这个函数来通知,然后明确的让cache 调用setimforationfile 改变大小


是让cache更新fcb里的文件大小,还是更新cache里的文件大小?
qianjunhua
驱动小牛
驱动小牛
  • 注册日期2003-12-08
  • 最后登录2013-02-27
  • 粉丝11
  • 关注0
  • 积分712分
  • 威望1052点
  • 贡献值1点
  • 好评度57点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-06-22 12:15
是的!cache的大小 从他驱动中得到的是明文的大小,也就是,那么cache的 lazy write 就是在写的时候就要比较offset 和得到的明文的大小,所以一旦=>明文大小的时候就停止写了!而且文件驱动规定了lazy write 的写的时候是不能改变文件大小的,也不能在文件尾添加。改变文件大小的时候是在一开始app 写的时候,fsd要检查是不是超过endoffile,如果超过就会setcachefile size 的这个函数来通知,然后明确的让cache 调用setimforationfile 改变大小
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-06-02 18:38
让CCmgr感知到文件头?如果让它感知到了,那它不会往下刷脏数据吗?
不会损毁我们自己的加在头部的加密标志吗?
栀子花驿站 www.zhizihua.com
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2008-05-28 12:39
引用第17楼boxcounter于2008-05-28 11:51发表的  :
让CCmgr感知到加密头的存在就OK了,当然我调整了整个框架实现这么个功能。
我是在NTFS上做的测试。


如何让CCmgr感知到文件头呢?
对缓冲读写也偏移文件头长度吗?
boxcounter
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2008-05-28 11:51
让CCmgr感知到加密头的存在就OK了,当然我调整了整个框架实现这么个功能。
我是在NTFS上做的测试。
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2008-05-27 19:25
引用第15楼boxcounter于2008-05-27 18:41发表的  :
我已经解决了,原因是因为CCmgr不知道我的加密头的存在,导致刷脏页的时候出现这个问题。多谢各位 :)

怎么解决的?这个问题是出现在NTFS上,还是FAT32上也会有?
boxcounter
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2008-05-27 18:41
我已经解决了,原因是因为CCmgr不知道我的加密头的存在,导致刷脏页的时候出现这个问题。多谢各位 :)
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2008-05-26 12:41
引用第13楼goodone于2008-05-26 08:17发表的  :
为什么会有两次的 set了?写之前有,写完以后还有?

还有就是写磁盘的话 flag应是0x43吧


一次是应用程序发的,一次是系统发的,具体我也在研究。
磁盘写是0x43,但Set的是0x42,具体flag定义参考微软文档,我也忘啦
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2008-05-26 08:17
为什么会有两次的 set了?写之前有,写完以后还有?

还有就是写磁盘的话 flag应是0x43吧
栀子花驿站 www.zhizihua.com
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2008-05-25 14:38
引用第9楼goodone于2008-05-24 11:02发表的  :



通过我的观察 SetInformation的IRP是在磁盘写之前出现的。。。。
所以 应该先在 SetInformation 中修改大小
.......


磁盘写出现之前的Set标志是A00,标志0x42的Set在磁盘写之后
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2008-05-24 14:54
引用第10楼fly1101于2008-05-24 11:34发表的  :
加密头在文件首部时,考虑了映射文件吗?
应用层用CreateFileMapping、MapViewOfFile
内核层用NtCreateSection、NtMapViewOfSection

这些都要处理的


不是很明白你说的意思,
可以在说详细点吗?
谢谢!
栀子花驿站 www.zhizihua.com
fly1101
驱动牛犊
驱动牛犊
  • 注册日期2007-10-22
  • 最后登录2012-04-19
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望93点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2008-05-24 11:34
加密头在文件首部时,考虑了映射文件吗?
应用层用CreateFileMapping、MapViewOfFile
内核层用NtCreateSection、NtMapViewOfSection

这些都要处理的
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2008-05-24 11:02
引用第1楼dionysus77于2008-05-20 12:22发表的  :
我也遇到这个问题,就是FileSize不够大的问题,因为SetInformation的IRP出现在磁盘写之后,而paging_io的写不能自动更新EoF。所以写入时,文件大小是不够的。自己设置一下长度再写入就好了。



通过我的观察 SetInformation的IRP是在磁盘写之前出现的。。。。
所以 应该先在 SetInformation 中修改大小
但是 如果简单的修改大小 还是会有问题
栀子花驿站 www.zhizihua.com
goodone
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2014-04-30
  • 粉丝3
  • 关注0
  • 积分372分
  • 威望174点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2008-05-24 11:00
这个确实是个问题,帮忙顶下,

期望大牛们给个回应
栀子花驿站 www.zhizihua.com
dionysus77
驱动小牛
驱动小牛
  • 注册日期2006-11-15
  • 最后登录2011-12-18
  • 粉丝0
  • 关注0
  • 积分27分
  • 威望392点
  • 贡献值0点
  • 好评度177点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2008-05-23 12:14
ValidDataLength(11677)<Length: (12288).
boxcounter
驱动牛犊
驱动牛犊
  • 注册日期2007-01-30
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2008-05-23 09:36
回dionysus77兄:
可能是我的日志没说太清楚,我解释一下 :)

[TFGF] PreCallback(IRP_MJ_WRITE): IrpFlags: 0x00000043, Offset(0), Length: (12288).
[TFGF] PostCallback(IRP_MJ_WRITE): AllocationSize(16384), FileSize(12701), ValidDataLength(11677).
[TFGF] PostCallback(IRP_MJ_WRITE): BytesWritten(10653), *Status(00000000).

这里是Paging IO,所以待写长度是页的整数倍大小(实际待写长度可能是没有这么多的),ValidDataLength就是实际上需要写的,但是实际上只写了10653, 比ValidDataLength还少1KB,而从FileSize上来看,文件的确有足够的空间可以写入ValidDataLength这么长的数据。
上一页
游客

返回顶部