Linux 權限控制的基本原理

Linux愛好者2018-06-15 02:00:56

(點擊上方藍字,快速關注我們)


來文來自原作者(呂凱)的推薦



以下是對用戶和組信息的舉例。 /etc/shadow 中的口令信息為加密存儲,不舉例。


$cat /etc/passwd |head -n 5

root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/bin/sh

bin:x:2:2:bin:/bin:/bin/sh

sys:x:3:3:sys:/dev:/bin/sh

sync:x:4:65534:sync:/bin:/bin/sync

 

$cat /etc/group |head -n 5

root:x:0:

daemon:x:1:

bin:x:2:

sys:x:3:

adm:x:4:miracle



輸出中, 第1個字符表示文件類型,其中,普通文件(-)、目錄文件 (d)、套接字文件(s),管道文件(p),字符文件(c),塊文件(b),鏈接文件(l); 第2個字符開始的 -rwxr-xr-x 部分表示文件的權限位,共有9位。


對於文件 /usr/bin/qemu-i386 , 這個權限控制的含義是:


  1. 第2~4位的 rwx 表示該文件可被它的 owner (屬主)以 r 或 w 或 x 的權限訪問。

  2. 第5~7位的 r-x 表示該文件可被與該文件同一屬組的用戶以 r 或 x 的權限訪問

  3. 第8~10位的 r-x 表示該文件可被其它未知用戶以 r 或 x 的權限訪問。


對於 test/, test2/, test3/ 設定的權限:


  1. r,w,x 權限對每一權限控制組的權限用一位8進制來表示; 例如: 755 表示 rwxr-xr-x。

  2. s,t 權限會替代 x 位置顯示;設定 s,t 權限則需在對應的、用於控制 r,w,x 的8進制權限控制組前追加數字; s 權限用於屬主屬組控制, t 用於其它控制。

  3. 設定屬主 s 需追加 4, 設定屬組 s 追加 2, 設定其它者 t 權限追加 1 ; 例如前面對 test/ 設定 t, 則用 1775, 表示 rwxrwxr-t 。


進程權限控制信息


進程權限


對於進程,有如下屬性與文件訪問權限相關:


  • effective user id : 進程訪問文件權限相關的 UID (簡寫為 euid )。

  • effective group id : 進程訪問文件權限相關的 GID (簡寫為 egid )。

  • real user id : 創建該進程的用戶登錄系統時的 UID (簡寫為 ruid )。

  • real group id : 創建該進程的用戶登錄系統時的 GID (簡寫為 rgid )。

  • saved set user id : 拷貝自 euid 。

  • saved set group id : 拷貝自 egid 。


舉例


我們可以使用 ps 和 top 選擇查看具有 euid 和 ruid 的進程。或者通過 top 來查看進程的 euid 和 ruid


通過 top 來查看的例子:


  1. 首先輸入 top 得到類似如下


其中, PID 是對應進程, USER 是對應的 effective user, RUSER 是對應的 real user 。


進程訪問文件的權限控制策略


規則


進程訪問文件大致權限控制策略


對於進程訪問文件而言,最重要的是 euid, 所以其權限屬性均以 euid 為 “中心”。


  • 進程的 euid 一般默認即為 其 ruid 值

  • 若可執行文件的可執行權限位為 s ,進程對其調用 exec 後,其 euid 被設置為該可執行文件的 user id

  • 進程的 saved set user id 拷貝自 euid.

  • 當進程的 euid 與文件的 user id 匹配時,進程才具有文件 user 權限位所設定的權限

  • 組權限 egid 的控制規則類似。


通過 exec 執行文件修改權限屬性


通過 exec 調用可執行文件之時:


  • 進程 ruid 值始終不變;

  • saved set-user ID 始終來自 euid ;

  • euid 值取決於文件的 set-user-ID 位是否被設置。


如下:



舉例


再舉幾個比較特別的例子:


- 設置了 set-user-id


$ ls -l /usr/bin/sudo

-rwsr-xr-x 1 root root 71288  2 28  2013 /usr/bin/sudo


如前所述,這個輸出的含義是,對於 /usr/bin/sudo 文件,


  • 第1~3位的 rws 表示該文件可被它的owner(屬主)以 r 或 w 或 s 的權限訪問

  • 第4~6位的 r-x 表示該文件可被與該文件同一屬組的用戶以 r 或 x 的權限訪問。

  • 第7~9位的 r-x 表示該文件可被其它未知用戶以 r 或 x 的權限訪問。


這樣設置之後,對於owner,具有讀、寫、執行權限,這一點沒有什麼不同。但是對於不屬於 root 組的普通用戶進程來說,卻大不相同。


普通用戶進程執行 sudo 命令時通過其 others 中的 x 獲得執行權限,再通過 user 中的 s使得普通用戶進程臨時具有了 sudo 可執行文件屬主( root )的權限,即超級權限。


這也是為什麼通過 sudo 命令就可以讓普通用戶執行許多管理員權限的命令的原因。


- 設置了 stick-bit


$ ls -l / |grep tmp

