嗨!就在上周,我以为我对用户和组如何在Linux上工作了如指掌。我认为他们的关系是这样的:每个进程都属于一个用户(比如用户julia)当这个进程试图读取某个组拥有的文件时,Linux会一个。首先检查用户julia是否有访问文档的权限。(LCTT译注:这里应该是指检查文件的拥有者是否为julia)b.检查julia属于哪些组,进一步检查这些组中的某个组是否拥有该文件或者是否有访问该文件的权限。如果上面的a或b为真(或“else”位设置为允许访问),则该进程可以访问该文件。例如,如果一个进程由用户julia拥有并且julia在awesome组中,那么该进程可以访问以下文件。r--r--r--1rootawesome6872Sep2411:09file.txt但是,我没有很清楚地考虑上述机制。如果你硬要解释清楚,我会说这个过程可能会检查/etc/group文件中是否有一些拥有当前用户的组。然而,这不是“组”在Linux中的工作方式。上周在工作中发现了一个有趣的事情,原来我之前的理解是错误的,我对团队如何工作的描述并不准确。特别是,Linux不会在每次进程尝试访问文件时检查进程的用户属于哪个组。在读完《Linux 编程接口》一书(真是一本了不起的书)的第9章(“过程资格”)后,我恍然大悟,这才是群体真正运作的方式!意识到我之前并没有真正理解用户和组是如何工作的,我自信地尝试了以下并验证了正在发生的事情,事实证明我的理解现在是正确的。用户和组权限检查是怎么做的现在这些关键知识在我看来已经很简单了!这本书的第9章告诉我以下事实:用户和组ID是进程的属性,它们是:真正的用户ID和组ID;有效的用户ID和组ID;已保存组用户ID和已保存组组ID;文件系统用户ID和组ID(特定于Linux);补充组ID;thisstatesLinux实际上为检查一个进程是否可以访问一个文件所做的组检查如下:/etc/group)查看要访问的文件的访问属性中的组设置,判断进程是否有访问该文件的权限(LCTT译注:即文件的组是否为上述组之一)通常在使用访问控制时,使用有效的用户/组ID,而不是真实的用户/组ID。从技术上讲,文件系统ID在访问文件时使用,通常与有效用户/组ID相同。(LCTT译注:这句话是针对Linux的。)将用户添加到组中并不会将现有进程(用户)添加到该组中这里有一个有趣的例子:如果我创建一个新组:pandagroup并添加我自己(bork)到这个组,然后运行组检查我是否在这个组中:结果是我(bork)不在这个组中?!bork@kiwi~>sudoaddgrouppandaAddinggroup‘panda’(GID1001)...Done.bork@kiwi~>sudoadduserborkpandaAddinguser‘bork’togroup‘panda’...添加用户borktogrouppandaDone.bork@kiwi~>groupsborkadmcdromsudodipplugdevlpadminsambasharedockerlxdpanda不在上面的组中!为了仔细检查我们的发现,让我们创建一个文件,归熊猫组所有,看看我是否可以访问它。$touchpanda-file.txt$sudochownroot:pandapanda-file.txt$sudochmod660panda-file.txt$catpanda-file.txtcat:panda-file.txt:Permissiondenied好的,当然,我(bork)无法访问panda-file.txt。毫不奇怪,我的shell没有将panda组作为补充组ID,运行adduserborkpanda也不会改变这一点。该过程首先是如何获得用户组的?这是一个非常令人困惑的问题,对吧?如果进程会把组信息预置到进程的属性中,那么进程在初始化的时候如何获取组呢?显然你不能给自己分配更多的组(否则就违背了Linux访问控制的初衷。。。)有一点还是很清楚的:一个新的进程是如何从我的命令行解释器(/bash/fish)开始的)得到它的组。(新)进程将在进程属性中包含我的用户ID(bork)和更多的组ID。从我的shell执行的所有进程都是从这个shell中fork()的,所以新进程得到与shell相同的组。因此,必须有一个“第一个”进程来将您的组设置到进程属性中,并且从此进程产生的所有进程都将设置这些组。“第一个”进程是您的登录程序,即登录shell,它在我的笔记本电脑上由登录程序(/bin/login)实例化。login程序是以root身份运行的,然后调用一个C库函数——initgroups来设置你进程所在的组(具体是通过读取/etc/group文件),因为login程序是以root身份运行的,所以可以设置group你的过程。让我们重新登录!假设我们在一个登录程序中,我想刷新我进程的组设置,根据我们了解的进程如何初始化组ID,我应该能够通过再次运行登录程序来刷新我的进程组和启动一个新的登录命令!让我们尝试以下操作:$sudologinbork$groupsborkadmcdromsudodipplugdevlpadminsambasharedockerlxdpanda$catpanda-file.txt#它有效!我现在可以访问`panda`拥有的文件了!当然成功了!现在登录程序生成的程序的用户是panda组的一部分!奇妙!如果我真的希望“所有”进程都可以访问panda组,这不会影响我其他已经运行的登录程序(及其子程序)。我必须完全重新启动我的登录会话,这意味着我必须退出我的窗口管理器并重新登录。(LCTT译注:更新进程树的根进程,这里是窗口管理器进程。)newgrp命令有人告诉我在推特上说,如果你只是想启动一个刷新组信息的命令解释器,你可以使用newgrp(LCTT译注:不启动一个新的命令解释器),如下:sudoaddgrouppandasudoadduserborkpandanewgrppanda#startsanewcommandinterpretershell,你不必是root就可以运行它!也可以用sgpandabash来完成同样的事情。因此,这个命令可以启动一个bash登录程序,这个程序有一个panda组。seduid将设置有效的用户ID我实际上对进程以setuidroot权限运行意味着什么有点似是而非。现在我知道了,实际发生的是:setuid设置“有效用户ID”!如果我(julia)运行一个setuidroot进程(比如passwd),那么该进程的真实用户ID将是julia,而有效用户ID将设置为root。passwd需要root权限运行,但是可以看到进程的真实用户ID是julia,它启动了进程,passwd会阻止进程更改julia以外用户的密码。就这样!在这本书中,有很多在Linux上使用一些功能的难得方法,并且详细解释了一切在Linux上是如何工作的,这里就不一一展开了。那本书太棒了,我上面说的都是那本书的第9章,在1300页的书中只占了17页。关于这本书,我最喜欢的一点是我只需要阅读17页关于用户和组如何工作的内容,而这17页是完整的、信息丰富的和有用的。我不必阅读所有1300页就可以获得有用的东西,这太棒了!
