c - 如果程序设置了 setuid 位,为什么/proc/self 中的文件最终会归 root 所有?

标签 c linux security setuid

我有这个小程序:

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <sys/prctl.h>

extern char **environ;

int main()
{
   char * const arglist[] = { "/bin/ls", "-l", "/proc/self/maps", NULL };
   uid_t uid, euid, suid;
   gid_t gid, egid, sgid;

   getresuid(&uid, &euid, &suid);
   printf("Before: uid: %u, euid: %u, suid: %u\n", uid, euid, suid);
   uid = euid;
   setresuid(uid, euid, suid);
   getresuid(&uid, &euid, &suid);
   printf(" After: uid: %u, euid: %u, suid: %u\n", uid, euid, suid);

   getresgid(&gid, &egid, &sgid);
   printf("Before: gid: %u, egid: %u, sgid: %u\n", gid, egid, sgid);
   gid = egid;
   setresuid(gid, egid, sgid);
   getresuid(&gid, &egid, &sgid);
   printf(" After: gid: %u, egid: %u, sgid: %u\n", gid, egid, sgid);

   printf("Get result == %d\n", prctl(PR_GET_DUMPABLE, 0, 0, 0, 0));
   printf("Set result == %d\n", prctl(PR_SET_DUMPABLE, 1, 0, 0, 0));
   printf("Get result == %d\n", prctl(PR_GET_DUMPABLE, 0, 0, 0, 0));

   if (fork())
   {
      return 0;
   }
   execve(arglist[0], arglist, environ);
}

我将此程序编译为名为 small-test 的可执行文件,并将其所有权更改为测试用户:

[omnifarious@foohost ~]$ ls -l small-test
-rwxrwxr-x. 1 testing testing 8512 Oct 23 12:55 small-test

然后我运行该程序:

[omnifarious@foohost ~]$ ./small-test 
Before: uid: 1001, euid: 1001, suid: 1001
 After: uid: 1001, euid: 1001, suid: 1001
Before: gid: 1001, egid: 1001, sgid: 1001
 After: gid: 1001, egid: 1001, sgid: 1001
Get result == 1
Set result == 0
Get result == 1
-r--r--r--. 1 hopper hopper 0 Oct 23 14:50 /proc/self/maps

到目前为止,一切都很好。然后我这样做:

[omnifarious@foohost ~]$ sudo chmod ug+s ./small-test
[omnifarious@foohost ~]$ ls -l ./small-test
-rwsrwsr-x. 1 testing testing 8512 Oct 23 12:55 ./small-test
[omnifarious@foohost ~]$ ./small-test 
Before: uid: 1001, euid: 1002, suid: 1002
 After: uid: 1002, euid: 1002, suid: 1002
Before: gid: 1001, egid: 1002, sgid: 1002
 After: gid: 1002, egid: 1002, sgid: 1002
Get result == 0
Set result == 0
Get result == 1
-r--r--r--. 1 root root 0 Oct 23 12:59 /proc/self/maps

为什么/proc/self/maps最终由root拥有,而不是由testingomnifarian拥有>?请注意,如果我移除fork,结果不会改变。

这让我烦恼的原因是我需要创建一个程序,将自己作为执行它的用户之外的用户放入命名空间中。这样我就无法访问启动该程序的用户拥有的 cgroup 和其他内容。但我不被允许写入程序的 uid_mapgid_map,因此我无法正确设置命名空间。

注意:我编辑了此问题,添加了对 prctl 的调用,以设置(并读取)DUMPABLE 标志作为答案(并且手册)表明重置此设置应该修复 /proc/self/* 文件的所有者。正如您在新程序中看到的那样,事实并非如此。

编辑:上面的程序有一个错误,它调用的是setresuid而不是setresgid。即使在添加对 prctl 的调用之后,这也是导致我出现问题的原因。如果进程的真实有效组和用户 ID 不相同,则 prctl(PR_SET_DUMPABLE, 1); 调用无效。

最佳答案

出于安全原因,任何 suid 进程都默认将其 /proc/self 目录归 root 所有(以防止用户引发核心转储并检查其内存以获取有值(value)的信息)。

您可以在 suid 之后通过使用 prctl PR_SET_DUMPABLE 手动使进程可转储来设置所有者。


这是 proc(5),其中包含对正在发生的情况以及如何影响它的描述:

   /proc/[pid]
          There is a numerical subdirectory for each running
          process; the subdirectory is named by the  process
          ID.

          Each /proc/[pid] subdirectory contains the pseudo-
          files  and  directories  described  below.   These
          files are normally owned by the effective user and
          effective group ID of the process.  However, as  a
          security  measure, the ownership is made root:root
          if the process's "dumpable" attribute is set to  a
          value other than 1.  This attribute may change for
          the following reasons:

          *  The  attribute  was  explicitly  set  via   the
             prctl(2) PR_SET_DUMPABLE operation.

          *  The  attribute  was  reset  to the value in the
             file   /proc/sys/fs/suid_dumpable    (described
             below), for the reasons described in prctl(2).

          Resetting  the  "dumpable"  attribute to 1 reverts
          the ownership of the /proc/[pid]/*  files  to  the
          process's real UID and real GID.

下面,suid_dumpable 说明了为什么默认值是这样的:

          1 ("debug")
                 All  processes  dump  core  when  possible.
                 (Reasons  why  a process might nevertheless
                 not dump core are  described  in  core(5).)
                 The  core  dump  is owned by the filesystem
                 user ID of the dumping process and no secu‐
                 rity is applied.  This is intended for sys‐
                 tem debugging situations only: this mode is
                 insecure  because  it  allows  unprivileged
                 users to examine  the  memory  contents  of
                 privileged processes.

作为奖励,prctl(2) 列出了影响可转储性的非 suid 情况:

   PR_SET_DUMPABLE (since Linux 2.3.20)
          (...)
          Normally,  this  flag is set to 1.  However, it is
          reset to the current value contained in  the  file
          /proc/sys/fs/suid_dumpable  (which  by default has
          the value 0), in the following circumstances:

          *  The process's effective user  or  group  ID  is
             changed.

          *  The  process's  filesystem  user or group ID is
             changed (see credentials(7)).

          *  The process executes (execve(2)) a  set-user-ID
             or  set-group-ID program, resulting in a change
             of either the effective user ID or  the  effec‐
             tive group ID.
          (...)

关于c - 如果程序设置了 setuid 位,为什么/proc/self 中的文件最终会归 root 所有?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46897570/

相关文章:

c - stdio 错误检测 : ferror versus fclose

javascript - 在 Google Chrome 中调试 CSP 违规

android - ]无法在 Ubuntu 14 中启动 Android Studio

java - Spring 安全 : Ignoring alias of server-name and forcing relogin

java - Websphere MQ v7 - Java 中的安全退出?

c - 如何使用 regex.h 查找美元符号

java - 如何在Java中处理C字符数组

签名中带有数组类型的 ccall 从 Julia 调用 C 中的结构

找不到在另一个动态库中定义的符号

java - stdin 数据流的第一个字节是否会触发 bash 命令运行?