来自APUE
保存的设置用户ID是通过
exec
函数从有效用户ID复制而来的。如果文件的设置用户 ID 位已设置,则保存此副本后exec
存储文件用户 ID 中的有效用户 ID。
是不是意味着
首先进程的 EUID 更改为文件的用户 ID,
那么进程保存的set-user-ID是否会更改为进程的EUID?
那么进程的 EUID 和保存的 set-user-ID 都更改为文件的用户 ID 吗?
答案1
这文档在credentials(7)
针对 Linux 系统澄清了这一点:
用户和组标识符
每个进程都有各种关联的用户和组 ID。这些 ID 是整数,分别使用类型
uid_t
和gid_t
表示(在 中定义<sys/types.h>
)。在 Linux 上,每个进程都有以下用户和组标识符:
真实用户ID和真实组ID。这些 ID 确定谁拥有该进程。进程可以使用 获取其真实用户(组)ID
getuid(2)
。有效用户ID和有效组ID。内核使用这些 ID 来确定进程在访问消息队列、共享内存和信号量等共享资源时所拥有的权限。在大多数 UNIX 系统上,这些 ID 还确定访问文件时的权限。但是,Linux 使用下面描述的文件系统 ID 来执行此任务。进程可以使用 获取其有效用户(组)ID
geteuid(2)
。已保存的设置用户 ID 和已保存的设置组 ID。这些 ID 在 set-user-ID 和 set-group-ID 程序中用于保存程序执行时设置的相应有效 ID 的副本(请参阅 参考资料
execve(2)
)。设置用户 ID 程序可以通过在其真实用户 ID 和保存的设置用户 ID 中的值之间来回切换其有效用户 ID 来获取和放弃特权。这种切换是通过调用seteuid(2)
、setreuid(2)
、 或 来完成的setresuid(2)
。 set-group-ID 程序使用setegid(2)
、setregid(2)
或执行类似的任务setresgid(2)
。进程可以使用 获取其保存的 set-user-ID (set-group-ID)getresuid(2)
。[...]
我编写了一个测试程序来看看会发生什么:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int getuids(uid_t *uids) {
if(getresuid(&uids[0], &uids[1], &uids[2]) == -1) {
perror("Unable to get UIDs\n");
return 0;
}
return 1;
}
int getgids(gid_t *gids) {
if(getresgid(&gids[0], &gids[1], &gids[2]) == -1) {
perror("Unable to get GIDs\n");
return 0;
}
return 1;
}
int main(void) {
uid_t uids[3];
gid_t gids[3];
if(getuids(uids) && getgids(gids)) {
printf("Real ID: user %d, group %d\n", (int)uids[0], (int)gids[0]);
printf("Effective ID: user %d, group %d\n", (int)uids[1], (int)gids[1]);
printf("Set-ID: user %d, group %d\n", (int)uids[2], (int)gids[2]);
seteuid(uids[0]);
getuids(uids);
getgids(gids);
printf("Effective ID: user %d, group %d\n", (int)uids[1], (int)gids[1]);
}
return 0;
}
这是文件:
server /home/erik # ls -l perms
-r-sr-sr-x 1 nobody nobody 8280 Apr 26 00:36 perms
运行为root
:
server-calgary /home/erik # ./perms
Real ID: user 0, group 0
Effective ID: user 65534, group 65534
Set-ID: user 65534, group 65534
Effective ID: user 0, group 65534
运行为erik
:
erik@server ~ $ ./perms
Real ID: user 1000, group 1000
Effective ID: user 65534, group 65534
Set-ID: user 65534, group 65534
Effective ID: user 1000, group 65534
正如我的测试程序所示,如果文件是 set-ID,则 EUID/EGID 以文件上的所有者/组的任何内容开头(只有 set-UID 和 set-UID+GID 权限有效!),但它可以更改如果程序需要的话,可以在该 ID 和呼叫者的真实 ID 之间进行。