分类:
2008-11-26 18:03:50
8.13 system function
System函数用来将一个命令行参数转化为区执行一个命令,传递给该函数的参数包括命令名,参数等信息,而且可以包含诸如’>’等重定向字符。这个函数等待命令结束后才返回。
#include int system(const char *cmdstring); |
Returns: (see below) |
他是一个ISO C中定义的函数,它实际上是调用了fork, exec, waitpid等函数实现的,书中给出了一个例子实现:
#include
#include
#include
int
system(const char *cmdstring) /* version without signal handling */
{
pid_t pid;
int status;
if (cmdstring == NULL)
return(1); /* always a command processor with UNIX */
if ((pid = fork()) < 0) {
status = -1; /* probably out of processes */
} else if (pid == 0) { /* child */
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); /* execl error */
} else { /* parent */
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
}
return(status);
}
关于apue2中不准使用system调用被set-user-id的可执行程序,书中:
The superuser permissions that we gave the tsys program are retained across the fork and exec that are done by system.
When /bin/sh is bash version 2, the previous example doesn't work, because bash will reset the effective user ID to the real user ID when they don't match.
If it is running with special permissionseither set-user-ID or set-group-IDand wants to spawn another process, a process should use fork and exec directly, being certain to change back to normal permissions after the fork, before calling exec. The system function should never be used from a set-user-ID or a set-group-ID program.
我的理解:
我的理解是:
对于版本较旧的bash当system调用执行之后,新spawn出来的进程的权限是effective user 的权限,而且被retained,这样会使不具该权限的用户获得权限的提升。所以是security hole. 而2版本之后的bash就不再会有这种问题。
我做了测试,我的确可以成功system一个set-user-id被设置的属于root的可执行程序,而且system前后,原进程的user/effective user id都保持不变。仅仅是被system调用产生的进程自己具有了root的权限。
不建议使用system的另一个原因是:system可以接受各种类型的字符串然后按照其内容执行,如果shell的IFS被认为修改,在fork和exec时,不将被修改的IFS重新还原成其默认值,那么system执行的程序就会被子shell以另一种IFS去解释,有可能存在安全漏洞。所以system的参数不能来自程序外部。