博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux setuid函数_setuid函数解析
阅读量:1540 次
发布时间:2019-04-21

本文共 3251 字,大约阅读时间需要 10 分钟。

在讨论这个setuid函数之前,我们首先要了解的一个东西就是内核为每个进程维护的三个UID值。这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user-ID)。

首先说这个实际用户ID,就是我们当前以哪个用户登录了,我们运行的程序的实际用户ID就是这个用户的ID。有效用户ID就是当前进程是以哪个用户ID来运行的,一般情况下是实际用户ID,如果可执行文件具有了SUID权限,那么它的有效用户ID就是可执行文件的拥有者。保存的设置用户ID就是有效用户ID的一个副本,与SUID权限有关。

关于那个SUID,最经典的例子莫过于passwd命令。passwd这个可执行文件的所有者是root,但是其他用户对于它也有执行权限,并且它自身具有SUID权限。那么当其他用户来执行passwd这个可执行文件的时候,产生的进程的就是以root用户的ID来运行的。如下图所示:

3661dbab082d6a865debd69cf6575a42.png

这个passwd的所有者是root,并且在权限那一栏中s代表的是SUID权限。我以普通用户michael来运行这个命令,产生的进程如下:

2ff2087c000aaed9ba9c8a735b04c89a.png

大家可以看到,倒数第二行这个进程其命令是passwd,但是其USER却是root。这就是SUID权限。

接下来,我们开始扯正题,setuid函数。这是setuid函数的声明和返回值:

c89b5720875d1a9fa672f7bdbe7856da.png

955f34b9fd3458cd2e99da62677b411d.png

如果成功返回0,如果失败返回-1,并将errno设置为合适的值。

关于这个函数的功能,APUE(《UNIX环境高级编程》,下面的APUE为相同的意思,不再赘述)上面是这样写的:

1ccede8beb3987d6e779e543c50042d5.png

这样光讲概念可能有点干巴巴了,下面我来举几个分别说明一下:

开始讲之前,我先验证一下我的电脑是支持"保存的设置用户ID"这个功能的,在电脑上运行以下代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #define BUFSIZE 512

8 void err_exit(char *fmt,...);9 int main(int argc,char *argv[])10 {11 if(sysconf(_SC_SAVED_IDS) > 0)12 printf("_POSIX_SAVED_IDS effective!\n");13

14 return 0;15 }

程序的运行结果如下:

8c2778412b2f7e710102888814b1fc7e.png

首先说一下我用到的用户,一共使用了三个用户,root(UID=0),michael(UID=500),xiaojie(UID=501)如下图所示:

5c3ce3a6bdec6537faa4f01870cd47f9.png

先讲第一点,如果进程具有超级用户特权,那么这三个UID都被设置成了uid(setuid函数的参数)的值。比如下面这段代码:

1 #include

2 #include

3 #include

4 int main(int argc,char *argv[])5 {6 uid_t ruid,euid,suid;7 //这三个uid分别是实际用户ID,有效用户ID,保存的设置用户ID

8

9 setuid(500);10 getresuid(&ruid,&euid,&suid);11 printf("real:%d\teffective:%d\tset-user-id:%d\n",ruid,euid,suid);12

13 return 0;14 }

我用root用户来运行这个程序,那么刚开始这个进程的有效用户ID为0,然后这个进程中调用setuid(500),这三个UID的值都会被设置成500(在程序中通过getresuid函数来获取进程的三个UID的值),运行结果如下图:

ea6b0b327419c5542c5d6a28d34ad0e8.png

接下来我们再来讨论第二种情况,如果函数的参数uid等于进程的实际用户ID或者保存的设置用户ID,那么就将有效用户ID设置为uid,其他的两个(实际用户ID和保存的设置用户ID)保持不变。比如下面这个程序:

1 #include

2 #include

3 #include

