这也许不算是linux的漏洞吧,应该算是它的一点点不足之处了。至少我是不晓得它有什么威胁到系统安全的利用价值。 呵呵,可能是我才疏学浅。
大致情况是这样的,那天我们操作系统课安排上机。实验主题是让我们熟悉linux下的系统调用,尝试用fork()函数创建一个子进程。
我是刚接触linux不久,很多概念还不清晰。至于fork()函数调用了以后,系统到底做了些什么都不是很清楚。于是自己在电脑上一步一步尝试。
老师告诉我说,fork()执行以后,父进程和子进程共享代码段。但我还是不理解子进程运行的时候,到底是从头开始执行呢,还是从fork()开始执行。fork这个单词的字面意思是分叉,按这个逻辑来应该是从fork()这个语句开始执行,上面的语句应该是不执行的。于是,我写了下面这段代码检验我的推测:
#include
#include
#include
int main(void)
...{
int pid;
printf("1");
pid = fork();
printf("0 ");
return 0;
}
然后输入gcc main.c -o main进行编译,在执行"./main"运行,结果出来的是:
10
10
这输出了两个10,那不就是指printf(1)执行了2两次了?难道前面的代码会被运行吗?
不过同时我也发现我的程序有个失误,我的本意一个是让1单独占一行,却忘了加转义字符'\n'。于是重新打开main.c在1后面添加了回车。按上面的逻辑来,这回应该输出:
1
0
1
0
于是再编译,再运行。但结果出来的却是:
1
0
0
前后两段代码仅仅只差了一个回车。却有不同的效果。问题就出在这个回车上,我又写了另一段测试代码:
#include
#include
#include
int main(void)
...{
int pid;
printf("1\n");
printf("2");
pid = fork();
printf("0 ");
return 0;
}
运行结果是:
1
20
20
加了回车它就不会显示,把上面的代码作一下修改,1后面没有回车,2后面加回车。输出结果是:
12
0
0
我猜测可能是输出回车的同时,系统还会清理一下标准输入的缓存区。我们知道C语言里标准输出是stdout,那用fflush(stdout)来主动清空一下缓存,看看效果,来验证我的猜想。代码:
#include
#include
#include
int main(void)
...{
int pid;
printf("1");
fflush(stdout);
pid = fork();
printf("0 ");
return 0;
}
输出结果是:
10
0
看来是对了,问题就是没有情况缓冲区,子进程把父进程的输出缓冲内容一起copy过来了。
我换了几个系统试了一下,发现在Redhat, fedora这些系统里都有这个问题。不小的其他版本的linux也没有这个问题。
按上面的说法,我们在终端里每运行一个程序,它应该都有系统输出的一个拷贝(如果没有清空的话)。也不小的这个问题也没有什么利用价值,也许这个问题已经很早就有人发现了,大概是高手们觉得这个不算是漏洞,没有修复的必要吧。
niutao0602 于 2008-01-09 11:06:56发表:
这不是bug.
fork()出来的子进程是对父进程的一个完全copy,也包括父进程打开的文件(其中就包括stdout文件)。在终端里运行一个程序系统确实是fork出一个子进程去执行该程序,但该子进程会完全脱离父进程。参考:
http://groups.google.com/group/linuxerfamily/browse_thread/thread/1d11df6d807e4620#5d628f3345a40ebd
http://www.linuxdiyf.com/blog/?87680/action_viewspace_itemid_2247.html