免费注册 查看新帖 |

Chinaunix

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

[C] AIX系统下C程序以只写方式写入文件出现空洞 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-05-27 00:11 |只看该作者 |倒序浏览
本帖最后由 crazy4c 于 2014-05-27 00:27 编辑

一个在AIX系统下运行了几个月的C程序,最近几天接二连三的出现写文件时出现文件空洞,值为\x00的字符,大小由几十K到几百K不等。文件打开的方式为file = fopen( filename, "w" );文件写入均通过fprintf,代码类似:
  1. while( exp ){
  2. /*  数据库查询 */
  3. ... ...
  4. fprintf( file, "%s\x7f\x5e%s\x7f\x5e%s\x7f\x5e%s\r\n",  str1, str2, str3, str4 );
  5. ... ...
  6. }
复制代码
以上代码仅为示例,实际代码中参数为几十个,参数跟格式化字符串可以确定是正确对应的。\x7f\x5e为分隔符,在编辑器中查看时可能为“?^”。
首先可以肯定,后面4个字符串参数均有值,且长度在50个字节以内,均为普通可见字符。而出现文件空洞的位置都出现在某个参数值内,如,str1、str2、str3、str4的值分别为"STR1", "STR2", "STR3", "STR4",而输出的内容则可能为:
STR1?^STR2?^S^@^@^@^@^@^@^@^@^@^@^@^@TR3?^STR4
其中^@为一个字符,其值为\x00。
最初认为出现空字符是因为某个参数不合法导致的,而这种情况应该是该参数整个都不会输出到文件,甚至该参数后的其他参数也不能写入到文件,而实际情况是出现在某个参数的中间位置,且不固定(当然也有可能出现在某两个参数之间,可能也只是碰巧,但这种情况并没有遇到过),而且该行数据删掉空字符后其实也是完整正确的。每个参数也都是规则合法的普通可见字符,没有发现导致这种情况的原因。
将数据库数据导出到另一个AIX机器上进行多次测试,但并没有重现这种情况!
我向别人描述这种情况时,半开玩笑的说:就像文件正在写入时,机器让人给踢了一脚,导致硬盘磁头往后蹦了一下。
之前就做网上见过sprintf的一些高级应用,或者说是漏洞,格式化结果可能是出人意料的,但fprintf函数是否也有这种情况就不清楚了。后尝试通过fprintf使用一些非法的格式及参数试图向文件中写入\x00的字符也并没有成功。
另外在网上看到过对意外出现文件空洞描述的一则例子是,通过重定向“>”写入日志文件时可能会文件空洞,若使用追加方式“>>”则可避免文件空洞,另,只写方式“w”与重定向对应、追加方式打开文件与“>>”对应。
到现在,出现该问题的原因也没有找到,甚至没有猜测到合理的答案。到底是程序自身的原因,还是操作系统的问题?
现在困扰我的几个问题:
1、fprintf是否通过某种手段向文件中写入\x00空字符串?
2、若参数不合法或内存越界或内存污染是否会影响到fprintf格式化的结果继而导致将出现文件空洞(虽然在我遇到的这个问题中并没有发现与参数不合法有关的迹象)?
3、在AIX UNIX操作系统下是否存在这种问题(或漏洞),是不是和操作系统有关?
4、文件中出现的空洞应该是非常大的(现最大的为>100K),若使fprintf格式出现异常,是否能达到这么大数量的字符串?看起来更像是fseek函数导致的,但在程序中根本没有使用过该函数;
5、是否有其他程序干扰了该程序的文件操作,但该程序运行时只有一个实例,与其他程序同时打开一个文件的情况应该不会出现;
6、就像我讲的那个玩笑一样,在写文件时,外部因素是否会导致文件数据错误但操作系统并没有检测出的情况(虽然我自己也认为企业级的服务器应该不会那么脆弱)?
7、出现这种情况是否与磁盘块大小有关?但文件起始位置到空洞之间的字符数似乎只是一个随机的数字,并不是1024的倍数,甚至不一定是2的倍数;
8、到底会是什么原因导致的呢???

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2014-05-27 08:20 |只看该作者
有多线程同时使用了fopen返回的文件指针?

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
3 [报告]
发表于 2014-05-27 08:31 |只看该作者
以上代码仅为示例,实际代码中参数为几十个,参数跟格式化字符串可以确定是正确对应的。\x7f\x5e为分隔符,在编辑器中查看时可能为“?^”。
首先可以肯定,后面4个字符串参数均有值,且长度在50个字节以内,均为普通可见字符。而出现文件空洞的位置都出现在某个参数值内,如,str1、str2、str3、str4的值分别为"STR1", "STR2", "STR3", "STR4",而输出的内容则可能为:
STR1?^STR2?^S^@^@^@^@^@^@^@^@^@^@^@^@TR3?^STR4
其中^@为一个字符,其值为\x00。
最初认为出现空字符是因为某个参数不合法导致的,而这种情况应该是该参数整个都不会输出到文件,甚至该参数后的其他参数也不能写入到文件,而实际情况是出现在某个参数的中间位置,且不固定(当然也有可能出现在某两个参数之间,可能也只是碰巧,但这种情况并没有遇到过),而且该行数据删掉空字符后其实也是完整正确的。每个参数也都是规则合法的普通可见字符,没有发现导致这种情况的原因。
将数据库数据导出到另一个AIX机器上进行多次测试,但并没有重现这种情况!
我向别人描述这种情况时,半开玩笑的说:就像文件正在写入时,机器让人给踢了一脚,导致硬盘磁头往后蹦了一下。
之前就做网上见过sprintf的一些高级应用,或者说是漏洞,格式化结果可能是出人意料的,但fprintf函数是否也有这种情况就不清楚了。后尝试通过fprintf使用一些非法的格式及参数试图向文件中写入\x00的字符也并没有成功。
另外在网上看到过对意外出现文件空洞描述的一则例子是,通过重定向“>”写入日志文件时可能会文件空洞,若使用追加方式“>>”则可避免文件空洞,另,只写方式“w”与重定向对应、追加方式打开文件与“>>”对应。
到现在,出现该问题的原因也没有找到,甚至没有猜测到合理的答案。到底是程序自身的原因,还是操作系统的问题?
现在困扰我的几个问题:
1、fprintf是否通过某种手段向文件中写入\x00空字符串?
<< fprintf可以写入0x00字符, 使用%c的话。
2、若参数不合法或内存越界或内存污染是否会影响到fprintf格式化的结果继而导致将出现文件空洞(虽然在我遇到的这个问题中并没有发现与参数不合法有关的迹象)?
<< fprintf参数不合不会,但其它函数内存越界会, 此外, printf是支持控制字符的, 请不要在Fmt串中出现不想要的控制字符(比如移动光标的控制字符)。
3、在AIX UNIX操作系统下是否存在这种问题(或漏洞),是不是和操作系统有关?
<< AIX,这么高大上的系统没用过。。。
4、文件中出现的空洞应该是非常大的(现最大的为>100K),若使fprintf格式出现异常,是否能达到这么大数量的字符串?看起来更像是fseek函数导致的,但在程序中根本没有使用过该函数;
<< 最大为100K, lseek引起的可能性的确很大。 如果在多线程中使用fprintf,试试append方式看看是不是问题会重现。
5、是否有其他程序干扰了该程序的文件操作,但该程序运行时只有一个实例,与其他程序同时打开一个文件的情况应该不会出现;
<< 进程屏障保证不会有这种情况
6、就像我讲的那个玩笑一样,在写文件时,外部因素是否会导致文件数据错误但操作系统并没有检测出的情况(虽然我自己也认为企业级的服务器应该不会那么脆弱)?
<< 不会, 不然坏的是整个文件系统。
7、出现这种情况是否与磁盘块大小有关?但文件起始位置到空洞之间的字符数似乎只是一个随机的数字,并不是1024的倍数,甚至不一定是2的倍数;
<< 不太可能。
8、到底会是什么原因导致的呢???
<< 不知道。

