BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース 静的アナライザRudraがRustクレート内に200件のメモリ安全上の問題を検出

静的アナライザRudraがRustクレート内に200件のメモリ安全上の問題を検出

原文(投稿日:2021/11/13)へのリンク

ジョージア工科大学で開発されたRudraは、Rustプログラム内の潜在的なメモリ安全性のバグをレポートするスタティックアナライザだ。Rustパッケージレジストリ全体のスキャンに使用されて、264件の新たなメモリ安全性バグを検出した。

Rustはメモリ安全性を実現するために設計された言語だ。nullポインタの生成やダングリングポインタ、データレース(data race)の可能性を低減するための機能を数多く備えている。これらすべての機能の基盤にあるのが、所有権に基づくRustのメモリ管理モデルと型システムであり、安全でない使用に対してコンパイラがフラグを付けることを可能にしている。

Rustプログラムに未定義の動作がないことを保証するために、Rustコンパイラがさまざまなことを行う一方で、これらの保証に拘束されないコードの記述も許されている。そのコードをunsafe領域に含めることだ。これは直接アクセスするポインタのように、低レベルのハードウェアアクセスを必要とするシステムソフトウェアを記述するために必要な言語機能である。要するにunsafe領域とは、コンパイラの保証を一時的にバイパスするメカニズムを提供するものなのだ。

Rustプログラムに不適切な処理が紛れ込むのはこの部分だ、と[Rudaの開発者ら]は説明する(https://dl.acm.org/doi/pdf/10.1145/3477132.3483570)。

Rustの安全性の保証は、プログラムだけでなく、標準ライブラリや外部ライブラリ内のすべてのunsafeコードの健全性に依存しており、それが正当性の判断を難しいものにしています。要するに、unsafeコード内のひとつのバグがプログラム全体の安全性保証を台無しにする、ということです。

Rustパッケージの25~30パーセントがunsafeを使用していると推定されており、それらがプログラムを不適切性のリスクにさらすことになる。不正な可能性のあるコードはunsafe領域内に分離されているため、それを集中的にチェックすることは可能ではあるが、不正であることを論証するのは簡単ではない、とRudraの作者らは述べた上で、panicの安全性、高次の安全性不変条件(safety invariants)、ジェネリック型におけるSend/Syncの伝搬という、Rustでメモリバグを発生させる3つのパターンについて説明している。Rudraでは、これらのパターンを処理するために特別なテクニックを構築している。これら3パターンの解析と検出のためのアプローチは、この記事で解説可能な複雑性のレベルを超越しているので、興味のある読者は前出のリンクから論文を参照して頂きたい。

上で述べた3つのバグパターンは難解に聞こえるかも知れないが、Rustパッケージレジストリを対象にRudraを実行すればパッケージ内に多数のバグを見つけることができる。その中にはRust標準ライブラリやRustコンパイラに加えて、ダウンロード数ベースで30位のクレートも含まれているのだ。

Rundaは、広範なコードカバレッジとファザ(fuzzer)を持ったユニットテストによって十分にテストされたパッケージからも、メモリ安全性に関するバグを見つけています。見つかったバグは軽微なものではありません — しかも、平均で3年以上存在しているのです。

Rudraはcrates.ioで公開されている43,000以上のパッケージを、6.5時間を要して分析した。その結果、145パッケージから264のメモリ安全性に関するバグが新たに見つかった。それらは現在、112のRustSecと76のCVEとして記載されている、と研究者らは述べている。

これらの結果は、Rustの安全モデルがC++など他の言語よりも改善されている、という信念を損なうように思えるかも知れない。だが、それは正しくない、とRudraを開発した研究者らは言う。彼らは変わらず、Rustの安全性を最高レベルの改善であると考えているのだ。

C/C++ではバグを報告する前に、その動作がバグなのか、あるいは意図したものなのかを確認する必要があります。APIの使用方法の誤りとAPI自体のバグに明確な区別がないためなのですが、それとは対照的に、Rustの持つ安全規則は、バグが誰の障害であるのかを判断するための客観的な基準を提供しています。

しかし、彼らの結論では、特に悪意のあるパッケージやOSドライバにある種の不正な動作が意図的に記述されている可能性がある、という観点で言えば、Rustの安全性モデルは、それ自体でシステムの安全性を保証するには力不足なのである。この点においてRudraは、Rustエコシステムの安全性に価値ある貢献をしていると考えられる。

さらに、Rudraの開発者らが主導した分析により、誤用の多いRust APIが何であるかも明らかになったため、Rustの公式リンタであるClippyに新たなルールが加えられる、という予想外の成果もあった。

Rudaは公式のDockerイメージを使って簡単にインストールすることができる。Rustコンパイラのプラグインとして実装されており、ターゲットパッケージの依存関係を変えることなく、分析アルゴリズムを挿入する。また、cargoと統合されていることから、単にcargo rudraを実行するだけで既存のパッケージをチェックすることが可能だ。

この記事に星をつける

おすすめ度
スタイル

BT