インストールされたRaspbianのコピーを使用しています。鳩。 Pi-genはファイルシステムボリュームを持つDockerコンテナで実行され、ボリュームdebootstrap
内でカスタムスクリプトを実行します。chroot
chroot
Raspbianファイルシステム内でシェルを使用して実行していますが、qemu-arm-static
Dockerは使用しません。
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 +f
ありset +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を実行します。dash
http://raspbian.raspberrypi.org/raspbian stretch/main armhf
4.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の変更のようです。
getdents64
d_off
64ビットLinuxでは、32ビットに不適切な値を返す可能性がありますint
。 32ビットシステムは32ビット値のみを返します。qemu-user
64ビットLinuxで32ビットシステムをエミュレートするとシステムコールが転送されるため、32ビットユーザーモードプロセスはオーバーフロー値を取得できます。- glibc 2.28では変化これにより、
readdir
正しくないときは常に使用され、エラーが発生する可能性がありますgetdents64
。d_off
実際の32ビットシステムでは、glibcはこれを処理するため、問題は発生しないでください。 (以前はgetdents
32ビットシステムで呼び出され、32ビット値を返し、すべての切り捨てはカーネルによって行われました。)
修正(または不足)
このglibcエラー現在、この問題の進捗状況を追跡しています。ディストリビューションを修正して最終的にデプロイするには時間がかかります。
解決策
- 私が見ることができる最も簡単な解決策は、32ビットLinuxカーネルを持つシステムでこれらのビルドを実行することです。
- glibc バージョン (chroot!) を 2.27 にダウングレードすると問題は解決しますが、これにより依存関係の問題が発生し、ビルド中のイメージが変更されることがあります。
- リンクスレッドの多くのパッチの1つを適用することもできますが、これにはカーネル、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ビット値を期待します)。