设置用户ID则是有效用户ID的副本,当进程运行时,设置用户ID被设置成有效用户ID(由于有效用户ID会根据suid位被设置成实际用户ID或者执行文件所有者ID,所以该设置用户ID也会变)。除非后面有root权限的进程通过setuid方法去重设,否则该ID不变。
代码说话:
test.cpp:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
printf("int test and uid is %d\n",getuid());
printf("int test and euid is %d\n",geteuid());
}
runtest.cpp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char* argv[])
{
assert(argc==2);
int uid=atoi(argv[1]);
pid_t child = 0;
if ((child=fork())<0)
{
}
else if(child > 0)
{
//parent process
}
else//child==0
{
//child process
int result=setuid(uid);
if(-1==result)
{
printf("setuid failed\n");
}
printf("in runtest and uid is %d\n",getuid());
printf("in runtest and euid is %d\n",geteuid());
result=execl("/home/shared/test",(char*)0);
exit(0);
}
return 0;
}
在这两个程序中,会获取当前用户ID和有效用户ID,runtest会根据传入的uid参数,设置有效用户ID并调用test。把这两个程序分别编译出具有suid和不具有suid的可执行文件,所有者都是dodomouse
-rwxrwxr-x. 1 dodomouse dodomouse 9039 Aug 31 19:01 runtest
-rwxrwxrwx. 1 dodomouse dodomouse 543 Aug 31 19:01 runtest.cpp
-rwsrwxr-x. 1 dodomouse dodomouse 9039 Aug 31 19:06 sruntest //具有suid位
-rwsrwxr-x. 1 dodomouse dodomouse 8619 Aug 31 19:45 stest //具有suid位
-rwxrwxr-x. 1 dodomouse dodomouse 8619 Aug 31 19:45 test
-rwxrwxrwx. 1 dodomouse dodomouse 171 Aug 31 18:55 test.cpp
运行结果:
[mouse@localhost shared]$ ./test //当执行没有suid的test时,uid=euid
int test and uid is 1002
int test and euid is 1002
[mouse@localhost shared]$ ./stest //当执行有suid的时候,euid等于文件所有者的id了
int test and uid is 1002
int test and euid is 1000
[root@localhost shared]# ./test
int test and uid is 0
int test and euid is 0
[root@localhost shared]# ./stest //对于root来说,euid也还是文件所有者
int test and uid is 0
int test and euid is 1000</span>
普通用户的setuid:
[mouse@localhost shared]$ ./runtest 1000
setuid failed
in runtest and uid is 1002
in runtest and euid is 1002
int test and uid is 1002
int test and euid is 1002
[mouse@localhost shared]$ ./runtest 1001
setuid failed
in runtest and uid is 1002
in runtest and euid is 1002
int test and uid is 1002
int test and euid is 1002
[mouse@localhost shared]$ ./runtest 1002 //以上这三个case表明在没有设置suid的情况下,
in runtest and uid is 1002 //setuid只能设置为实际用户ID
in runtest and euid is 1002
int test and uid is 1002
int test and euid is 1002
[mouse@localhost shared]$ ./sruntest 1000 //当有suid位的时候,可以把执行程序的所有者ID设为有效用户ID
in runtest and uid is 1002
in runtest and euid is 1000
int test and uid is 1002
int test and euid is 1000
[mouse@localhost shared]$ ./sruntest 1001 //仍旧不能把其他ID设为有效用户ID
setuid failed
in runtest and uid is 1002
in runtest and euid is 1000
int test and uid is 1002
int test and euid is 1000
[mouse@localhost shared]$ ./sruntest 1002 //可以设自己的ID位有效用户ID
in runtest and uid is 1002
in runtest and euid is 1002
int test and uid is 1002
int test and euid is 1002
对于root就不一样了:
[root@localhost shared]# ./runtest 1000 //对于没有suid位,直接设为参数uid
in runtest and uid is 1000
in runtest and euid is 1000
int test and uid is 1000
int test and euid is 1000
[root@localhost shared]# ./runtest 1001
in runtest and uid is 1001
in runtest and euid is 1001
int test and uid is 1001
int test and euid is 1001
[root@localhost shared]# ./sruntest 1000 //可以设置为执行程序所有者的uid,但是设置其他uid的时候却失败了。
in runtest and uid is 0 //因为此时的uid正是执行程序所有者自己了。
in runtest and euid is 1000 //从./stest中可以看出当具有suid位的程序执行时,哪怕是root,
int test and uid is 0 //有效用户ID也变成了执行程序所有者自己了。
int test and euid is 1000
[root@localhost shared]# ./sruntest 1001
setuid failed
in runtest and uid is 0
in runtest and euid is 1000
int test and uid is 0
int test and euid is 1000
[root@localhost shared]# ./sruntest 0 //当把设置的uid设为root本身的时候,就把所有的ID均设为root本身了。
in runtest and uid is 0
in runtest and euid is 0
int test and uid is 0
int test and euid is 0
[root@localhost shared]# ./stest
int test and uid is 0
int test and euid is 1000
对于sgid位来说,也是大同小异。
总结:进程运行时的权限取决于有效用户ID,即geteuid()获取的那个。当实际用户是非root用户时,设置用户ID来源于刚开始运行执行程序时的有效用户ID,之后则不变。而有效用户ID只能在实际用户ID和设置用户ID之间切换。对于root用户来讲,当执行文件没有suid的时候,可以设置任意的有效用户ID,实际用户ID和设置用户ID。否则运行执行程序文件的时候,有效用户ID的root权限会被替换为文件拥有者的ID而暂时失去root权限,需要通过setuid切换回来。
如果有错误,请大家不吝指正,非常感谢!!!