drwxrwxrwt  25 root root 12288  7 20 09:09 tmp


這樣設置之後,對於 /tmp 目錄,任何人都具有讀、寫、執行權限,這一點沒有什麼不同。但是對於 others 部分設置了粘滯位 t, 其功能卻大不相同。


若目錄沒設置粘滯位,任何對目錄有寫權限者都則可刪除其中任何文件和子目錄,即使他不是相應文件的所有者,也沒有讀或寫許可; 設置粘滯位後,用戶就只能寫或刪除屬於他的文件和子目錄。


這也是為什麼任何人都能向 /tmp 目錄寫文件、目錄,卻只能寫和刪除自己擁有的文件或目錄的原因。


舉一個 man 程序的應用片斷,描述 set-user-id 和 saved set-user-id 的使用

man 程序可以用來顯示在線幫助手冊, man 程序可以被安裝指定 set-user-ID 或者 set-group-ID 為一個指定的用戶或者組。


man 程序可以讀取或者覆蓋某些位置的文件,這一般由一個配置文件(通常是 /etc/man.config 或者 /etc/manpath.config )或者命令行選項來進行配置。


man 程序可能會執行一些其它的命令來處理包含顯示的 man 手冊頁的文件。


為防止處理出錯, man 會從兩個特權之間進行切換:運行 man 命令的用戶特權,以及 man程序的擁有者的特權。


需要抓住的主線:當只執行 man 之時,進程特權就是 man 用戶的特權, 當通過 man 執行子進程(如通過 !bash 引出shell命令)時,用戶切換為當前用戶,執行完又切換回去。


過程如下:


  1. 假設 man 程序文件被用戶 man 所擁有,並且已經被設置了它的 set-user-ID 位,當我們 exec 它的時候,我們有如下情況:

    • real user ID = 我們的用戶UID

    • effective user ID = man用戶UID

    • saved set-user-ID = man用戶UID

  2. man 程序會訪問需要的配置文件和 man 手冊頁。這些文件由 man 用戶所擁有,但是由於 effective user ID 是 man,文件的訪問就被允許了。

  3. 在 man 為我們運行任何命令的時候,它會調用 setuid(getuid())) (getuid() 返回的是 real user id).因為我們不是 superuser 進程,這個變化只能改變 effective user ID. 我們會有如下情況:

    現在 man 進程運行的時候把我們得UID作為它的 effective user ID.這也就是說,我們只能訪問我們擁有自己權限的文件。也就是說,它能夠代表我們安全地執行任何 filter.

    • real user ID = 我們的用戶UID(不會被改變)

    • effective user ID = 我們的用戶UID

    • saved set-user-ID = man 的用戶UID(不會被改變)

  4. 當 filter 做完了的時候, man 會調用 setuid(euid).這裡, euid 是 man 用戶的UID.(這個ID是通過 man 調用 geteuid 來保存的)這個調用是可以的,因為 setuid 的參數和 saved set-user-ID 是相等的。(這也就是為什麼我們需要 saved set-user-ID).這時候我們會有如下情況:

    • real user ID = 我們的用戶UID(不會被改變)

    • effective user ID = man的UID

    • saved set-user-ID = man 的用戶UID(不會被改變)

  5. 由於 effective user ID 是 man,現在 man 程序可以操作它自己的文件了。通過這樣使用 saved set-user-ID,我們可以在進程開始和結束的時候通過程序文件的 set-user-ID 來使用額外的權限。然而,期間我們卻是以我們自己的權限運行的。如果我們無法在最後切換回 saved set-user-ID,我們就可能會在我們運行的時候保留額外的權限。


下面我們來看看如果 man 啟動一個 shell 的時候會發生什麼:


  • 這裡的 shell 是 man 使用 fork 和 exec 來啟動的。

  • 因為這時 real user ID 和 effective user ID 都是我們的普通用戶UID(參見step3), 所以 shell 沒有其它額外的權限.

  • 啟動的 shell 無法訪問 man 的 saved set-user-ID(man) ,因為 shell 的 saved set-user-ID 是由 exec 從 effective user ID 拷貝過來的。

  • 在執行 exec 的子進程( shell )中,所有的 user ID 都是我們的普通用戶ID.


實際上,我們描述 man 使用 setuid 函數的方法不是特別正確,因為程序可能會 set-user-ID 為 root .這時候, setuid 會把所有三種uid都變成你設置的id,但是我們只需要設置 effective user ID。



【關於作者】


呂凱:深圳,工作經驗 9 年,冠捷科技公司資深主任工程師。關注軟件開發、系統運維、內容管理、行動管理等領域,喜歡計數寫作及分享。


【關於投稿】


如果大家有原創好文投稿,請直接給公號發送留言。


① 留言格式:
【投稿】+《 文章標題》+ 文章鏈接

② 示例:
【投稿】《不要自稱是程序員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/

③ 最後請附上您的個人簡介哈~



看完本文有收穫?請分享給更多人

關注「Linux 愛好者」,提升Linux技能

閱讀原文

TAGS:文件man 程序 可以權限進程