Linux setuid使用
一、说明
2.1 背景说明
在上家公司的时候想实现应用进程不使用root用户启动,但开发反馈像配置网卡等命令就是得用root来执行的,领导朋友说可以通过setuid解决这个问题。
由于物联网设备毕竟是和硬件强相关的改造动作可能比较大又可能遗漏某些意想不到的地方,并没有着手处理root启动的问题。
所以自己对setuid使用不是很清楚,但也就没更进一步研究。最近总感觉这问题留在这让人很不舒服,所以就再来研究一下。
2.2 setuid的作用
setuid的程序,任何用户执行时,都以setuid程序文件所属的用户的身份运行。
一般使用场景是,对归属root的程序进行setuid,以便普通用户有root用户的权限。
二、setuid实现
演示操作:setuid前普通用户不能删除root用户的文件,setuid后普通用户可以删除root用户的文件。
2.1 环境准备
将以下代码保存成test.c:
#include <stdio.h> #include <unistd.h> int main() { printf("the uid is: %d\n", geteuid()); sleep(5); // system("rm -f test.txt"); remove("test.txt"); return 0; }
将其编译成可执行文件test:
gcc test.c -o test
创建搭配使用的test.txt:
touch test.txt
最终环境如下:
2.2 未setuid前删除文件失败
如下所示,未setuid前,用户身份就是普通用户(uid是1000),未能成功删除属于root的test.txt文件。
2.3 setuid后文件删除成功
如下所示,setuid(即对文件进行chmod +s)后,还是普通用户执行,但程序报运行自己的是root用户(uid是0),且确实能成功删除属于root用户的test.txt文件。
此时使用也可以ps看到虽是普通用户执行,但ps显示的是root用户。
三、setuid不可用的情况
3.1 shell脚本s权限无效
由于脚本s权限会导致较大的安全隐患,所以Linux调整成了只认可二进制可执行文件的s权限,而忽略脚本类可执行文件的s权限。脚本类包括shell、python等等。
3.2 子进程不继承s权限
脚本类文件s权限不受认可,那么可不可以先用C写个程序赋予s权限,然后在C里通过system()等函数调用脚本,从而通过“传递”实现脚本s权限呢。
答案是不行的。不仅system()调用脚本不行,system()调用二进制可执行文件也不具有s权限。
本质原因是,system()是通过fork()建立子进程,fork()建立子进程时把子进程归属uid而归属euid。
参考: