pipe道访问权限setuid程序

我正在扩展GNU / Linux(Ubuntu 14.04)下运行的一些软件(我不是作者),它由一个manager进程和几个worker进程组成。 pipe理员可以通过我可以在configuration文件中指定的命令行来启动一个worker。

启动一名工人后,pipe理人员使用pipe道与其通信。 出于安全原因,我们决定让工人在不同于pipe理者的用户下运行(让我们称他们为manager-userworker-user )。 这是通过编写一个小的包装脚本来实现的,该脚本用su来切换用户并启动一个新的worker。 在此之后,经理可以通过pipe道与工作进程进行通信。 这种方法现在已经运行了好几个月了。

作为su的替代,我们已经考虑使用setuid位来运行工作者。 所以我们写了一个C封装器,可以由pipe理器调用来启动一个worker。 如果我们将包装器configuration为由manager-user拥有,则worker正确启动(当然,但具有错误的权限)。 如果我们将包装程序configuration为由worker-user拥有并设置setuid位,则启动worker,但因为无法连接到manager而退出。

所以我的问题是:如何运行一个setuid可执行文件影响由父进程和subprocess创build的pipe道权限? 难道通过setuid-wrapper启动的工作进程没有权限打开pipe理器的pipe道(或者相反)? 如果可以的话,我们如何改变这些权限?

我几乎没有使用setuid经验,因此欢迎任何信息/解释。

Unix pipe可以被命名或未命名。 一个命名管道被实现为一个文件,它具有标准的用户,组和世界所有权限位。

一个未命名的管道也具有权限,但是在创建管道时这些管道受到euidegidumask限制。

因此,如果您的worker-user为具有不同组权限的另一个用户,除非该egid与主进程通用,否则将无法使用用户或组perm访问父级创建的管道处理。

当然,对于某些umask值,未命名的管道世界权限将允许进程通过管道进行通信,但任何进程都可以读取/写入该管道。 未命名是比命名管道更安全,但是授予任何管道的世界通行证并不是一个好的安全措施。

这个用例的一个可能的解决方案(希望两个通信进程在不同的用户下运行)可能是manager-user worker-user进程和worker-user进程在同一个组中,并且umask清除了group-perm位创建时,这两个进程可以读取和写入未命名的管道。

因此,如果

  1. manager-userteam拥有,
  2. worker-user也由team拥有,
  3. 两个进程的组umask位清零(没有值1x7x
  4. 在未命名的管道创建之前

然后, manager-user应该能够在未命名管道上写入,并且即使作为单独的用户运行, worker-user应该能够读取它(反之亦然,这取决于管道的使用方式)。

有关权限位的详细信息,请参见chmod上的man页。

使用pipe()函数的匿名管道,就像这样(这个例子是从德国维基百科借用的):

 # 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); } 

上面的程序创建一个单向管道,父进程保存读取结束,子进程保存写入结束。