Linux进程ID小结

linux 进程中有三个ID:实际用户ID,有效用户ID和设置用户ID。

在Linux下执行一个文件主要涉及到2个用户,一个是当前运行的用户,一个则是文件的所有者。这三个ID就和这2个用户有关。
另外,linux下的文件权限除了正常的ugo之外,还有suid,sgid等(suid表示使具有x权限的用户在执行该文件时,具有该文件所有者的权限,可以通过chmod u+s 打开)。

实际用户ID表示运行进程的用户ID,即当前的用户。除非后面有root权限的进程通过setuid方法去重设,否则该ID不变。

有效用户ID则定义了进程所具有的访问权限,当该进程的执行文件没有设置suid时,有效用户ID=实际用户ID,当设置了suid时,有效用户ID=该执行文件的所有者ID。在调用setuid的方法时,主要改变的就是它。当setuid的参数是当前实际用户ID或者是保存的设置用户ID时,则可设置成功,换句话说,在一般用户(非root)模式下,setuid方法可以使有效用户ID在实际用户ID和设置用户ID之间切换,以适应访问权限需求,则也是同suid位的意义是一致的。

设置用户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切换回来。


如果有错误,请大家不吝指正,非常感谢!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值