在學(xué)習(xí) Linux 系統(tǒng)權(quán)限相關(guān)的主題時,我們首先關(guān)注的基本都是文件的 ugo 權(quán)限。ugo 權(quán)限信息是文件的屬性,它指明了用戶與文件之間的關(guān)系。但是真正操作文件的卻是進(jìn)程,也就是說用戶所擁有的文件訪問權(quán)限是通過進(jìn)程來體現(xiàn)的。本文主要介紹進(jìn)程的權(quán)限,并通過示例解釋用戶身份與進(jìn)程權(quán)限之間的關(guān)系。說明:本文的演示環(huán)境為 ubuntu 16.04。
基本概念
用戶
對于支持多任務(wù)的 Linux 系統(tǒng)來說,用戶就是獲取資源的憑證。
權(quán)限
權(quán)限用來控制用戶對計算機(jī)資源(CPU、內(nèi)存、文件等)的訪問,一般會分為認(rèn)證和授權(quán)兩步。比如用戶先經(jīng)過認(rèn)證機(jī)制(authentication)登錄系統(tǒng),然后由授權(quán)系統(tǒng)(authorization)對用戶的操作進(jìn)行授權(quán)。
進(jìn)程
進(jìn)程是任何支持多道程序設(shè)計的操作系統(tǒng)中的基本概念。通常把進(jìn)程定義為程序執(zhí)行時的一個實例。因此,如果有 10 個用戶同時運行 vi,就會有 10 個獨立的進(jìn)程(盡管它們共享同一份可執(zhí)行代碼)。
實際上,是進(jìn)程在幫助我們完成各種任務(wù)。進(jìn)程就是用戶訪問計算機(jī)資源的代理,用戶執(zhí)行的操作其實是帶有用戶身份信息的進(jìn)程執(zhí)行的操作。
進(jìn)程權(quán)限
既然是進(jìn)程在為用戶執(zhí)行具體的操作,那么當(dāng)用戶要訪問系統(tǒng)的資源時就必須給進(jìn)程賦予權(quán)限。也就是說進(jìn)程必須攜帶發(fā)起這個進(jìn)程的用戶的身份信息才能夠進(jìn)行合法的操作。
從登陸過程觀察進(jìn)程攜帶的用戶身份信息
在 Linux 系統(tǒng)啟動后,init 系統(tǒng)會 fork 出子進(jìn)程執(zhí)行 /sbin/getty 程序等待用戶登錄。當(dāng)用戶進(jìn)行登錄操作時,該子進(jìn)程通過 exec 函數(shù)開始執(zhí)行 /bin/login 程序(此時該進(jìn)程已經(jīng)變成了 login 進(jìn)程)。由 login 進(jìn)程驗證我們的用戶名和密碼并查詢 /etc/passwd 和 /etc/shadow 確定其合法性。如果是合法的用戶,該進(jìn)程再次通過 exec 函數(shù)執(zhí)行用戶的默認(rèn) shell 程序,此時的 login 進(jìn)程就變成了 shell 進(jìn)程(筆者機(jī)器上是 bash 進(jìn)程)。并且該 shell 進(jìn)程的有效身份被設(shè)置成為該用戶的身份,之后 fork 此 shell 進(jìn)程的子進(jìn)程都會繼承該有效身份。我們可以通過下圖來理解用戶從 tty 登錄系統(tǒng)的過程(此圖來自互聯(lián)網(wǎng)):

上圖描述了 init 進(jìn)程、getty 進(jìn)程、login 進(jìn)程和 shell 進(jìn)程的交互。
簡單點說就是:用戶登錄后, shell 進(jìn)程的有效用戶就是該用戶。下面我們來了解下進(jìn)程的用戶信息。
進(jìn)程的 real user id、effective user id 和 saved set user id
通過 cat /proc/

