如何在 linux 命名空間中創建 /dev
AFAIK 容器術語,我基本上想要完成的是編寫我自己的“容器執行時”。
我在做什麼:
user@host:~$ mkdir test user@host:~$ cd test user@host:~/test$ mkdir dev user@host:~/test$ mkdir proc user@host:~/test$ echo 1 |sudo tee /proc/sys/kernel/unprivileged_userns_clone user@host:~$ unshare --ipc --mount --net --pid --uts --cgroup --user \ --map-root-user --fork bash root@host:~/test# mount none -t tmpfs dev/ root@host:~/test# touch dev/zero root@host:~/test# mount /dev/zero -o bind dev/zero root@host:~/test# echo 1 > dev/zero bash: dev/zero: Permission denied root@host:~/test# ls -lah dev total 4.0K drwxrwxrwt 2 root root 60 Sep 1 15:12 . drwxr-xr-x 3 root root 4.0K Sep 1 13:47 .. crw-rw-rw- 1 nobody nogroup 1, 5 Sep 1 13:55 zero root@host:~/test# mount # we are still looking at hosts /proc <...> none on /home/user/test/dev type tmpfs (rw,relatime,uid=1000,gid=1000) udev on /home/user/test/dev/zero type devtmpfs (rw,nosuid,relatime,size=3921088k,nr_inodes=980272,mode=755) root@host:~/test# mount none -t proc proc/ root@host:~/test# cat proc/mounts <...> none /home/user/test/dev tmpfs rw,relatime,uid=1000,gid=1000 0 0 udev /home/user/test/dev/zero devtmpfs rw,nosuid,relatime,size=3921088k,nr_inodes=980272,mode=755 0 0 none /home/user/test/proc proc rw,relatime 0 0
回顯
dev/zero
產生錯誤。有人可以告訴我我做錯了什麼嗎?我從 dockers runc(libcontainer) 那裡得到了這個想法: https ://github.com/docker/runc/blob/ae2948042b08ad3d6d13cd09f40a50ffff4fc688/libcontainer/rootfs_linux.go#L463
這個問題可能是相關的: -bash: /dev/null: Permission denied
作業系統:Debian buster 核心:4.19.37
快速解決您的問題:
tmpfs
使用mode=
選項掛載(設置文件系統根目錄的權限),並使用沒有粘性位(01000
)或其他人的寫權限(002
)的模式 - 這兩個都打開預設情況下:root@host:~/test# mount -o mode=0755 -t tmpfs none dev/
你不會失去任何東西;首先,讓
/dev
每個人都可以在容器中粘貼可寫目錄並不是一個好主意(知道 docker 是否也在這樣做會很有趣;-))發生這種情況是因為使用者命名空間內的掛載:核心根據執行掛載的程序的未翻譯憑據(然後在輸出中)設置文件系統
tmpfs
根目錄的所有者,並將其權限設置為預設值(對於每個人+粘性位)。tmpfs``uid=1000,gid=1000``mount(1)``01777``rwx
在較新的Linux 核心中,非 root 所有者、其他人的寫權限
S_IWOTH
(使用,即使由目錄的所有者完成:S_ISVTX``open(2)``EACCES``O_CREAT
$ mkdir doo; chmod 1777 doo $ su -c 'mknod -m 666 doo/null c 1 3' # or touch doo/null; mount -B /dev/null doo/null $ echo > doo/null bash: doo/null: Permission denied $ perl -MFcntl -e 'sysopen(NULL, "doo/null", O_WRONLY|O_CREAT, 0666) or die $!' Permission denied at -e line 1. $ perl -MFcntl -e 'sysopen(NULL, "doo/null", O_WRONLY, 0666) or die $!' $ # ok! $ chmod -t doo $ echo > doo/null $ # ok!
這可以在 Debian Buster / 4.19.0-5 和更新的核心上重現,但不能在 Debian Stretch / 4.9.0-4 上重現。
該行為是作為此送出的副作用引入的:
commit 30aba6656f61ed44cba445a3c0d38b296fa9e8f5 Author: Salvatore Mesoraca <s.mesoraca16@gmail.com> Date: Thu Aug 23 17:00:35 2018 -0700 namei: allow restricted O_CREAT of FIFOs and regular files ... diff --git a/fs/namei.c b/fs/namei.c ... +static int may_create_in_sticky(struct dentry * const dir, + struct inode * const inode) +{ + if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || + (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || + likely(!(dir->d_inode->i_mode & S_ISVTX)) || + uid_eq(inode->i_uid, dir->d_inode->i_uid) || + uid_eq(current_fsuid(), inode->i_uid)) + return 0; + + if (likely(dir->d_inode->i_mode & 0002) || + (dir->d_inode->i_mode & 0020 && + ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) || + (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) { + return -EACCES; + } + return 0; +}
doo/null
不會清除第一個,if
因為它既不是 fifo,也不是正常文件,包含的 dir 確實設置了它的粘性位,並且它的 uid 與 dir 的 uid 以及試圖打開它的程序的 uid 不同。它將立即匹配第二個
if
,因為包含的目錄設置了002
(write-for-others) 位。我還沒有在 lkml 討論中找到引入(1、2、3)是否考慮了這種影響。無論如何,將字元設備放在世界可寫的粘性目錄中不太可能是故意的。