🦀
Homebrew経由で入れたbinutilsを使ってビルドスクリプトを使うようなcargo build --releaseをするとSIGKILLが出て死ぬ
#tech2024-06-29
タイトルの通り.Homebrew経由で入れたbinutilsを使ってcargo build --releaseするとbuild-script-buildでSIGKILLが出る.cargo buildすると正常に通る.
M1 MAXが載ったmacでやっていたのでチップの問題を疑ったが,原因はbinutilsをどう入れているかに起因したという話.
セキュリティ・キャンプ2024 全国大会 OS自作ゼミで,ひとまず以前作成したRISC-V 32bit向けRust製カーネルを64bitにしていくことになった.それ自体は割とすぐできたが,その後のユーザーランドを追加する部分でこの問題が発生した.まずは当時の状態を貼る:
この後の説明に必要な部分だけ説明すると,ディレクトリ構造が次のようになっていて,
$ tree -L 2 -d
.
├── kernel
│ ├── src
│ └── target
└── user
├── src
└── target
6 directories
kernelにはカーネルのソースコード,userにはユーザーランドのソースコードを入れている.ビルド手順はMakefile.tomlに定義されているrunというジョブにあるが,大雑把に言うとuserをビルドしてそのバイナリをkernelにリンクさせる形式でkernelをビルドする.この際にkernelに入ってcargo build --releaseするとSIGKILLが起こって死ぬ問題が発生した.

様子
ここでbuild-script-build内でSIGKILLが起こっていることは分かるのでとりあえず雑にこのバイナリに対してfileとかotoolとかを刺してみるが有用っぽい情報は得られなかった.
「きびし~」と思って試しにcargo buildすると,これは通る.あと普段のこのOSの開発はWSL2上でやっているのだが,こちらだとどちらのビルドも通る.少し調べたがエスカレしておいて良さそうと思ったので,セキュキャンのDiscordサーバーで講師にエスカレした(見ていただいてありがとうございます...).
一緒に調査したところ,まずlldbを刺してみると良いのではという話になり,lldbでrunしてみた.その様子がこちら:

lldbを刺した様子
"Malformed Mach-O file"と宣っている.普通にビルドしただけなのにMalformedとか言われるの大分心外だが!?みたいな気持ちになり,なる.皆さんも同じ状況ならなると思います.
ここから調査すると,次のようなIssueが見つかった:
どうやらbinutilsをHomebrew経由で入れると,中に入っているstripが壊れていてMalformedなMach-Oになるらしい.確かにそれならreleaseビルドでだけ死ぬのも納得だが,だが...
で,更に調査するとHomebrew経由のbinutilsと使ってビルドしたものとMacにデフォルトで入っているbinutils系のコマンドを使ってビルドしたものではMach-Oのバージョンが異なるので,binutils側が追従できていないんだろうなあの気持ちになる(前者が2,後者が1).
ということでbrew uninstall binutilsをしてビルドして難を逃れている.パスを変えるのでも良いが忘れそう.
上で挙げたIssueはどれも"Homebrew経由で入れるの止めようね!笑"でcloseされているのできびしい気持ちにはなる.