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
エラーが発生します。誰かが私が間違っていることを教えてもらえますか?
私はdocker runc(libcontainer)からこのアイデアを得ました。 https://github.com/docker/runc/blob/ae2948042b08ad3d6d13cd09f40a50ffff4fc688/libcontainer/rootfs_linux.go#L463
この質問は以下に関連する可能性があります。 -bash: /dev/null: 権限が拒否されました。
オペレーティングシステム:Debian Busterカーネル:4.19.37
答え1
問題をすばやく修正する:オプションを使用したマウント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
非ルート所有者、他人の書き込み権限()、およびS_IWOTH
ディレクトリの固定ビット()の組み合わせは、最新のLinuxカーネルで奇妙な動作を引き起こす可能性があります。使用済みとマークされている場合は、ディレクトリ所有者が実行した場合も同様です。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 <[email protected]>
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でも通常のファイルでもないため、消去されません。これは、インクルードディレクトリに固定ビットが設定されており、そのuidがそのディレクトリのuidとそのファイルを開こうとするプロセスのuidとは異なるためです。
if
含まれているディレクトリに002
(他のユーザーへの書き込み)ビットが設定されているため、2番目のディレクトリとすぐに一致します。
私はこれが紹介されたlkmlディスカッションのどこにもありません(1、2、サム)この影響を考慮しました。とにかく、書き込み可能な固定ディレクトリに文字デバイスを置くことは意図的なことではありません。