- 论坛徽章:
- 0
|
本帖最后由 crazy4c 于 2014-05-27 00:27 编辑
一个在AIX系统下运行了几个月的C程序,最近几天接二连三的出现写文件时出现文件空洞,值为\x00的字符,大小由几十K到几百K不等。文件打开的方式为file = fopen( filename, "w" );文件写入均通过fprintf,代码类似:- while( exp ){
- /* 数据库查询 */
- ... ...
- fprintf( file, "%s\x7f\x5e%s\x7f\x5e%s\x7f\x5e%s\r\n", str1, str2, str3, str4 );
- ... ...
- }
复制代码 以上代码仅为示例,实际代码中参数为几十个,参数跟格式化字符串可以确定是正确对应的。\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、到底会是什么原因导致的呢??? |
|