4 void err_exit(char *fmt,...);5 int main(int argc,char *argv[])6 {7 uid_t ruid,euid,suid;8

9 printf("Before:\n");10 if(-1 == getresuid(&ruid,&euid,&suid))11 err_exit("[getresuid]:");12 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);13 setuid(500);14 printf("After:\n");15 if(-1 == getresuid(&ruid,&euid,&suid))16 err_exit("[getresuid]:");17 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);18

19 return 0;20 }

关于这段代码生成的可执行文件,我让它的拥有者变成了xiaojie(UID=501),并且给它加上了SUID权限,如下图所示:

9869977e4b74891efbc66ad79f8e4bfe.png

然后我用michael用户(UID=500)来运行这个程序,那么这个程序的实际用户ID=500,而有效用户ID和保存的设置用户ID都为501。接着,在这个程序中调用setuid函数,传入的参数为500,大家可以猜想到,最终应该只有有效用户ID受到影响,而保存的设置用户ID保持不变。运行结果如下图所示:

a0690ee66b65ad86cb056627b22d42bf.png

这就符合了我们的预期,仅仅只有有效用户ID受到了影响,而实际用户ID和保存的设置用户ID并没有改变。(这里我仅仅是验证了保存的设置用户ID不受影响,大家也可以自己写一个程序,来验证实际用户ID并不受影响。)

最后一点,如果setuid函数的参数的uid的值即不等于实际用户ID,也不等于保存的设置用户ID,而且这个进程的有效用户ID也不是0(非特权进程)。那么这个程序就会出错,并将errno设置为EPERM。比如下面这个程序:

1 #include

2 #include

3 #include

4 #include

5 #include

6 int main(int argc,char *argv[])7 {8 uid_t ruid,euid,suid;9

10 getresuid(&ruid,&euid,&suid);11 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);12

13 if(-1 == setuid(500))14 {15 printf("%s\n",strerror(errno));16 if(errno ==EPERM)17 {18 printf("Error number is EPERM!\n");19 }20 }21 else

22 {23 getresuid(&ruid,&euid,&suid);24 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);25 }26

27 return 0;28 }

我以xiaojie用户(UID=501)来运行这个程序,那么这个程序的三个用户ID都为501,然后在这个程序中,调用setuid(500)。于是程序就会报错,并将errno设置为EPERM,如下图所示:

e60151f4c059099d3ec7daf1ba91de84.png

OK,这就是APUE上关于setuid函数的解释,讲了这么多,综合成一句话就是,root是神,想怎么干就怎么干,没人管得了。而普通用户呢,只能管自己分内的事(把进程的有效ID改成自己的ID),不能胡乱来。

OK,that‘s all。希望这篇文章对大家能够有帮助。

转载地址:http://ulrdy.baihongyu.com/

你可能感兴趣的文章
Centos7 开机自动加载 模块 ko
查看>>
Mybatis plus 多表联查字段名重复处理 Column 'xxxx' in where clause is ambiguous
查看>>
springboot H2数据库持久化配置
查看>>
SpringCloud Consul 程序控制服务上下线
查看>>
Springboot 实现启动后动态修改配置
查看>>
车架号OCR识别算法
查看>>
车牌识别系统
查看>>
是时候给自己搞一台示波器了
查看>>
减小波形噪声的方法-示波器
查看>>
示波器探头介绍
查看>>
示波器基础二十问(上)
查看>>
示波器基础知识二十问(下)
查看>>
示波器安全使用原则
查看>>
麦科信示波器直播回放相关汇总(不断更新)
查看>>
用示波器测量福特福克斯智能交流发电机波形
查看>>
用示波器测量汽车COP独立点火信号与简要分析
查看>>
汽车氧传感器信号示波器测量(锆氧带加热器)
查看>>
通过示波器主板讲解示波器原理
查看>>
如何用示波器测量汽车爆震传感器及波形分析
查看>>
用示波器测量汽车节气门传感器信号的方法
查看>>