대시는 chroot에서 glob 와일드카드를 확장하지 않습니다.

대시는 chroot에서 glob 와일드카드를 확장하지 않습니다.

설치된 Raspbian 사본을 사용하고 있습니다.비둘기. Pi-gen은 파일 시스템 볼륨이 있는 Docker 컨테이너에서 실행되고 debootstrap볼륨 내에서 사용자 지정 스크립트를 실행합니다.chroot

chrootRaspbian 파일 시스템 내에서 셸을 사용하고 실행하고 있지만 qemu-arm-staticDocker는 사용하지 않습니다.

mkinitramfs스크립트가 작동하지 않는 것으로 나타났습니다 . dash스크립트가 실행되는 위치 에서 문제를 추적했습니다 .

어떤 이유로 dash파일 이름 와일드카드가 명령에서 확장되지 않습니다.

# echo /*
/*
# ls /
bin boot dev etc home lib media mnt opt proc root run sbin sys tmp usr var

이는 chroot 내의 모든 폴더에서 발생하며대본에서도. 이것은 많은 것을 깨뜨릴 것입니다.

그러나 와일드카드 확장은 내부적으로 바인드 마운트된 파일 시스템( chroot/proc: /run. 또한 dash동일한 바이너리를 사용하는 경로 확장을 다른 chroot.

나는 그것을 시도했지만 set +fset +o noglob이 좋지 않았습니다. 이 noglob옵션은 확실히 켜져 있지 않습니다.

# set -o
Current option settings
errexit         off
noglob          off
ignoreeof       off
interactive     on
monitor         on
noexec          off
stdin           on
xtrace          off
verbose         off
vi              off
emacs           off
noclobber       off
allexport       off
notify          off
nounset         off
nolog           off
debug           off

의 패키지 버전을 실행하고 있습니다 0.5.8-2.4. 호스트는 커널과 함께 Kali Linux 2019.1을 실행합니다.dashhttp://raspbian.raspberrypi.org/raspbian stretch/main armhf4.19.0-kali4-amd64

이전에 비슷한 문제를 본 사람이 있습니까? 해결 방법으로 무엇을 사용할 수 있나요?

고쳐 쓰다:strace작업 덤프의 관련 부분은 다음과 같습니다 chroot.

read(0, "echo /*\n", 8192)              = 8
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents(3, /* 11 entries */, 32768)    = 264
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
write(1, "/bin /dev /etc /lib /pls /proc /"..., 46) = 46

이는 작업하지 않을 때도 마찬가지입니다 chroot.

read(0, "echo /*\n", 8192)              = 8
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
close(3)                                = 0
write(1, "/*\n", 3)                     = 3

답변1

이유

~처럼에티엔이 발견했습니다(그들의 연구 노력에 투표해주세요) 근본 원인은 glibc 2.28의 변경인 것 같습니다.

  • getdents64d_off64비트 Linux에서는 32비트에 적합하지 않은 값을 반환할 수 있습니다 int. 32비트 시스템에서는 32비트 값만 반환합니다.
  • qemu-user64비트 Linux에서 32비트 시스템을 에뮬레이션하면 시스템 호출이 전달되므로 32비트 사용자 모드 프로세스는 오버플로 값을 얻을 수 있습니다.
  • glibc 2.28에는변화이렇게 하면 readdir맞지 않을 때 항상 사용하고 오류가 발생할 수 있습니다 getdents64. d_off실제 32비트 시스템에서는 glibc가 이를 처리하므로 문제가 발생해서는 안 됩니다. (이전에는 getdents32비트 시스템에서 호출되어 32비트 값을 반환하고 모든 잘림은 커널에 의해 수행되었습니다.)

수정(또는 부족)

이 glibc 오류현재 이 문제의 진행 상황을 추적 중입니다. 배포판을 수정하고 최종적으로 배포하는 데는 시간이 걸립니다.

해결책

  • 제가 볼 수 있는 가장 간단한 해결책은 32비트 Linux 커널이 있는 시스템에서 이러한 빌드를 실행하는 것입니다.
  • glibc 버전(chroot!)을 2.27로 다운그레이드하면 문제가 해결되지만 이로 인해 종속성 문제가 발생하고 빌드 중인 이미지가 변경될 수 있습니다.
  • 링크 스레드의 많은 패치 중 하나를 적용할 수도 있지만 이를 위해서는 커널, glibc 또는 (아마도 가장 간단한) QEMU를 컴파일해야 합니다(패키지 관리자에서 분리할 수도 있음).

답변2

다른 프로젝트(QEMU가 아닌 docker 기반)를 작업 중인데도 내 컴퓨터에서 똑같은 증상이 나타나므로 이것이 귀하의 경우 문제인지 증명할 수는 없지만 그럴 수도 있습니다.

와일드카드가 항상 확장되지 않기 때문에 때로는 작동하고 때로는 실패하는 빌드가 있습니다(제가 수행하고 있는 작업입니다 ls /tmp/linux*deb).

Strace는 실패할 경우 getdents에 대한 호출이 반환됨을 보여줍니다.-1 EOVERFLOW (Value too large for defined data type)

업무 사례:

[pid 29791] open("/tmp", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
[pid 29791] fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 29791] getdents(3, /* 3 entries */, 32768) = 60
[pid 29791] getdents(3, /* 0 entries */, 32768) = 0
[pid 29791] close(3)                    = 0

실패 사례:

[pid 25606] open("/tmp", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
[pid 25606] fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=100, ...}) = 0
[pid 25606] getdents(3, /* 1 entries */, 32768) = 16
[pid 25606] getdents(3, 0x585a831c, 32768) = -1 EOVERFLOW (Value too large for defined data type)
[pid 25606] close(3)                    = 0

이 문제를 언급하는 몇 가지 버그 보고서를 발견했습니다(getdents는 64비트 값을 반환하지만 이 경우 호출자는 32비트 값을 기대합니다).

관련 정보