c - 第二个 getpwuid 调用似乎覆盖了旧值

标签 c linux rhel setuid getpwuid

这是一个小型 C 程序,当文件设置了 setuid 标志时,它会打印(好吧,应该打印)进程的真实有效 ID。在这个程序中,当我第二次调用getpwuid时(L.No 38),它往往会覆盖在L.No 24中获得的变量realUserName的值.我无法解释这种行为。这是预期的行为吗?为什么?我正在 Linux 机器 (RHEL 2.6.18-371.1.2.el5) 中尝试此操作。

  1 /* Filename: test.c
  2  * Notes:
  3  * 1] ./test owned by user cadmn (userID: 3585)
  4  * 2] ./test run by user pmn (4471)
  5  * 3] ./test has the setuid bit switched-on.
  6  */
  7 #include <stdio.h>
  8 #include <pwd.h>
  9 #include <sys/types.h>
 10 #include <unistd.h>
 11 int main()
 12 {
 13
 14     uid_t realId, effectiveId;
 15     struct passwd *realUser, *effUser;
 16
 17     realId = getuid(); // realId = 4471
 18     effectiveId = geteuid(); //effectiveId = 3585
 19
 20     printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
 21     //prints 4472 and 3585, respectively
 22
 23     realUser = getpwuid(realId);
 24     char *realUserName = realUser->pw_name; //realUserName = pmn
 25
 26     printf("Real ID (name) at this point is %s\n", realUserName);
 27     // prints pmn.
 28
 29     /*
 30      *********************************************************
 31      *                                                       *
 32      *    everything works as expected up to this point      *
 33      *                                                       *
 34      *********************************************************
 35      */
 36
 37     // The value obtained from this call is not used anywhere in this program
 38     effUser = getpwuid(effectiveId);
 39     printf("\nCalled getpwuid with the effectiveId\n\n");
 40
 41     printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
 42     //prints 4472 and 3585, respectively
 43
 44     printf("Real ID (name) at this point is %s.\n", realUserName);
 45     // Expect to still see 'pmn' printed; though see 'cadmn' as the output!
 46     // Why does this happen?
 47
 48     return 0;
 49 }
 50

输出:

pmn@rhel /tmp/temp > id pmn
uid=4471(pmn) gid=1000(nusers) groups=1000(nusers)
pmn@rhel /tmp/temp >

pmn@rhel /tmp/temp > id cadmn
uid=3585(cadmn) gid=401(cusers) groups=401(cusers)
pmn@rhel /tmp/temp >

pmn@rhel /tmp/temp > ls -l ./test
-r-sr-xr-x 1 cadmn cusers 9377 Dec 24 19:48 ./test
pmn@rhel /tmp/temp >

pmn@rhel /tmp/temp > ./test
Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is pmn

Called getpwuid with the effectiveId

Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is cadmn.
pmn@rhel /tmp/temp >

最佳答案

您观察到的行为是预期的行为。

getpwuid() 的返回值引用的结构是在后者内部静态定义的,因此每次调用 getpwuid 时都会填充(并覆盖)该结构().

这一行

char * realUserName = realUser->pw_name; 

仅存储对此静态内部结构所保存的值的引用。如果下次调用 getpwuid() 覆盖静态内部结构,则该值也会被覆盖。

要解决这个问题,有两种可能性:

  • 使用getpwuid()的可重入版本,即getpwuid_r() 。为了能够使用它,添加

    #define _POSIX_SOURCE
    

    在程序源代码中第一个st #include 语句之前。

  • 创建所需成员的副本,在本例中为pw_name。例如,可以通过执行以下操作来实现:

    char * realUserName = strdup(realUser->pw_name);
    

    请注意,realUserName 现在指向动态分配的内存,如果不再需要,需要由程序本身free()释放。为此,请调用

    free(realUserName); 
    

关于c - 第二个 getpwuid 调用似乎覆盖了旧值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20757940/

相关文章:

linux - Linux RHEL 上的 RabbitMQ 内部内存路径映射到另一个位置

c - 尝试访问 C 中二维数组的地址并出现段错误

c - 这个结构代码是如何工作的

linux - 如何将变量传递给 bash 脚本中的命令参数?

linux - 在bash中将数字分成等份

ruby - RVM Ruby 安装破坏了引导节点上的 Chef-Client

compiler-errors - gcc 汇编程序消息无法打开/tmp/ccqjY5HV.s 以读取没有这样的文件或目录

c - 在 Win32 API 上将结构传递给线程时出现指针问题

为位图创建滚动条

linux - CentOS 6.3 上 eth0 和 venet0 配置的区别