@Rotem jackoby的回答很好。作为休闲,你可以看到我对这篇文章的回答。它包含一个示例C程序,你可以运行它,亲眼看看Linux中 * 进程 * 的真实的用户ID(RUID),有效的用户ID(EUID)和保存的用户ID(SUID)之间的区别。 在这里我只想指出,所有类Unix系统的官方文档,当然包括Linux,* The Open Group Base Specifications Issue 7,2018 edition*(参见“3.定义”here),指出了RUID的概念,EUID和SUID适用于“当用户的身份与 * 进程 * 相关联时”(参见3.436 User ID here)。换句话说,如果用户没有启动或生成任何进程,那么谈论RUID、EUID或SUID就没有意义,但仅关于用户ID(UID),仅此而已。
5条答案
按热度按时间lf5gs5x21#
区分真实的和有效的用户id是因为您可能需要临时使用另一个用户的标识(大多数情况下,这将是
root
,但它可以是任何用户)。(除了把你的话视为理所当然,如果你是X1 M1 N1 X,使用X1 M2 N1 X的特权更改为任何用户)。因此,真实的用户ID是您的真实身份(拥有进程的人),而有效的用户ID是操作系统用来决定是否允许您执行某些操作的依据(大多数情况下,也有一些例外)。
当您登录时,登录shell会将真实的和有效的用户id设置为密码文件提供的相同值(您的真实的用户id)。
现在,你执行一个setuid程序,除了作为另一个用户运行(例如
root
),setuid程序还应该代表你做一些事情。这是如何工作的?执行setuid程序后,它将拥有您的真实的id(因为您是进程所有者)和文件所有者的有效用户id(例如
root
),因为它是setuid。这个程序会使用超级用户权限来完成它需要完成的任何事情,然后代表你做一些事情。这意味着,尝试做一些你不应该做的事情 * 应该失败 。它是如何做到的?很明显,通过将其有效的用户ID更改为真实的用户ID!
现在setuid程序没有办法切换回来,因为内核只知道你的id和. * 你的id。砰,你死了。
这就是保存的set-user id的用途。
wlwcrazw2#
我将尝试用一些例子来逐步解释。
短背景
每个进程都有自己的“进程凭证”,其中包括
PID
、PPID
、PGID
、session ID
等属性,以及真实的和有效的用户和组ID:RUID
、EUID
、RGID
、EGID
。我们会关注这些。
第1部分:了解UID和GID
现在我将使用我的凭据登录到一个shell并运行:
字符串
你可以看到我的登录名(rotem),UID和GID都是1000,以及其他细节,如我登录到的shell。
第2部分:了解RUID和RGID
让我们运行一个简单的命令来检查它:
型
检查进程UID和GID:
型
即进程的真实的 * 用户ID(
RUID
)和真实的组ID(RGID
)。(*)检查other options to view the UID and GID和ways to get this in a single line。
现在,接受
EUID
和EGID
属性是“冗余”的事实,并且在幕后相当于RUID
和RGID
。第3部分:了解EUID和EGID
让我们以
ping
命令为例。使用
which
命令搜索二进制位置,然后运行ls -la
:型
您可以看到文件的所有者和组是
root
。这是因为ping
命令需要打开一个特殊的套接字,而Linux内核需要root
权限。但是,如果我没有
root
权限,如何使用ping
?请注意,在文件权限的所有者部分中,'s '字母代替了'x'。
这是特定二进制可执行文件(如
ping
和sudo
)的特殊权限位,称为setuid。这就是
EUID
和EGID
发挥作用的地方。当执行一个setuid二进制文件(如
ping
)时,进程将其有效用户ID(EUID
)从默认的RUID
更改为这个特殊的二进制可执行文件的所有者,在本例中为-root
。这一切都是由这个文件具有
setuid
位的简单事实完成的。内核通过查看进程的
EUID
来决定该进程是否具有特权。因为现在EUID
指向root
,所以该操作不会被内核拒绝。注意事项:在最新的Linux版本中,
ping
命令的输出看起来会有所不同,因为它们采用了Linux Capabilities方法而不是这种setuid方法-对于那些不熟悉的人-请阅读here。第4部分:SUID和SGID如何?
当特权进程正在运行(例如
root
)并且它需要执行一些非特权任务时,将使用保存的用户ID(SUID
)。在这种情况下,之前的有效UID(
EUID
)将保存在SUID
中,然后更改为非特权任务。当非特权任务完成时,EUID
将从SUID
的值中取出,并切换回特权帐户。7y4bm7vi3#
真实的用户ID是生成进程的用户。
有效用户id是由正在执行的二进制文件上的setuid位确定的用户。
以下是一些关于uid和euid的事实,以及每种的手动源代码:
当你以root身份生成时,你可以使用euid,你需要暂时放弃特权,并且仍然能够在之后重新获得root特权,如man setuid(2)所示:
字符串
如果你的有效用户名是root,那么所有的操作都将像你是root一样进行,除了我认为唯一的例外是文件访问检查将检查你的真实的用户名而不是有效的用户名,这是一个混淆的来源,就像man access(2):
型
当调用bash时,它不会传播euid,除非你像man bash(1)那样传递
-p
:型
当使用sudo时,有效的和真实的用户ID都被设置为man sudo(8):
型
gg58donl4#
我是这样理解的。用户执行的文件(相当于启动一个进程)将有一个RUID等于该用户的id。这里需要注意的是,创建文件的uid与执行文件的uid是不同的。它们可以相同或不同。因此,RUID可能会根据执行文件的UID而有所不同。当文件上有setuid位时,每当uid执行该文件时,该uid将临时替换为文件所有者的uid。因此,如果我们有一个由uid 456拥有的文件,并且其上具有setuid位,则每当uid 123执行该文件时,该文件将以uid 456执行。在此场景中,uid 123是RUID,uid 456是EUID。
xn1cxnb45#
@Rotem jackoby的回答很好。作为休闲,你可以看到我对这篇文章的回答。它包含一个示例C程序,你可以运行它,亲眼看看Linux中 * 进程 * 的真实的用户ID(RUID),有效的用户ID(EUID)和保存的用户ID(SUID)之间的区别。
在这里我只想指出,所有类Unix系统的官方文档,当然包括Linux,* The Open Group Base Specifications Issue 7,2018 edition*(参见“3.定义”here),指出了RUID的概念,EUID和SUID适用于“当用户的身份与 * 进程 * 相关联时”(参见3.436 User ID here)。换句话说,如果用户没有启动或生成任何进程,那么谈论RUID、EUID或SUID就没有意义,但仅关于用户ID(UID),仅此而已。