通過 man proc 可以查詢到第一行的四個數(shù)字分別是 real user id, effective user id, saved set user id 和 filesystem UID,第二行則是對應(yīng)的組 ID。這里我們只介紹第一行中的前三個 ID,即 real user id, effective user id 和 saved set user id。
real user id
real user id 是執(zhí)行進(jìn)程者的 user id,一般情況下就是用戶登錄時的 user id。子進(jìn)程的 real user id 從父進(jìn)繼承。通常這個是不更改的,也不需要更改。比如我以用戶 nick 登錄 Linux 系統(tǒng),我接下來運行的所有命令的進(jìn)程的 real user id 都是 nick 的 user id。
effective user id
如果要判斷一個進(jìn)程是否對某個文件有操作權(quán)限,驗證的是進(jìn)程的 effective user id,而不是 real user id。
通常我們是不建議直接使用 root 用戶進(jìn)行操作的,但是在很多情況下,程序可能需要特殊的權(quán)限。比如 passwd 程序需要 root 權(quán)限才能夠為普通用戶修改密碼,一些 services 程序的操作也經(jīng)常需要特殊的權(quán)限。為此,Linux 中設(shè)計了一些特殊的權(quán)限,請參考《Linux 特殊權(quán)限 SUID,SGID,SBIT》一文。這里我們以 passwd 程序為例,為二進(jìn)制可執(zhí)行文件 /usr/bin/passwd 設(shè)置 set-user-id bit=ON,這個可執(zhí)行文件被用 exec 啟動之后的進(jìn)程的 effective user id 就是這個可執(zhí)行文件的 owner id,而并非父進(jìn)程的 real user id。如果 set-user-id bit=OFF 的時候,這個被 exec 起來的進(jìn)程的 effective user id 應(yīng)該是等于進(jìn)程的 user id 的。所以,effective user id 存在的意義在于,它可能和 real user id 不同。
saved set user id
saved set user id 相當(dāng)于是一個 buffer,在 exec 函數(shù)啟動之后,它會拷貝 effective user id 位的信息覆蓋自己。對于非 root 用戶來說,可以在未來使用 setuid() 函數(shù)將 effective user id 設(shè)置成為 real user id 或 saved set user id 中的任何一個。但是不允許非 root 用戶用 setuid() 函數(shù)把 effective user id 設(shè)置成為任何第三個 user id。
對于 root 用戶來說,調(diào)用 setuid() 的時候,將會設(shè)置所有的這三個 user id。
從總體上來看,進(jìn)程中 real user id, effective user id 和 saved set user id 的設(shè)計是為了讓 unprivilege user 可以獲得兩種不同的權(quán)限。同時我們也可以得出下面的結(jié)論:
Linux 系統(tǒng)通過進(jìn)程的有效用戶 ID(effective user id) 和有效用戶組 ID(effective group id) 來決定進(jìn)程對系統(tǒng)資源的訪問權(quán)限。
其實我們通過 ps aux 查看的結(jié)果中,第一列顯示的就是進(jìn)程的 effective user:

Shell 中外部命令的執(zhí)行方式
在 shell 中執(zhí)行的命令分為內(nèi)部命令和外部命令兩種。
內(nèi)部命令:內(nèi)建的,相當(dāng)于 shell 的子函數(shù)
外部命令:在文件系統(tǒng)的某個路徑下的一個可執(zhí)行文件
外部命令的執(zhí)行過程如下:
Shell 通過 fork() 函數(shù)建立一個新的子進(jìn)程,新的子進(jìn)程為當(dāng)前 shell 進(jìn)程的一個副本。
在新的進(jìn)程里,從 PATH 變量所列出的目錄中尋找指定的命令程序。當(dāng)命令名稱包含有斜杠(/)符號時,將略過路徑查找步驟。
在新的進(jìn)程里,通過 exec 系列函數(shù),以所找到的新程序替換 shell 程序并執(zhí)行。
子進(jìn)程退出后,最初的 shell 會接著從終端讀取并執(zhí)行下一條命令。
我們通過下面的例子來理解在 shell 中執(zhí)行外部命令的過程,例子很簡單就是通過 cat 命令查看一個文本文件 test.log:
$ cat test.log
我們先來檢查一下當(dāng)前用戶以及相關(guān)文件的權(quán)限:

當(dāng)前用戶 nick 的 real user id 為 1000,/bin/cat 文件的所有者為 root,但是所有人都有執(zhí)行權(quán)限,test.log 文件的所有者為 nick。我們結(jié)合下圖來介紹 cat test.log 命令的執(zhí)行過程:

當(dāng)我們在 shell 中執(zhí)行一個外部程序的時候,默認(rèn)情況下進(jìn)程的 effective user ID 等于 real user ID,進(jìn)程的 effective group ID 等于 real group ID(接下來的介紹中省略 group ID)。當(dāng)我們以用戶 nick 登錄系統(tǒng),并在 bash 中鍵入 cat test.log 命令并回車后。Bash 先通過 fork() 建立一個新的子進(jìn)程,這個新的子進(jìn)程是當(dāng)前 bash 進(jìn)程的一個副本。新的進(jìn)程在 PATH 變量指定的路徑中搜索 cat 程序,找到 /bin/cat 程序后檢查其權(quán)限。/bin/cat 程序的所有者為 root,但是其他人具有讀和執(zhí)行的權(quán)限,所以新進(jìn)程可以通過 exec 函數(shù)用 cat 程序的代碼段替換當(dāng)前進(jìn)程中的代碼段(把 /bin/cat 程序加載到了內(nèi)存中,此時的進(jìn)程已經(jīng)變成了 cat 進(jìn)程,cat 進(jìn)程會從 _start 函數(shù)開始執(zhí)行)。由于 cat 進(jìn)程是由用戶 nick 啟動的,所以 cat 進(jìn)程的 effective user ID 是 1000(nick)。同時 cat 進(jìn)程的 effective user ID 和 test.log 文件的 owner ID 相同(都是 1000),所以 cat 進(jìn)程擁有對此文件的 rw- 權(quán)限,那么順理成章地就可以讀寫 test.log 文件的內(nèi)容了。
下面我們演示一個通過設(shè)置特殊權(quán)限 set uid ID 改變進(jìn)程 effective user ID 的例子。
創(chuàng)建文件 root.log,權(quán)限為 640,此時只有 root 有權(quán)限讀寫該文件的內(nèi)容,用戶 nick 連讀取該文件的權(quán)限都沒有:

然后通過設(shè)置特殊權(quán)限 set uid ID 讓運行 cat 程序的進(jìn)程具有 root 權(quán)限:
$ sudo chmod 4755 /bin/cat

現(xiàn)在可以了!因為運行 cat 程序的進(jìn)程的 effective user ID 變成了 root。記得要把 /bin/cat 的權(quán)限改回去呀:
$ sudo chmod 755 /bin/cat
Shell 腳本的執(zhí)行方式
在 shell 中執(zhí)行腳本的方式和執(zhí)行外部命令的方式差不多,比如我們要執(zhí)行下面的腳本:
$ /bin/bash ./test.sh
這時同樣會 fork 出一個子進(jìn)程。只不過腳本與程序相比沒有代碼段,也沒有 _start 函數(shù),此時 exec 函數(shù)就會執(zhí)行另外一套機(jī)制。比如我們在 test.sh 文件的第一行通過 #!/bin/bash 指定了一個解釋器,那么解釋器程序的代碼段會用來替換當(dāng)前進(jìn)程的代碼段,并且從解釋器的 _start 函數(shù)開始執(zhí)行,而這個文本文件被當(dāng)作命令行參數(shù)傳給解釋器。所以上面的命令執(zhí)行過程為:Bash 進(jìn)程 fork/exec 一個子 bash 進(jìn)程用于執(zhí)行腳本,子 bash 進(jìn)程繼承父進(jìn)程的環(huán)境變量、用戶信息等內(nèi)容,父進(jìn)程等待子 bash 進(jìn)程終止。
總結(jié)
文件上的權(quán)限信息和用戶的信息都是靜態(tài)的,而進(jìn)程是動態(tài)的,它把自身攜帶的用戶信息和將要進(jìn)行的操作結(jié)合起來,從而實現(xiàn)權(quán)限管理。至此我們也基本上搞明白了 Linux 權(quán)限系統(tǒng)的工作原理。
鏈接:https://www.cnblogs.com/sparkdev/p/9694103.html
-
Linux
+關(guān)注
關(guān)注
88文章
11622瀏覽量
217818 -
計算機(jī)
+關(guān)注
關(guān)注
19文章
7761瀏覽量
92651 -
內(nèi)存
+關(guān)注
關(guān)注
9文章
3170瀏覽量
76092 -
Ubuntu
+關(guān)注
關(guān)注
5文章
603瀏覽量
32835
原文標(biāo)題:深入解析:Linux 用戶身份與進(jìn)程權(quán)限管理
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Linux守護(hù)進(jìn)程
linux的權(quán)限和指令
Linux 中文件權(quán)限管理的探討
Linux守護(hù)進(jìn)程詳解
淺談Linux權(quán)限管理的ACL權(quán)限
Linux權(quán)限控制的基本原理
Linux進(jìn)程權(quán)限的分析說明
Linux基礎(chǔ)的用戶權(quán)限
linux文件訪問權(quán)限怎么設(shè)置
Linux把目錄權(quán)限給指定用戶
linux權(quán)限管理詳解
Linux權(quán)限管理基礎(chǔ)入門

Linux用戶身份與進(jìn)程權(quán)限詳解
評論