“使用者組”在 Linux 上到底是怎麼工作的?
| 2018-09-29 13:23 收藏: 1
嗨!就在上週,我還自認為對 Linux 上的使用者和組的工作機制瞭如指掌。我認為它們的關係是這樣的:
- 每個程式都屬於一個使用者(比如使用者
julia
) - 當這個程式試圖讀取一個被某個組所擁有的檔案時, Linux 會 a. 先檢查使用者
julia
是否有許可權訪問檔案。(LCTT 譯註:此處應該是指檢查檔案的所有者是否就是julia
) b. 檢查julia
屬於哪些組,並進一步檢查在這些組裡是否有某個組擁有這個檔案或者有許可權訪問這個檔案。 - 如果上述 a、b 任一為真(或者“其它”位設為有許可權訪問),那麼這個程式就有許可權訪問這個檔案。
比如說,如果一個程式被使用者 julia
擁有並且 julia
在awesome
組,那麼這個程式就能訪問下面這個檔案。
r--r--r-- 1 root awesome 6872 Sep 24 11:09 file.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
)竟然不在這個組?!
bork@kiwi~> sudo addgroup panda
Adding group `panda' (GID 1001) ...
Done.
bork@kiwi~> sudo adduser bork panda
Adding user `bork' to group `panda' ...
Adding user bork to group panda
Done.
bork@kiwi~> groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd
panda
並不在上面的組裡!為了再次確定我們的發現,讓我們建一個檔案,這個檔案被 panda
組擁有,看看我能否訪問它。
$ touch panda-file.txt
$ sudo chown root:panda panda-file.txt
$ sudo chmod 660 panda-file.txt
$ cat panda-file.txt
cat: panda-file.txt: Permission denied
好吧,確定了,我(bork
)無法訪問 panda-file.txt
。這一點都不讓人吃驚,我的命令直譯器並沒有將 panda
組作為補充組 ID,執行 adduser bork panda
並不會改變這一點。
那程式一開始是怎麼得到使用者的組的呢?
這真是個非常令人困惑的問題,對嗎?如果程式會將組的資訊預置到程式的屬性裡面,程式在初始化的時候怎麼取到組的呢?很明顯你無法給你自己指定更多的組(否則就會和 Linux 訪問控制的初衷相違背了……)
有一點還是很清楚的:一個新的程式是怎麼從我的命令列直譯器(/bash/fish
)裡被執行而得到它的組的。(新的)程式將擁有我的使用者 ID(bork
),並且程式屬性裡還有很多組 ID。從我的命令直譯器裡執行的所有程式是從這個命令直譯器裡 fork()
而來的,所以這個新程式得到了和命令直譯器同樣的組。
因此一定存在一個“第一個”程式來把你的組設定到程式屬性裡,而所有由此程式而衍生的程式將都設定這些組。而那個“第一個”程式就是你的登入程式,在我的膝上型電腦上,它是由 login
程式(/bin/login
)例項化而來。登入程式以 root 身份執行,然後呼叫了一個 C 的庫函式 —— initgroups
來設定你的程式的組(具體來說是透過讀取 /etc/group
檔案),因為登入程式是以 root 執行的,所以它能設定你的程式的組。
讓我們再登入一次
好了!假如說我們正處於一個登入程式中,而我又想重新整理我的程式的組設定,從我們前面所學到的程式是怎麼初始化組 ID 的,我應該可以透過再次執行登入程式來重新整理我的程式組並啟動一個新的登入命令!
讓我們試試下邊的方法:
$ sudo login bork
$ groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd panda
$ cat panda-file.txt # it works! I can access the file owned by `panda` now!
當然,成功了!現在由登入程式衍生的程式的使用者是組 panda
的一部分了!太棒了!這並不會影響我其他的已經在執行的登入程式(及其子程式),如果我真的希望“所有的”程式都能對 panda
組有訪問許可權。我必須完全的重啟我的登入會話,這意味著我必須退出我的視窗管理器然後再重新登入。(LCTT 譯註:即更新程式樹的樹根程式,這裡是視窗管理器程式。)
newgrp 命令
在 Twitter 上有人告訴我如果只是想啟動一個重新整理了組資訊的命令直譯器的話,你可以使用 newgrp
(LCTT 譯註:不啟動新的命令直譯器),如下:
sudo addgroup panda
sudo adduser bork panda
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 頁書就能得到有用的東西,太棒了!
via: https://jvns.ca/blog/2017/11/20/groups/
作者:Julia Evans 譯者:DavidChen 校對:wxy
相關文章
- linux上使用者、使用者組及私有使用者組(轉)Linux
- 從規範去看Function.prototype.call到底是怎麼工作的?Function
- linux中什麼是使用者組?使用者與組的關係是什麼?Linux
- 在linux上怎麼檢視tomcat日誌LinuxTomcat
- 卷向位元組碼-Java異常到底是怎麼被處理的?Java
- hypernetwork在SD中是怎麼工作的
- Linux記憶體是怎麼工作的?Linux記憶體
- linux上的組管理Linux
- 社交軟體上“你可能認識的人”到底是怎麼找到你的?
- win10怎麼建立區域網工作組 win10組建區域網工作組的基本步驟Win10
- for迴圈在Python中是怎麼工作的Python
- w10系統怎麼加入工作組_win10系統如何更改工作組Win10
- 在硬碟上安裝windows,linux,solaris的組合(轉)硬碟WindowsLinux
- 雲端計算到底是怎麼玩的?
- Linux Apache 怎麼修改工作模式LinuxApache模式
- 怎麼做表格在電腦上怎麼操作 在電腦上做表格的操作方法介紹
- xgpu怎麼在pc上用 xgpu怎麼在電腦上免費玩遊戲GPU遊戲
- Linux運維到底是做什麼的?LinuxLinux運維
- 在 Linux 中把使用者新增到組的四個方法Linux
- 在Linux中,什麼是管道?它是如何工作的?Linux
- 在Linux中,什麼是SSH?它是如何工作的?Linux
- 在Linux中,Keepalived的工作原理是什麼?Linux
- 《Linux是怎麼樣工作的》讀書筆記Linux筆記
- 網站流量到底是怎麼來的?網站
- 現在找個軟體工程師的工作怎麼這麼難!軟體工程工程師
- 頓號在鍵盤上怎麼打 頓號符號在鍵盤上怎麼打不出來符號
- Win10系統怎麼查詢當前使用者組及組中使用者Win10
- 在Linux中,如何新增一個使用者到特定的組?Linux
- 怎樣在 Ubuntu Linux 上安裝 MySQLUbuntuLinuxMySql
- Linux的使用者和使用者組管理Linux
- 我在阿里是怎麼工作的——寫在阿里入職一週年阿里
- 如何在 Linux 上為特定的使用者或使用者組啟用或禁用 SSH?Linux
- Linux上oracle怎麼啟動OEMLinuxOracle
- 跨行零實戰怎麼寫簡歷上的工作經驗
- Go Error 巢狀到底是怎麼實現的?GoError巢狀
- 關於大資料到底是怎麼來的大資料
- win10怎麼加入工作組計算機_win10加入工作組計算機操作步驟Win10計算機
- Linux系統上的常用基礎命令,深入使用者與使用者組的相關命令!Linux