简体   繁体   English

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

[英]A second getpwuid call appears to overwrite old value

Here's a small C program that prints (well, supposed to print) the real and effective IDs of a process when the file has the setuid flag set. 这是一个小的C程序,当该文件设置了setuid标志时,该程序会打印(当然应该打印)进程的真实和有效ID。 In this program, when I call getpwuid a second time (L.No 38), it tends to overwrite the value of the variable realUserName that was obtained in L.No 24. I'm unable to explain this behavior. 在此程序中,当我第二次调用getpwuid (L.No 38)时,它趋向于覆盖在L.No 24中获得的变量realUserName的值。我无法解释这种现象。 Is this the expected behavior and why? 这是预期的行为,为什么? I'm trying this in a Linux box (RHEL 2.6.18-371.1.2.el5). 我正在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

Output: 输出:

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 >

The behaviour you observe is the expected one. 您观察到的行为是预期的行为。

The structure referenced by the return value of getpwuid() is defined statically internal to the latter, so it is expected to be filled (and with this overwritten) for each call to getpwuid() . getpwuid()的返回值引用的结构是在静态内部定义的,因此,每次对getpwuid()调用都应填充该结构(并覆盖此结构getpwuid()

This line 这条线

char * realUserName = realUser->pw_name; 

just stores a reference to a value held by this statically internal structure. 只是存储对该静态内部结构所保存的值的引用。 This value is also overwritten if the statically internal structure is overwritten by the next call to getpwuid() . 如果静态内部结构被下一次对getpwuid()调用覆盖,则此值也将被覆盖。

To get around this there are two possibilities: 为了解决这个问题,有两种可能性:

  • Use te reentrant version of getpwuid() which is getpwuid_r() . 使用getpwuid()可重入版本,即getpwuid_r() To be able to use it, add 为了能够使用它,添加

     #define _POSIX_SOURCE 

    before the very 1 st #include statement in your program's sources. 在程序源代码中的第一个 #include语句之前。

  • Create copy of the members you need, pw_name in this case. 创建所需成员的副本,在这种情况下为pw_name The can be achieved by for example doing: 可以通过执行以下操作来实现:

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

    Be awre that realUserName is now pointing to dynamically allocated memory, which needs to be free() ed by the program itself if not need anymore. 不要担心realUserName现在指向动态分配的内存,如果不再需要该内存,则程序本身需要free() ed。 To do so call 为此打电话

     free(realUserName); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM