2

以下は、ファイルに setuid フラグが設定されている場合に、プロセスの実際の ID と有効な ID を出力する (出力するはずの) 小さな C プログラムです。このプログラムではgetpwuid、2 回目に呼び出すと (L.No 38)、realUserNameL.No 24 で取得した変数の値を上書きする傾向があります。この動作は説明できません。これは予想される動作で、その理由は何ですか? これを 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 >
4

1 に答える 1

3

あなたが観察する動作は期待されるものです。

の戻り値によって参照される構造体getpwuid()は、後者の内部で静的に定義されるため、 への呼び出しごとに埋められる (そして上書きされる) ことが期待されますgetpwuid()

この行

char * realUserName = realUser->pw_name; 

この静的な内部構造が保持する値への参照を格納するだけです。この値は、静的な内部構造が への次の呼び出しによって上書きされる場合にも上書きされますgetpwuid()

これを回避するには、次の 2 つの方法があります。

  • の再入可能バージョンを使用getpwuid()しますgetpwuid_r()。それを使用できるようにするには、追加します

    #define _POSIX_SOURCE
    

    プログラムのソースの最初のステートメント 前。#include

  • pw_nameこの場合、必要なメンバーのコピーを作成します。これは、たとえば次のようにして実現できます。

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

    realUserName動的に割り当てられたメモリを指していることに注意してください。これはfree()、もう必要ない場合はプログラム自体で編集する必要があります。そのために電話する

    free(realUserName); 
    
于 2013-12-24T09:36:43.857 に答える