麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 服務器 > Linux服務器 > 正文

詳解Linux Namespace之User

2024-09-05 23:05:00
字體:
來源:轉載
供稿:網友

User namespace 是 Linux 3.8 新增的一種 namespace,用于隔離安全相關的資源,包括 user IDs and group IDs,keys, 和 capabilities。同樣一個用戶的 user ID 和 group ID 在不同的 user namespace 中可以不一樣(與 PID nanespace 類似)。換句話說,一個用戶可以在一個 user namespace 中是普通用戶,但在另一個 user namespace 中是超級用戶。

User namespace 可以嵌套(目前內核控制最多32層),除了系統默認的 user namespace 外,所有的 user namespace 都有一個父 user namespace,每個 user namespace 都可以有零到多個子 user namespace。 當在一個進程中調用 unshare 或者 clone 創建新的 user namespace 時,當前進程原來所在的 user namespace 為父 user namespace,新的 user namespace 為子 user namespace。

說明:本文的演示環境為 ubuntu 16.04。

創建 user namespace

我們可以通過 unshare 命令的 --user 選項來創建新的 user namespace:

$ unshare -user -r /bin/bash

Linux,Namespace,User

通過 -r 參數,我們把新的 user namespace 中的 root 用戶映射到了外面的 nick 用戶(接下來會介紹映射相關的概念)。在新的 user namespace 中,root 用戶是有權限創建其它的 namespace 的,比如 uts namespace。這是因為當前的 bash 進程擁有全部的 capabilities:

Linux,Namespace,User

下面我們創建一個新的 uts namespace 試試:

$ unshare --uts /bin/bash

Linux,Namespace,User

我們看到,新的 uts namespace 被順利的創建了。這是因為除了 user namespace 外,創建其它類型的 namespace 都需要 CAP_SYS_ADMIN 的 capability。當新的 user namespace 創建并映射好 uid、gid 了之后, 這個 user namespace 的第一個進程將擁有完整的所有 capabilities,意味著它就可以創建新的其它類型 namespace。

其實沒有必要把上面的操作(創建兩個 namespace)分成兩步,我們可以通 unshare 一次創建多個 namespace:

Linux,Namespace,User

在 unshare 的實現中,其實就是傳入了 CLONE_NEWUSER | CLONE_NEWUTS,大致如下:

unshare(CLONE_NEWUSER | CLONE_NEWUTS);

在上面這種情況下,內核會保證 CLONE_NEWUSER 先被執行,然后執行剩下的其他 CLONE_NEW*,這樣就使得不用 root 用戶而創建新的容器成為可能,這條規則對于clone 函數也同樣適用。

理解 UID 和 GID 的映射

在前面的演示中我們提到了用戶在 user namespace 之間的映射,下面我們同樣通過演示來理解映射是什么。我們先查看下當前用戶的 ID 和 user namespace 情況:

Linux,Namespace,User

然后執行 unshare --user /bin/bash 命令創建一個新的 user namespace,注意這次沒 -r 參數:

$ unshare --user /bin/bash

Linux,Namespace,User

在新的 user namespace 中,當前用戶變成了 nobody,并且 ID 也變成了 65534。

這是因為我們還沒有映射父 user namespace 的 user ID 和 group ID 到子 user namespace 中來,這一步是必須的,因為這樣系統才能控制一個 user namespace 里的用戶在其他 user namespace 中的權限(比如給其它 user namespace 中的進程發送信號,或者訪問屬于其它 user namespace 掛載的文件)。

如果沒有映射,當在新的 user namespace 中用 getuid() 和 getgid() 獲取 user ID 和 group ID 時,系統將返回文件 /proc/sys/kernel/overflowuid 中定義的 user ID 以及 proc/sys/kernel/overflowgid 中定義的 group ID,它們的默認值都是 65534。也就是說如果沒有指定映射關系的話,會默認會把 ID 映射到 65534。

下面我們來完成 nick 用戶在新的 user namespace 中的映射。

映射 ID 的方法就是添加映射信息到 /proc/PID/uid_map 和 /proc/PID/gid_map (這里的 PID 是新 user namespace 中的進程 ID,剛開始時這兩個文件都是空的)文件中。這兩個文件中的配置信息的格式如下(每個文件中可以有多條配置信息):

ID-inside-ns ID-outside-ns length

比如 0 1000 500 這條配置就表示父 user namespace 中的 1000~1500 映射到新 user namespace 中的 0~500。

對 uid_map 和 gid_map 文件的寫入操作有著嚴格的權限控制,簡單點說就是:這兩個文件的擁有者是創建新的 user namespace 的用戶,所以和這個用戶在一個 user namespace 中的 root 賬號可以寫;這個用戶自己是否有寫 map 文件的權限還要看它有沒有 CAP_SETUID 和 CAP_SETGID 的 capability。注意:只能向 map 文件寫一次數據,但可以一次寫多條,并且最多只能 5 條。

我們把剛才打開的 shell 窗口稱為第一個 shell 窗口開始執行用戶的映射操作(把用戶 nick 映射為新 user namespace 中的 root)。

第一步,先在第一個 shell 窗口中查看當前進程的 ID:

Linux,Namespace,User

第二步,新打開一個 shell 窗口,我稱之為第二個 shell 窗口。查看進程 3049 的映射文件屬性:

