我有一个过程磷它是由 root 拥有的进程产生的。后磷创建 setguid() 并调用 setuid() 并以用户身份运行U。
过程磷尝试创建文件F在文件夹上F(在根文件系统中)由root拥有并具有以下权限:
drwxrwx--- 2 root root
函数调用如下所示:
open(path , O_CREAT | O_RDWR , 0660);
如果我运行命令ps -e -o cmd,uid,euid,ruid,suid,gid,egid,rgid,sgid 结果如下:
/my/process 500 500 500 500 500 500 500 500
这证实了该过程磷没有以 root 身份运行,但是很奇怪,即使该进程以用户身份运行U文件F是在文件夹下创建的F只能由 root 及其组成员写入:
-rw-rw---- 1 U U
所以该文件的所有者是U。
如果我尝试从 bash 中执行相同的操作,我会按预期得到“权限被拒绝”:
$ touch /F/f
touch: cannot touch `/F/f': Permission denied
如果我设置文件夹F权限:
drwx------ 2 root root
那么 open() 调用将失败,并按预期显示“权限被拒绝”。
为什么可以磷当向根组授予写入权限时,在该文件夹中创建文件吗?
这附注命令显示所有 uid 和 gid 都设置为相关的用户 id,那怎么可能呢?
这些是组成员身份根和U:
$groups root
root : root
$groups U
U : U G
所以U有G作为次要群体
$lid -g root
root(uid=0)
sync(uid=5)
shutdown(uid=6)
halt(uid=7)
operator(uid=11)
$lid -g U
U(uid=500)
$lid -g G
U(uid=500)
这表明仅U是的成员G
答案1
就像@jdwolf 在评论中提到的那样,问题可能是补充组。setgid()
不会删除它们。
一个简单的测试,./drop
下面是一个程序,调用setregid()
和setreuid()
将 GID 和 UID 更改为nobody
,然后运行id
:
# id
uid=0(root) gid=0(root) groups=0(root)
# ./drop
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup),0(root)
还有零组。添加setgroups(0, NULL)
(在 之前setuid()
)会删除该组:
# ./drop2
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
当然,这不会添加任何其他目标用户的组。