Linux 네임스페이스에 /dev를 만드는 방법

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오류가 발생합니다. 누구든지 내가 뭘 잘못하고 있는지 말해 줄 수 있나요?

나는 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마운트를 수행하는 프로세스의 번역되지 않은 자격 증명을 기반으로 파일 시스템 루트의 소유자를 설정하고(이후 출력에서) 해당 권한을 기본값(모든 사람에 대해) + 고정 비트로 설정합니다. ).tmpfsuid=1000,gid=1000mount(1)01777rwx

루트가 아닌 소유자, 다른 사람의 쓰기 권한( ) 및 S_IWOTH디렉토리의 고정 비트( )의 조합은 최신 Linux 커널에서 이상한 동작을 유발할 수 있습니다. 사용된 것으로 표시되면 디렉토리 소유자가 수행한 경우에도 마찬가지입니다.S_ISVTXopen(2)EACCESO_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첫 번째 파일은 iffifo도 일반 파일도 아니기 때문에 지워지지 않습니다. 포함 디렉터리에 고정 비트가 설정되어 있고 해당 uid가 해당 디렉터리의 uid 및 해당 파일을 열려고 하는 프로세스의 uid와 다르기 때문입니다.

if포함하는 디렉토리에 002(다른 사용자를 위한 쓰기) 비트가 설정되어 있으므로 두 번째 디렉토리와 즉시 일치합니다 .

나는 이것이 소개된 lkml 토론 어디에서도 찾을 수 없습니다(1,2,) 이 영향을 고려했습니다. 어쨌든 쓰기 가능한 고정 디렉터리에 문자 장치를 넣는 것은 의도적인 일이 아닐 것입니다.

관련 정보