我正在扩展一些在GNU / Linux(Ubuntu 14.04)下运行的软件(我不是作者),它由一个manager
进程和几个worker
进程组成。管理员可以通过我可以在配置文件中指定的命令行来启动工作程序。
启动工人后,经理使用管道与其通信。出于安全原因,我们决定让工作人员在与管理员不同的用户下运行(让我们称他们为manager-user
和worker-user
)。这是通过编写一个小包装脚本来实现的,该脚本用su
切换用户并启动一个新工作程序。在此之后,管理员可以通过管道与工作进程进行通信。这种方法已经工作了好几个月了。
作为su
的替代方案,我们考虑使用setuid
位运行工作程序。所以我们编写了一个C
包装器,可以由管理器调用来启动一个worker。如果我们将包装器配置为manager-user
所有,则工作正常启动(但当然,具有错误的权限)。如果我们将包装器配置为由worker-user
拥有并设置setuid
位,则启动工作程序,然后退出,因为它们无法连接到管理器。
所以我的问题是:运行setuid
可执行文件如何影响父进程和子进程创建的管道的权限?可以通过setuid-wrapper启动的工作进程没有打开管理器管道(或反过来)的权限吗?如果是这种情况,我们如何更改这些权限?
我没有使用setuid
的经验,所以欢迎任何信息/解释。
答案 0 :(得分:4)
Unix pipe
可以命名或未命名。命名管道实现为文件,该文件具有标准用户,组和世界所有权权限位。
未命名的管道也具有权限,但在创建管道时,这些权限受到euid
,egid
和umask
的约束。
因此,如果您的worker-user
setuid
为具有不同组权限的其他用户,除非egid
与主进程相同,否则将无法使用用户或组perms访问父进程创建的管道。
当然,对于某些umask
值,未命名的管道世界权限将允许进程通过管道进行通信,但任何进程都能够读取/写入该管道。未命名比命名管道更安全,但授予任何管道世界权限并不是一个好的安全措施。
此用例(希望两个通信进程在不同用户下运行)的可能解决方案将同时具有manager-user
和worker-user
进程在同一个组中,并且在管道创建时清除了umask
group-perm位,这样两个进程都可以读取和写入未命名的管道。
所以,如果
manager-user
归team
所有,worker-user
也归team
所有,umask
位(没有值1x
.. 7x
)然后manager-user
应该能够在未命名的管道上写入,worker-user
应该能够读取它(反之亦然,取决于管道的使用方式),即使它们是作为单独的用户运行。
有关权限位的详细信息,请参阅man
上的chmod
页面。
答案 1 :(得分:0)
使用pipe()
函数使用匿名管道,如下所示(该示例来自german Wikipedia):
# check the link above for #includes and const definitons
int main(void) {
int fd[2], n, i;
pid_t pid;
char line[MAX_CHARS];
// Create the pipe
if (pipe(fd) < 0)
fprintf(stderr, "Failed to create pipe()");
// Fork child
if ((pid = fork()) > 0) {
// Parent process
close(fd[0]);
fprintf(stdout, "Parent : ");
fgets(line, MAX_CHARS, stdin);
write(fd[1], line, strlen(line));
if (waitpid(pid, NULL, 0) < 0)
fprintf(stderr, "Error: waitpid()");
}
else {
// Child process
close(fd[1]);
n = read(fd[0], line, MAX_CHARS);
for (i = 0; i < n; i++)
line[i] = toupper(line[i]);
fprintf(stderr, "Child : ");
write(STDOUT_FILENO, line, n);
}
exit(0);
}
上述程序创建一个单向管道,父进程保存读取结束,子进程保存写入结束。