古い話になりますが、Androidがシステムプログラムのために「Rust」をサポートするとGoogle Security Blogにエントリを公開しています。
公開されたエントリでは、Android OSのシステムプログラミングに使われている、CとC++は言語仕様が要因でメモリ関連のバグが引き起こされており、これは重要度の高い脆弱性のうち70%を占めるとしています。また、この類のバグ検出や修正、軽減のために多大な労力とリソースを割いているともしています。
これを解決するために、メモリセーフなプログラミング言語を使うのが最も効率の高い手段と考えて、OSを開発するためのサポート開発言語としてRustをサポートするとアナウンスしました。
システムプログラムにCやC++を使う理由
一方、Androidアプリの開発には、JavaやKotlinが使われています。
これで開発する時は、プログラマーはメモリの状況を意識してプログラミングする必要がありません。メモリ管理は、Androidのランタイム(ART)が代わりに行います。結果、メモリ関連のバグが引き起こされることはなく、安全にアプリを実行できます。
近年、実行プラットフォームのハードウェアリソースが潤沢になったために、アプリ開発言語は、メモリ管理を意識しないプログラミング言語がメジャーになりました。JavaScriptは、その好例です。
システムプログラムでも、同じプログラミング言語で開発すれば良いのでは?と考える方もいると思います。こうした言語が使われない理由は、ランタイム実装のリソースが必要になるのとオーバーヘッドの要因になるのを嫌っています。また、実行時のパフォーマンス予測や低レベルでの制御がしづらくなるのも理由です。
OSの中でもハードウェアに近く、基礎性能の高さが求められる部分には使わないのが通例ですが、あまりシビアではない部分、たとえば、ユーザインターフェースにはJavaScriptやCSSなどHTML5が使われている例があり、webOSやFirefox OSがそうでした。
CとC++を使い続ける場合、安全を担保するためにサンドボックスを使う方法も考えられます。こうすることで、メモリ関連の操作が起因となっている脆弱性を低減できますが、このコストとしてオーバーヘッドと遅延の増加、そして、メモリ使用量の増加があります。これを気にしないとしても、メモリ操作が起因したバグが無くなったわけではないので、根本的な解決にはなりません。
Rustの特徴的なメモリ管理
Rustは、CとC++に代わるシステムプログラム言語を目指して開発されています。MozillaがFirefoxのレンダリングエンジンをRustで開発していることでも有名です。
登場時期は2010年です。C言語が1972年の登場になるので、比較すると歴史の浅いプログラミング言語です。元はMozilla従業員の個人プロジェクトでしたが、Mozillaが開発に関わりはじめてMozilla Researchの公式プロジェクトになった経緯があります。現在は、オープンソースで開発が進められており、言語仕様、ソースコード、ドキュメントなどが公開されています。
Rustには、Javaなどで使われるガベージコレクションがなく、独自の考えを持った特徴的なメモリ管理を行います。
例えば、スコープ内で使われた変数やオブジェクトは、スコープを抜けると破棄することを言語レベルでサポートします。他にも特徴的な部分として、所有権と移譲という考え方があります。たとえば、以下のコードでは、
hogeからhelloに代入したするとhogeが使えなくなります。
代入した時はオブジェクトがコピーされたと考えるのが通例ですが、値を代入した時は所有権も譲渡されます。この所有を渡したくない場合は、参照を使う方法もあります。Rustは、操作間違いが発生しづらいメモリ管理のルールを適用することで、メモリリークなどを抑制しています。また、変数に対する不正なアクセスチェックなどは、コンパイル時に行われるので問題には事前対処できます。
これで、メモリ操作に対する安全性が担保しつつ、コード量に対するバグ密度を減らすことができるという考えです。
C++はRustと共生する
RustはAndroidの開発に導入されており、最初のプロジェクトはBluetoothスタックです。
膨大なコードの書き換えは、新たなバグを作る要因となるのでRustに書き換えることはせず、新規開発のプロジェクトからRustを使うアプローチが取られています。当面は、C++と共生することになりそうです。
今週は、このあたりで、また来週。