파일 형식을 읽으려고 합니다 /dev/null
. 사용하면 stat()
문자장치라고 정확하게 보고됩니다.
을 사용하면 getdents()
문자 장치라고 보고됩니다. 컨테이너에서 실행하지 않는 한 일반 파일이라고 표시됩니다!
컨테이너에서 실행하면 왜 다른 결과가 나오나요?
이 이미지를 사용하여 최신 버전의 docker 및 podman에서 테스트한 결과는 동일했습니다 ubuntu:22.04
.
복사할 코드는 다음과 같습니다. 이 코드는 stat()
항상 작동하지만 getdents
컨테이너 내에서 실행될 때 어설션이 실패하게 됩니다. 또한 주목할 만한 점은 코드가 항상 복사되는 것은 아니라는 점입니다. 일부 시스템/컨테이너에서는 여전히 잘 작동하는 것 같습니다.
(리눅스 6.8.2-arch2-1 및 podman 5.0.0에서 테스트됨)
#include <assert.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#define BUF_SIZE 1024
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
int main() {
// stat approach
struct stat st;
stat("/dev/null", &st);
printf("stat type: %d\n", st.st_mode & S_IFMT);
assert((st.st_mode & S_IFMT) == S_IFCHR);
// getdirents approach
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
fd = open("/dev", O_RDONLY | O_DIRECTORY);
for (;;) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *)(buf + bpos);
if (strcmp(d->d_name, "null") == 0) {
d_type = *(buf + bpos + d->d_reclen - 1);
printf("getdents type: %d\n", d_type);
assert(d_type == DT_CHR);
exit(EXIT_SUCCESS);
}
bpos += d->d_reclen;
}
}
close(fd);
exit(EXIT_SUCCESS);
}
답변1
getdirents
이것이 당신에게 말하는 진실이라는 것이 밝혀졌습니다 !
루트 없는 podman 컨테이너로 이동하여 실행하면 이것이 실제로 바인드 마운트임을 mount
알 수 있습니다 ( 컨테이너 내부에서 예제 코드에 액세스할 수 있도록 여기에 있습니다)./dev/null
-v ...
$ podman run -it --rm -v $PWD:/src:z fedora:39
[root@00af7efc8781 /]# mount |grep /dev/null
devtmpfs on /dev/null type devtmpfs (rw,nosuid,noexec,seclabel,size=4096k,nr_inodes=8186582,mode=755,inode64)
이 번들 설치를 제거하면 무엇을 볼 수 있습니까? 알아 보자:
먼저 컨테이너 pid가 필요합니다.
$ podman container inspect -l | jq .[0].State.Pid 50502
이 방법으로
nsenter
관련 mount 및 pid 네임스페이스를 입력할 수 있습니다.$ sudo nsenter -t 50502 -m -p
/dev/null
마지막으로 바인드 마운트를 제거할 수 있습니다 .[root@fizzgig /]# umount /dev/null
이제 다음을 볼 수 있습니다.
[root@fizzgig /]# ls -l /dev/null
-rwx------. 1 21937 21937 0 Apr 2 20:03 /dev/null
놀랍게도 이것은 파일입니다!
호출은 getdirents
디렉토리 항목에서 읽는 중입니다 /dev
. 이는 바인드 마운트에 대해 알지 못함을 의미하므로 d_type
기본 항목이 표시됩니다.