AIがプログラミングコードを書く時代に「重要性が高まるメモリ安全」とは?
ソフトウェアの脆弱性を素早く正確に見つける能力をAIが備えつつある現在、ソフトウェアの安全性を高める「メモリ安全」と呼ばれるキーワードに注目が集まっている。米国ホワイトハウスも「ソフトウェアはメモリ安全になるべき」との声明を出した。メモリ安全とは何か、なぜ重要なのかを今回は解説する。
ホワイトハウスも「メモリ安全なプログラム」を推奨
2024年2月、米国ホワイトハウスの国家サイバー局長室(The White House Office of the National Cyber Director:ONCD)は、テクノロジー業界に対して「将来のソフトウェアはメモリ安全(Memory Safe)なプログラミング言語で開発されるべき」とする提言を発表しました。
その背景には近年のサイバー攻撃が国家の安全保障にも影響を与える規模になってきており、主な原因が「メモリ関連の脆弱性」にあるからです。ホワイトハウスの提言は、そのメモリ関連の脆弱性を引き起こさない「メモリ安全なプログラミング言語を使うべき」ということを示唆しているのです。
このメモリ安全について少し説明しておきましょう。
プログラムの実行中に、例えばユーザーから「テキストの入力がある」あるいは「画面に画像を表示する」といった処理があるとします。このとき入力された文章や表示される画像のデータはいったんメモリ上に展開されます。
データがメモリに展開されるとき、プログラムはOSに対して必要な量のメモリを要求し、メモリは確保されます。入力されたテキストはそのメモリ上に保持してファイルやデータベースに書き込む、あるいは画像データをメモリに読み込んで画面に表示します。
そしてテキストの書き込みや画像の表示が終了したら、そのデータとメモリは不要になるため、確保していたメモリ領域をOSに返却して解放します。
「C/C++」などの従来型のプログラミング言語では、このメモリの確保と解放の指示をプログラマーが自らプログラミングしていきます。このとき例えば操作するメモリの大きさや場所を間違えたり、メモリを確保したまま解放を忘れたりといったバグの発生する余地を残してしまうのです。
このバグから次のような代表的な脆弱性を発生させる可能性があります。
◆バッファオーバーフロー(Buffer Overflow)
確保したメモリ領域を超えてデータを書き込んでしまうこと。プログラムのクラッシュなど予期せぬ動作を引き起こしたり、外部から不正なコマンドを実行可能にされたりする原因となります。
◆解放後メモリの利用(Use-After-Free)
すでにOSに返却され、別のプログラムなどで使われているメモリ領域に対して、誤ったデータを読み書きしてしまうこと。データの改ざんや情報の漏えいにつながります。
◆メモリリーク(Memory Leak)
確保したメモリ領域を使い終わった後、解放を忘れてしまうこと。利用可能なメモリがどんどん減少していき、最終的にシステムが重くなり、異常停止などを引き起こします。
いくつかの調査によると、これまでに発見された深刻なセキュリティ脆弱性の約7割がこうしたメモリ関連のバグに起因するとされています。
それゆえホワイトハウスが提言するように「メモリ安全なプログラミング言語」を使うことで、脆弱性を引き起こさないことが推奨されているのです。
(出典:米国ホワイトハウス、ただしこのページは現在削除されています)
ピンチアウトで拡大
メモリ安全を実現する「2つの方式」
メモリ関連のバグによる脆弱性を引き起こさないためにはメモリ安全なプログラミング言語を利用することですが、具体的には「Java」や「C#」、「Python」「JavaScript」「Go」「Rust」など多くの種類のプログラミング言語があります。
これらのプログラミング言語にはメモリ安全を実現するためのアプローチが主に2種類あります。
1つは「ガベージコレクション方式」です。JavaやC#、Python、JavaScript、Goなど、仮想マシンやインタプリタを用いて実行されるプログラミング言語ではこの方式が採用されています。
ガベージコレクション方式では、メモリの割り当てや解放はすべて仮想マシンやインタプリタが自動的に行ってくれます。プログラマーはメモリ管理を意識することなくプログラミングを行うことになるため、コードの記述が容易になる反面、仮想マシンやインタプリタでガベージコレクションが働く際にわずかな動作遅延が発生するといったデメリットもあります。
もう1つの方法が「静的解析方式」です。代表的なプログラミング言語にはRustがあります。
静的解析方式ではプログラマーがメモリ操作をプログラミングしますが、コンパイル時にコンパイラがメモリ操作にバグがないかどうかを解析し、バグがあればコンパイル時にエラーを発します。これにより実行時にはバグのないメモリ操作が約束されるのです。
そしてコンパイルされたネイティブバイナリが生成・実行されるため、プログラマーによる細かなメモリ管理と高速な実行が実現されるだけでなく、アプリケーションやOS、デバイスドライバといった低レイヤーで動作するシステム構築にも対応できるメリットがあります。
そのためRustは「Linux OS」の開発など、これまでC/C++言語が使われてきた領域での利用も始まっています。
AI時代にメモリ安全が重要な理由とは
生成AIを用いてコードを生成する仕組みが広く使われようとしています。AIは人間よりも短時間で大量にコードを生成することが可能です。そして生成AIによって生成されたコードであっても、バグが含まれている可能性は排除できません。
しかも、AIで大量に生成されたコードにバグや脆弱性が含まれていたとして、それを人間やAIがレビューしてもバグや脆弱性の見逃しを完全になくすことはできないでしょう。
またAIは昨今、コードを生成するだけでなく、サイバー攻撃にも使われるようになってきています。生成AIによる攻撃は人間よりも素早く脆弱性を見つけ出し、攻撃を組み立ててきます。
こうした状況が想定されるからこそ、最初からメモリ関連のバグや脆弱性を引き起こさないプログラミング言語の利用に重要性が高まっているのです。
AI支援で「プログラミング言語の移行」も容易に
とはいえ、現在でも例えばLinux OSが主にC/C++でつくられているように、メモリ安全ではないプログラミング言語で書かれ、開発が行われているソフトウェアは世の中に多数存在します。
これらを突然、すべてメモリ安全なRustで書き直すことは現実的ではありません。そもそもC/C++のようなメモリ安全ではないプログラミング言語でこれまで開発を進めてきたプログラマーが、新たにRustのようなメモリ安全なプログラミング言語を従来同様に使いこなせるかは疑問です。
しかし、そうした学習コストもAIのコーディング支援によって大幅に縮小されつつあり、あるいはAIによる移行作業そのものの自動化も進むことでしょう。
実際にLinux OSではRustでの開発を受け入れており、またマイクロソフトもWindowsの開発にRustを採用し始めたという報道がされています。
AIの登場によって大量にコードが生成される時代の一方で、AIを取り巻くさまざまな要因がメモリ安全なプログラミング言語の重要性を高めながら、その活用を促進していくのは間違いありません。そしてホワイトハウスの提言通り、数年後もしくは十数年後には、ほとんどすべてのソフトウェアがメモリ安全なプログラミング言語で開発されることになるでしょう。
※このコラムは不定期連載です。
※会社名および商標名は、それぞれの会社の商標あるいは登録商標です。

-
新野淳一/Junichi Niino
ブログメディア「Publickey」( http://www.publickey1.jp/ )運営者。IT系の雑誌編集者、オンラインメディア発行人を経て独立。新しいオンラインメディアの可能性を追求。