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

如果程序设置了setuid位,为什么/proc/self中的文件最终归root所有?,c,linux,security,setuid,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;

我有一个小程序:

#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);
}
然后我运行程序:

[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
所有,而不是
testing
omnifarious
?请注意,如果我移除
分叉
,结果不会改变

这让我烦恼的原因是,我需要创建一个程序,将自己作为用户而不是执行它的用户放入命名空间中。这样我就不能访问cgroup和启动程序的用户拥有的其他东西。但是我不允许写入程序的
uid\u映射
gid\u映射
,因此无法正确设置名称空间

注意:我编辑了这个问题,包括调用
prctl
,以设置(并读取)可转储的
标志,作为回答(手册)指出重置此标志应修复
/proc/self/*
文件的所有者。但事实并非如此,正如你从新计划中看到的那样


Edit:上述程序有一个错误,它调用的是
setresuid
,而不是
setresgid
。这就是导致我的问题的原因,即使在将调用添加到
prctl
之后也是如此。
prctl(PR\u SET\u DUMPABLE,1)调用无效。

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

通过使用prctl
PR\u set\u dumpable
手动使进程可转储,可以在
suid
之后设置所有者


以下是
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.
          (...)

有趣的我在上面的代码中插入了使用prctl重置可转储标志的代码,并将其打印出来。我成功地将其设置回1,但/proc/self的权限保持不变。即使I
fork
prctl
之后,但在
execve
之前。但是,在
/proc/sys/fs/suid\u dumpable
中放入1会导致
/proc/self
中的文件的所有权再次成为进程所有者的用户id。有趣的我想知道为什么
prctl
没有效果。我将用使用
prctl
的新程序修改我的问题。我已经解决了。我错过了几个应该用gid替换uid的地方,我没有将真正的组id重置为有效的组id。显然,如果实际用户id与有效用户id不匹配,或者实际组id与有效组id不匹配,则设置DUMPABLE标志无效。有趣。文件可能应该提到这一点。
   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.
          (...)