Linux,Namespace,User

用戶 nick 是這兩個文件的所有者,讓我們嘗試向這兩個文件寫入映射信息:

Linux,Namespace,User

看上去很奇怪呀,明明是文件的所有者,卻沒有權限向文件中寫入內容!其實根本的原因在于當前的 bash 進程沒 CAP_SETUID 和 CAP_SETGID 的權限:

Linux,Namespace,User

下面我們為 /bin/bash 程序設置相關的 capabilities:

 

復制代碼代碼如下:
$ sudo setcap cap_setgid,cap_setuid+ep /bin/bash

 

$ sudo setcap cap_setgid,cap_setuid+ep /bin/bash

然后重新加載 bash,就可以看到相應的 capabilities 了:

Linux,Namespace,User

現在重新向 map 文件寫入映射信息:

$ echo '0 1000 500' > /proc/3049/uid_map$ echo '0 1000 500' > /proc/3049/gid_map

這次的寫入成功了。后面就不需要我們手動寫入映射信息了,所以我們通過下面的命令把 /bin/bash 的 capability 恢復為原來的設置:

$ sudo setcap cap_setgid,cap_setuid-ep /bin/bash

Linux,Namespace,User

第三步,回到第一個 shell 窗口

重新加載 bash,并執行 id 命令:

Linux,Namespace,User

當前用戶已經變成了 root(新的 user namespace 中的 root 用戶)。在看看當前 bash 進程具有的 capability:

Linux,Namespace,User

0000003fffffffff 表示當前運行的 bash 擁有所有的 capability。

第四步,在第一個 shell 窗口中

查看 /root 目錄的訪問權限:

Linux,Namespace,User

沒權限啊!嘗試修改主機的名稱:

Linux,Namespace,User

依然是沒有權限啊!看來這個新 user namespace 中的 root 用戶在父 user namespace 里面不好使。這也正是 user namespace 所期望達到的效果,當訪問其它 user namespace 里的資源時,是以其它 user namespace 中的相應用戶的權限來執行的,比如這里 root 對應父 user namespace 的用戶是 nick,所以改不了系統的 hostname。

普通用戶 nick 沒有修改 hostname 的權限,那把默認的 user namespace 中的 root 用戶映射為子 user namespace 中的 root 用戶后可以修改 hostname 嗎?答案是,不行!那是因為不管怎么映射,當用子 user namespace 的用戶訪問父 user namespace 的資源的時候,它啟動的進程的 capability 都為空,所以這里子 user namespace 的 root 用戶在父 user namespace 中就相當于一個普通的用戶。

User namespace 與其它 namespace 的關系

Linux 下的每個 namespace,都有一個 user namespace 與之關聯,這個 user namespace 就是創建相應 namespace 時進程所屬的 user namespace,相當于每個 namespace 都有一個 owner(user namespace),這樣保證對任何 namespace 的操作都受到 user namespace 權限的控制。這也是為什么在子 user namespace 中設置 hostname 失敗的原因,因為要修改的 uts namespace 屬于的父 user namespace,而新 user namespace 的進程沒有老 user namespace 的任何 capabilities。

以 uts namespace 為例,在 uts_namespace 的結構體中有一個指向 user namespace 的指針,指向它所屬的 user namespace(筆者查看的 v4.13內核,uts_namespace 結構體的定義在 /include/linux/utsname.h 文件中):

Linux,Namespace,User

其它 namespace 的定義也是類似的。

總結

相對其它的 namespace 而言,user namespace 稍顯復雜。這是由其功能決定的,涉及到權限管理的內容時,事情往往會變得不那么直觀。筆者在本文中也只是介紹了 user namespace 的基本概念,更多豐富有趣的內容還有待大家自行發掘。

參考:

user namespace man page
Namespaces in operation, part 5: User namespaces
Namespaces in operation, part 6: more on user namespaces
Linux capabilities

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到服務器教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 精品国产91久久久 | 成人精品一区二区三区中文字幕 | 亚洲男人的天堂在线视频 | 成人午夜在线免费视频 | 精品国内视频 | 艹男人的日日夜夜 | 黄色免费大片 | 毛片免费在线观看 | 特一级黄色毛片 | 成人免费毛片一 | 欧美一区成人 | 久久经典国产视频 | 深夜视频在线 | 狠狠干五月天 | 欧美一级特黄aaaaaaa什 | 在线观看免费污视频 | 国产成人精品一区二区三区电影 | 国产成人综合在线 | 日韩精品中文字幕在线播放 | 久久狠狠高潮亚洲精品 | 欧美一级黄色片免费观看 | 久久出精品| 日韩一级电影在线观看 | 亚洲视频精品在线 | 粉嫩蜜桃麻豆免费大片 | 嗯~啊~弄嗯~啊h高潮视频 | 免费啪视频在线观看 | 九九热视频免费观看 | 91九色视频在线播放 | 久久久久久99 | 91成人久久 | 欧美成年性h版影视中文字幕 | 国产精品一品二区三区四区18 | 亚洲小视频在线观看,com | 九九久久视频 | 成人福利在线视频 | 欧美极品欧美精品欧美视频 | 伊人久操视频 | 欧美精品久久久久久久久老牛影院 | 免费啪啪 | 国产精品剧情一区二区三区 |