--bind --make-private /etc/hosts를 새 네임스페이스에 마운트하고 이전 네임스페이스에서 vim을 사용하여 이 파일을 수정하면 새 ns에도 영향을 미치는 이유는 무엇입니까?

--bind --make-private /etc/hosts를 새 네임스페이스에 마운트하고 이전 네임스페이스에서 vim을 사용하여 이 파일을 수정하면 새 ns에도 영향을 미치는 이유는 무엇입니까?

다른 네임스페이스를 사용하여 새 네임스페이스를 만들고 싶었 기 때문에 이 답변에서 참조한 대로 unshare를 사용하여 생성 /etc/hosts해 보았습니다 .mount --bindhttps://unix.stackexchange.com/a/242830/271204

# Create temp hosts
export TEMP_HOSTS=$(mktemp XXXXXXX.hosts)
trap "{ rm -f $TEMP_HOSTS; }" EXIT
cat /etc/hosts > $TEMP_HOSTS

# Create new ns
unshare -m bash
mount --make-private "$TEMP_HOSTS" /etc/hosts --bind

그런 다음 새 쉘(Shell2라고 부르겠습니다)을 얻었고 그 안에 몇 가지 내용을 썼습니다. 중요하지 않습니다. /etc/hosts추가하거나 편집한 후에도 계속 마운트됩니다.

(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
218 189 8:1 /tmp/Z3flEXS.hosts /etc/hosts rw,relatime - ext4 /dev/sda1 rw,errors=remount-ro
(Shell2) # echo '127.0.0.1 aaaa' >> /etc/hosts
(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
218 189 8:1 /tmp/Z3flEXS.hosts /etc/hosts rw,relatime - ext4 /dev/sda1 rw,errors=remount-ro

새 터미널 창을 시작하거나 새 SSH 세션을 생성하면 시스템의 이전 네임스페이스가 포함된 셸이 생성되고 이는 Shell1로 표시됩니다.

Shell1 아래의 /etc/hosts는 마운트되어 있기 때문에 여전히 이전 버전입니다 --make-private. 그러나 `vim을 사용하여 Shell1 아래의 /etc/hosts를 수정하면 Shell2 아래의 /etc/hosts도 변경되고 마운트가 사라집니다.

# Append "127.0.0.1 aaaaa" with vim, or you can use vim interactively.
(Shell1) # vim -c "$ s/$/\r127.0.0.1 aaaaa/" -c "wq" /etc/hosts
(Shell1) # md5sum /etc/hosts
1580e29f05e6af70012afe37ce08cb5a  /etc/hosts
(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
* Nothing here
(Shell2) # md5sum /etc/hosts
1580e29f05e6af70012afe37ce08cb5a  /etc/hosts

/etc/hosts하지만 새로운 네임스페이스의 shell1에서 /etc/hosts를 수정하는 단계에서 echo '127.0.0.1 aaaa' >> /etc/hostsedit vim구하다.

그렇다면 제 질문은 이전 네임스페이스의 파일을 수정하면 vim새 네임스페이스의 파일도 영향을 받는 이유는 무엇입니까? 쉘 리디렉션을 사용할 때 동작이 다른 이유는 무엇입니까? 이전 네임스페이스에서 vim으로 인한 변경을 방지하기 위해 unshare또는 옵션을 변경할 수 있나요 ?mount

답변1

이는 파일이 제자리에서 편집되지 않기 때문입니다 vim. 파일을 저장할 때 vim은 동일한 디렉터리에 임시 파일을 만든 다음 이름을 원래 파일로 바꿉니다.

cp /etc/hosts{,~}; mv /etc/hosts{~,}를 사용하거나 를 사용하여 sed -i동일한 효과를 얻을 수 있습니다 vim. 한 파일의 이름을 다른 파일로 바꾸는 것은 이전 디렉토리 항목의 링크를 해제한 다음 그 자리에 다른 파일을 생성하는 것과 같습니다(그러나 단일 원자 단계로).

연결 해제 부분은 다른 네임스페이스에서 마운트를 제거하는 것입니다.

detach_mounts이는 예상된 동작입니다. in 호출을 참조하세요.fs/namei.c에서 vfs_{unlink,rename,rmdir}(). 마운트는 하나만동일한네임스페이스로 인해 실패하고 표시됩니다 EBUSY.

다소 개략적으로 느껴지지만 이것이 없으면 모든 프로세스가 개인 네임스페이스의 파일이나 디렉터리에 마운트되어 삭제되는 것을 방지할 수 있으며 이는 서비스 거부 공격으로 바뀔 수 있습니다.[1]

다음 파일을 마운트할 때에도 동일한 당황스러운 동작이 발생합니다. /proc/PID/프로세스가 종료되면 마운트가 PID명시적으로 마운트 해제되지 않고 사라집니다.


[1] 이것은 실제로 다음에서 나온 것입니다.범죄이로 인해 2013년에도 행동이 바뀌었습니다.마운트 네임스페이스(7)맨페이지:

이전에는(Linux 3.18 이전) 다른 마운트 네임스페이스의 마운트 지점이었던 파일이나 디렉터리를 연결 해제하거나 이름을 바꾸거나 삭제하려고 하면 오류가 발생했습니다 EBUSY. 이 동작에는 기술적 구현 문제(예: NFS)가 있으며 더 많은 권한을 가진 사용자에 대한 서비스 거부 공격이 허용됩니다. (즉, 마운트를 번들로 묶음으로써 개별 파일이 업데이트되는 것을 방지합니다).

관련 정보