论坛徽章:
0
4 [报告]
发表于 2014-05-27 08:43 |只看该作者
回复 2# hellioncu
在这个程序里是单个进程的,也只有一个线程。

   

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
5 [报告]
发表于 2014-05-27 09:06 |只看该作者
crazy4c 发表于 2014-05-27 08:43
回复 2# hellioncu
在这个程序里是单个进程的,也只有一个线程。


du看看这个文件用了多少个块,确定下到底是空洞还是你自己写进去的0

论坛徽章:
0
6 [报告]
发表于 2014-05-27 09:07 |只看该作者
回复 3# folklore
非常感谢一一解答。第1个问题中忘了你说地那种情况,可以输出\x00,但似乎遇我遇到地问题差别有些大,程序里没有%c格式。如果是其他函数内存越界,输出结果应该不会那么规则,感觉应该是一堆乱码才对。你的最后一个问题答案令我很欣慰
   

论坛徽章:
0
7 [报告]
发表于 2014-05-27 09:25 |只看该作者
回复 5# hellioncu
当时忘了考虑这个问题了,现在是通过ftp拿到的文件,应该跟原服务器上的占用空间不同了。不过两边使用了同一个函数获取文件大小得到结果是不一致的,应该是文件空洞吧。

   

论坛徽章:
0
8 [报告]
发表于 2014-05-27 22:40 |只看该作者
问题原因找到了,真的就是最开始排除的多进程操作文件的原因造成的。虽然可以确定程序被调用时是单实例生成文件,但并没有对并发做过考虑,最初也没有这方面需求,最终由于外部调度系统的调度频率发生变动,致使一次执行结束前又开始了另一次操作。而现在新的问题是,在生成当日文件时,不管执行多少次,数据都是一样的,结果文件应该也是一样的,所以即便并发写同一文件也只是用相同的数据覆盖原数据,而不应该会出现空洞。问题答案应该是在文件生成后的传输会对原文件进行压缩,这应该是导致空洞的根本原因吧?谁知道呢。经过这次事件,真不敢再相信自己的判断了。
总结一下问题发生后自己犯的错误,过于相信经验、过于主观臆断,在没有考虑全面之前,想当然的否定了自以为不可能的因素,导致判断问题走上了一条不归路。而类似失误其实在自己身上不止一次发生过。
不知路过的人有没有犯过与我类似的问题。引以为戒,与君共勉!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP