首頁 > 軟體

「使用者組」在 Linux 上到底是怎麼工作的?

2020-06-16 16:44:25

嗨!就在上週,我還自認為對 Linux 上的使用者和組的工作機制瞭如指掌。我認為它們的關係是這樣的:

  1. 每個進程都屬於一個使用者(比如使用者 julia
  2. 當這個進程試圖讀取一個被某個組所擁有的檔案時, Linux 會 a. 先檢查使用者julia 是否有許可權存取檔案。(LCTT 譯註:此處應該是指檢查檔案的所有者是否就是 julia) b. 檢查 julia 屬於哪些組,並進一步檢查在這些組裡是否有某個組擁有這個檔案或者有許可權存取這個檔案。
  3. 如果上述 a、b 任一為真(或者“其它”位設為有許可權存取),那麼這個進程就有許可權存取這個檔案。

比如說,如果一個進程被使用者 julia 擁有並且 juliaawesome 組,那麼這個進程就能存取下面這個檔案。

  1. r--r--r--1 root awesome 6872Sep2411:09file.txt

然而上述的機制我並沒有考慮得非常清楚,如果你硬要我闡述清楚,我會說進程可能會在執行時去檢查 /etc/group 檔案裡是否有某些組擁有當前的使用者。

然而這並不是 Linux 裡“組”的工作機制

我在上個星期的工作中發現了一件有趣的事,事實證明我前面的理解錯了,我對組的工作機制的描述並不準確。特別是 Linux 並不會在進程每次試圖存取一個檔案時就去檢查這個進程的使用者屬於哪些組。

我在讀了《Linux 程式設計介面》這本書的第九章(“進程資格”)後才恍然大悟(這本書真是太棒了),這才是組真正的工作方式!我意識到之前我並沒有真正理解使用者和組是怎麼工作的,我信心滿滿的嘗試了下面的內容並且驗證到底發生了什麼,事實證明現在我的理解才是對的。

 

使用者和組許可權檢查是怎麼完成的

現在這些關鍵的知識在我看來非常簡單! 這本書的第九章上來就告訴我如下事實:使用者和組 ID 是進程的屬性,它們是:

  • 真實使用者 ID 和組 ID;
  • 有效使用者 ID 和組 ID;
  • 儲存的 set-user-ID 和儲存的 set-group-ID;
  • 檔案系統使用者 ID 和組 ID(特定於 Linux);
  • 補充的組 ID;

這說明 Linux 實際上檢查一個進程能否存取一個檔案所做的組檢查是這樣的:

  • 檢查一個進程的組 ID 和補充組 ID(這些 ID 就在進程的屬性裡,並不是實時在 /etc/group 裡查詢這些 ID)
  • 檢查要存取的檔案的存取屬性裡的組設定
  • 確定進程對檔案是否有許可權存取(LCTT 譯註:即檔案的組是否是以上的組之一)

通常當存取控制的時候使用的是有效使用者/組 ID,而不是真實使用者/組 ID。技術上來說當存取一個檔案時使用的是檔案系統的 ID,它們通常和有效使用者/組 ID 一樣。(LCTT 譯註:這句話針對 Linux 而言。)

 

將一個使用者加入一個組並不會將一個已存在的進程(的使用者)加入那個組

下面是一個有趣的例子:如果我建立了一個新的組:panda 組並且將我自己(bork)加入到這個組,然後執行 groups 來檢查我是否在這個組裡:結果是我(bork)竟然不在這個組?!

  1. bork@kiwi~>sudo addgroup panda
  2. Adding group `panda' (GID 1001) ...
  3. Done.
  4. bork@kiwi~> sudo adduser bork panda
  5. Adding user `bork' to group `panda'...
  6. Adding user bork to group panda
  7. Done.
  8. bork@kiwi~>groups
  9. bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd

panda 並不在上面的組裡!為了再次確定我們的發現,讓我們建一個檔案,這個檔案被 panda 組擁有,看看我能否存取它。

  1. $ touch panda-file.txt
  2. $ sudochown root:panda panda-file.txt
  3. $ sudochmod660 panda-file.txt
  4. $ cat panda-file.txt
  5. cat: panda-file.txt:Permission denied

好吧,確定了,我(bork)無法存取 panda-file.txt。這一點都不讓人吃驚,我的命令直譯器並沒有將 panda 組作為補充組 ID,執行 adduser bork panda 並不會改變這一點。

 

那進程一開始是怎麼得到使用者的組的呢?

這真是個非常令人困惑的問題,對嗎?如果進程會將組的資訊預置到進程的屬性裡面,進程在初始化的時候怎麼取到組的呢?很明顯你無法給你自己指定更多的組(否則就會和 Linux 存取控制的初衷相違背了……)

有一點還是很清楚的:一個新的進程是怎麼從我的命令列直譯器(/bash/fish)裡被執行而得到它的組的。(新的)進程將擁有我的使用者 ID(bork),並且進程屬性裡還有很多組 ID。從我的命令直譯器裡執行的所有進程是從這個命令直譯器裡 fork() 而來的,所以這個新進程得到了和命令直譯器同樣的組。

因此一定存在一個“第一個”進程來把你的組設定到進程屬性裡,而所有由此進程而衍生的進程將都設定這些組。而那個“第一個”進程就是你的登入程式login shell,在我的筆記型電腦上,它是由 login 程式(/bin/login)範例化而來。登入程式以 root 身份執行,然後呼叫了一個 C 的庫函數 —— initgroups 來設定你的進程的組(具體來說是通過讀取 /etc/group 檔案),因為登入程式是以 root 執行的,所以它能設定你的進程的組。

 

讓我們再登入一次

好了!假如說我們正處於一個登入程式中,而我又想重新整理我的進程的組設定,從我們前面所學到的進程是怎麼初始化組 ID 的,我應該可以通過再次執行登入程式來重新整理我的行程群組並啟動一個新的登入命令!

讓我們試試下邊的方法:

  1. $ sudologin bork
  2. $ groups
  3. bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd panda
  4. $ cat panda-file.txt # it works! I can access the file owned by `panda` now!

當然,成功了!現在由登入程式衍生的程式的使用者是組 panda 的一部分了!太棒了!這並不會影響我其他的已經在執行的登入程式(及其子進程),如果我真的希望“所有的”進程都能對 panda 組有存取許可權。我必須完全的重新啟動我的登入對談,這意味著我必須退出我的視窗管理器然後再重新登入。(LCTT 譯註:即更新進程樹的樹根進程,這裡是視窗管理器進程。)

 

newgrp 命令

在 Twitter 上有人告訴我如果只是想啟動一個重新整理了組資訊的命令直譯器的話,你可以使用 newgrp(LCTT 譯註:不啟動新的命令直譯器),如下:

  1. sudo addgroup panda
  2. sudo adduser bork panda
  3. newgrp panda # starts a new shell,and you don't have to be root to run it!

你也可以用 sg panda bash 來完成同樣的效果,這個命令能啟動一個bash 登入程式,而這個程式就有 panda 組。

 

seduid 將設定有效使用者 ID

其實我一直對一個進程如何以 setuid root 的許可權來執行意味著什麼有點似是而非。現在我知道了,事實上所發生的是:setuid 設定了
“有效使用者 ID”! 如果我(julia)執行了一個 setuid root 的進程( 比如 passwd),那麼進程的真實使用者 ID 將為 julia,而有效使用者 ID 將被設定為 root

passwd 需要以 root 許可權來執行,但是它能看到進程的真實使用者 ID 是 julia ,是 julia 啟動了這個進程,passwd 會阻止這個進程修改除了 julia 之外的使用者密碼。

 

就是這些了!

在《Linux 程式設計介面》這本書裡有很多 Linux 上一些功能的罕見使用方法以及 Linux 上所有的事物到底是怎麼執行的詳細解釋,這裡我就不一一展開了。那本書棒極了,我上面所說的都在該書的第九章,這章在 1300 頁的書裡只佔了 17 頁。

我最愛這本書的一點是我只用讀 17 頁關於使用者和組是怎麼工作的內容,而這區區 17 頁就能做到內容完備、詳實有用。我不用讀完所有的 1300 頁書就能得到有用的東西,太棒了!

相關資料可從以下資訊得到下載:

點選這個http://www.linuxidc.com/Linux/2013-12/93755.htm 連結關注 Linux公社官方微信,關注後回復數位154515。即可得到網友的分享密碼。

如果取消關注Linux公社公眾號,即使再次關注,也將無法提供本服務!

連結: https://pan.baidu.com/s/1A8a_s8UvOXPcjUEtMsYHRg 密碼:獲得見上面的方法,地址失效請在下面留言。

------------------------------------------分割線------------------------------------------

全部下載見

FTP地址:ftp://ftp1.linuxidc.com

使用者名稱:ftp1.linuxidc.com

密碼:www.linuxidc.com

在 2018年LinuxIDC.com/9月/“使用者組”在 Linux 上到底是怎麼工作的?/

下載方法見 http://www.linuxidc.com/Linux/2013-10/91140.htm


IT145.com E-mail:sddin#qq.com