From: http://blog.chinaunix.net/space.php? Uid = 1877180 & Do = Blog & cuid = 1132108
In Linux, each process has three [4th] user identifiers.
Real uid: real User ID.
Saved uid: saved user ID
Valid uid: valid user ID
The real User ID (real UID) is the login user,
Valid uid is used for all security checks ).
Generally:
Real uid = saved uid = valid uid
In some cases, the setuid and setruid functions can be used to change the valid uid.
Make the program run with special permissions. A common example is the passwd command in Linux,
Because all user information, including user passwords, are stored in the/etc/passwd file, and/etc/passwd
Only the root permission of the file can be read and written. If you want to allow each user to modify only their own password, you must
Allows common users to temporarily obtain limited read/write/etc/passwd permissions. Use setuid to solve this problem.
Problem.
Linux Setuid (UID) function:
(1) If called by a common user, set the valid ID of the current process to uid.
(2) If a process with a valid user ID of 0 is called, the real, valid, and saved user IDs are set
Set to uid.
The setuid function in Linux is different from the setuid function in UNIX.
The behavior of the. setuid (UID) function in UNIX:
(1) If the process does not have the superuser privilege and the UID is equal to the actual user ID or the saved user ID, only
Set valid user ID to uid. Otherwise, an error is returned.
(2) If the process has the superuser privilege, it will be real, valid, and
All saved user tokens are set to uid.
The main difference here is the behavior of normal users during calls. The cause of this problem is POSIX and
BSD implementation differences, while Linux supports both.
Setreuid (uid_t ruid, uid_t EUID)
Real UID and valid uid.
When a process with a user ID of 0 is called, The saved user ID is not changed. The seteuid (uid_t UID) function is equivalent.
In setreuid (-1, UID), only change the valid user ID (valid UID ).
Example:
Use setuid or setruid to allow non-root users to read
File.
# Assume the program name is setuid_ex.
# The file to be read is root_only.txt.
$ Users
Dd Admin
$ LS-l root_only.txt
-RW ------- 1 Root 33 Jan 11 :07 root_only.txt
$ VI setuid_ex.cpp
1 /**
2 * Linux Setuid function example.
3 **/
4 # include <unistd. h> // setuid () and getuid ()
5 # include <iostream>
6 # include <fstream>
7
8 using namespace STD;
9 void test_read_file (const char * name)
10 {
11 ifstream F (name );
12 if (F. Fail ())
13 cout <"= [Error]: Read failed." <Endl;
14 else
15 cout <"= [OK]: read successful." <Endl;
16}
17 // print UID and EUID.
18 inline void p_states (void)
19 {
20 int uid, EUID;
21 cout <"----- current states --------------------------" <Endl;
22 cout <"Real uid \ t" <getuid () <Endl;
23 cout <"valid tive uid \ t" <geteuid () <Endl;
24 cout <"---------------------------------------------" <Endl;
25}
26 // call setuid.
27 inline void run_setuid_fun (int uid)
28 {
29 If (setuid (UID) =-1)
30 cout <"= [Error]: setuid (" <uid <") error" <Endl;
31 p_states ();
32}
33 // call seteuid.
34 inline void run_seteuid_fun (int uid)
35 {
36 IF (seteuid (UID) =-1)
37 cout <"= [Error]: seteuid (" <uid <") error" <Endl;
38 p_states ();
39}
40
41 int main ()
42 {
43 int t_re = 0;
44 const char * file = "root_only.txt ";
45
46 cout <Endl <"Test 1:" <Endl;
47 p_states ();
48 // [1] at this time, real uid = Login User ID
49 // valid tive uid = root
50 // saved uid = root
51 test_read_file (File );
52
53 cout <Endl <"Test 2: seteuid (getuid ()" <Endl;
54 run_seteuid_fun (getuid ());
55 // [2] at this time, real uid = Login User ID
56 // valid tive uid = Login User ID
57 // saved uid = root
58 test_read_file (File );
59
60 cout <Endl <"Test 3: seteuid (0)" <Endl;
61 run_seteuid_fun (0 );
62 // [3] at this time, real uid = Login User ID
63 // valid tive uid = root
64 // saved uid = root
65 test_read_file (File );
66
67 cout <Endl <"Test 4: setuid (0)" <Endl;
68 run_setuid_fun (0 );
69 // [4] at this time, real uid = root
70 // valid tive uid = root
71 // saved uid = root
72 test_read_file (File );
73
74 cout <Endl <"Test 5: setuid (503)" <Endl;
75 run_setuid_fun (503 );
76 // [5] at this time, real uid = Login User ID
77 // valid tive uid = Login User ID
78 // saved uid = Login User ID
79 test_read_file (File );
80
81 cout <Endl <"Test 6: setuid (0)" <Endl;
82 // [6] at this time, real uid = Login User ID
83 // valid tive uid = Login User ID
84 // saved uid = Login User ID
85 // running setuid (0) will return the error value-1.
86 run_setuid_fun (0 );
87 test_read_file (File );
88 return 0;
89}
90
91
$ VI makefile
1 src = setuid_ex.cpp
2 EXE = setuid_ex
3 cc = g ++
4 flags =-G
5
6 All: $ {SRC}
7 $ {CC }$ {flags}-o $ {EXE}
8 chown root: root $ {EXE}
9 ### in fact, chmod 4111 changes the valid tive ID and saved uid values.
10 ### this is also the premise for the setuid setruid function to switch between different permissions.
11 chmod 4111 $ {EXE}
$ Sudo make # Use root for make.
$ LS-l setuid_ex
--- S -- X 1 Root 58579 Jan 15 11: 27 setuid_ex
$./Setuid_ex
Test 1:
----- Current states --------------------------
Real uid 503
Valid tive UID 0
---------------------------------------------
= [OK]: read successful.
Test 2: seteuid (getuid ())
----- Current states --------------------------
Real uid 503
Valid tive uid 503
---------------------------------------------
= [Error]: Read failed.
Test 3: seteuid (0)
----- Current states --------------------------
Real uid 503
Valid tive UID 0
---------------------------------------------
= [OK]: read successful.
Test 4: setuid (0)
----- Current states --------------------------
Real UID 0
Valid tive UID 0
---------------------------------------------
= [OK]: read successful.
Test 5: setuid (503)
----- Current states --------------------------
Real uid 503
Valid tive uid 503
---------------------------------------------
= [Error]: Read failed.
Test 6: setuid (0)
= [Error]: setuid (0) Error
----- Current states --------------------------
Real uid 503
Valid tive uid 503
---------------------------------------------
= [Error]: Read failed.