来自 APUE
保存的 set-user-ID 是通过
exec函数从有效用户 ID 复制而来的。如果设置了文件的设置用户 ID 位,则在exec存储来自文件用户 ID 的有效用户 ID后保存该副本。
是不是意味着
首先将进程的 EUID 更改为文件的用户 ID,
那么进程保存的 set-user-ID 会更改为进程的 EUID 吗?
那么进程的 EUID 和保存的 set-user-ID 都更改为文件的用户 ID?
中的文档credentials(7)对 Linux 系统进行了一些澄清:
用户和组标识符
每个进程都有各种关联的用户和组 ID。这些 ID 是整数,分别使用类型
uid_t和gid_t(在 中定义<sys/types.h>)表示。在 Linux 上,每个进程都有以下用户和组标识符:
真实用户 ID 和真实组 ID。这些 ID 决定谁拥有进程。进程可以使用
getuid(2).有效用户 ID 和有效组 ID。内核使用这些 ID 来确定进程在访问共享资源(例如消息队列、共享内存和信号量)时将拥有的权限。在大多数 UNIX 系统上,这些 ID 还确定访问文件时的权限。但是,Linux 使用下面描述的文件系统 ID 来完成此任务。进程可以使用
geteuid(2).保存的 set-user-ID 和保存的 set-group-ID。这些 ID 在 set-user-ID 和 set-group-ID 程序中使用,以保存执行程序时设置的相应有效 ID 的副本(请参阅 参考资料
execve(2))。set-user-ID 程序可以通过在其真实用户 ID 和保存的 set-user-ID 中的值之间来回切换其有效用户 ID 来承担和放弃特权。这种切换是通过调用完成seteuid(2),setreuid(2)或setresuid(2)。一组基团的ID使用程序执行类似的任务setegid(2),setregid(2)或setresgid(2)。进程可以使用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;
}
Run Code Online (Sandbox Code Playgroud)
这是文件:
server /home/erik # ls -l perms
-r-sr-sr-x 1 nobody nobody 8280 Apr 26 00:36 perms
Run Code Online (Sandbox Code Playgroud)
运行为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
Run Code Online (Sandbox Code Playgroud)
运行为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
Run Code Online (Sandbox Code Playgroud)
正如我的测试程序所示,如果文件是 set-ID,则 EUID/EGID 以文件上的所有者/组开始(只有 set-UID 和 set-UID+GID 权限有效!),但可以更改如果程序需要,在它和调用者的真实 ID 之间。