Android の Linux カーネル保護の強化
2016年8月17日水曜日
[この記事は Jeff Vander Stoep、Android セキュリティ チームによる Android Developers Blog の記事 "Protecting Android with more Linux kernel defenses" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]
Android はセキュリティ モデルを強制するために Linux カーネルを活用しており、カーネルの保護を強化するためにさまざまな仕組みが導入されています。大まかに、このような保護はメモリの保護と攻撃対象領域の削減という 2 つのカテゴリに分けることができます。
perf へのアクセスをブロックするパッチセットは、カーネル部とユーザー空間部に分けて考えた方がよいかもしれません。カーネルパッチは Ben Hutchings 氏によるもので、Brad Spengler 氏による Grsecurity の CONFIG_GRKERNSEC_PERF_HARDEN から派生しています。ユーザー空間の変更は、Daniel Micay 氏によるものです。perf のセキュリティ脆弱性を責任を持って開示してくださった Wish Wu 氏をはじめとする方々にお礼を申し上げます。
Android で報告されているカーネル脆弱性の大半は、ドライバで ioctl システムコールを使用することによって起きています。その例が、CVE-2016-0820 などです。サードパーティ アプリケーションの中には、いくつかの ioctl コマンドが必要なものもありますが、ほとんどのアプリケーションはそうではなく、ioctl コマンドへのアクセスは正規の機能を損なわずに制限できます。Android Nougat では、アプリケーションが利用できるのはごくわずかなソケット ioctl コマンドのホワイトリストのみとなっています。一部の端末では、アプリケーションからの GPU ioctl へのアクセスも同様に制限されています。
このような作業によって、カーネルのセキュリティはますます強化されていきます。いつものように、作業に対するフィードバックや Android の改善提案は大歓迎です。security@android.com までご連絡ください。
Posted by Yuichi Araki - Developer Relations Team
Android はセキュリティ モデルを強制するために Linux カーネルを活用しており、カーネルの保護を強化するためにさまざまな仕組みが導入されています。大まかに、このような保護はメモリの保護と攻撃対象領域の削減という 2 つのカテゴリに分けることができます。
メモリの保護
カーネルが提供する主要なセキュリティ機能の 1 つが、アドレス空間を独立させることによって、ユーザー空間で動作するプロセスのメモリを保護する仕組みです。ユーザー空間のプロセスとは異なり、さまざまなカーネルのタスクは 1 つのアドレス空間の中に存在しています。そのため、カーネル内に脆弱性があると、システムメモリの別の部分にも影響する可能性があります。カーネルメモリ保護は、脆弱性があったとしてもカーネルの整合性が維持されるように設計されています。メモリを読み取り専用/実行不可とマークする
この機能によって、カーネルメモリを論理的なセクションに分割し、それぞれのセクションに制限付きのページアクセス権限を設定できます。コードが格納されたメモリは、読み取り専用 + 実行とマークされます。データ セクションは実行不可とマークされ、さらに読み取り専用のセクションと読み書き可能なセクションに分割されます。この機能は、CONFIG_DEBUG_RODATA 設定オプションで有効になります。これは Kees Cook 氏がまとめたもので、Brad Spengler 氏による Grsecurity の KERNEXEC 機能と、Larry Bassel 氏と Laura Abbott 氏による Qualcomm の CONFIG_STRICT_MEMORY_RWX 機能のサブセットが基になっています。CONFIG_DEBUG_RODATA は、arm/arm64 のアップストリーム カーネルに追加され、Android の 3.18+ arm/arm64 標準カーネルに移植されています。ユーザー空間へのカーネル アクセスの制限
この機能は、ユーザー空間のメモリへの直接アクセスを禁じることによって、カーネルの保護を強化します。これによって、攻撃者が実行可能な カーネル メモリを制御するのが大幅に難しくなり、さまざまな攻撃を行いにくくなります。特に CONFIG_DEBUG_RODATA が有効になっている場合はそれが該当します。これと同様の機能は既に存在しています。最も早く登場したのは、Grsecurity の UDEREF です。この機能は、Russell King 氏が ARMv7 用に実装した設定オプション CONFIG_CPU_SW_DOMAIN_PAN で有効になり、Kees Cook 氏によって Android の 4.1 カーネルに移植されました。スタック バッファのオーバーフローに対する保護の強化
stack-protector-strong は、前身である stack-protector と同じように、スタック バッファのオーバーフローからの保護を行います。stack-protector では文字配列のみが保護されていたのに対し、多くの配列型の保護が提供されるようになっています。stack-protector-strong は Han Shan 氏が実装し、gcc 4.9 コンパイラーに追加されました。攻撃対象領域の削減
攻撃対象領域の削減は、正規の機能を損なうことなく、公開するカーネルへのエントリ ポイントを減らす試みです。攻撃対象領域の削減には、コードの削除、エントリ ポイントへのアクセスの削除、公開する機能の限定などが含まれます。デバッグ機能へのデフォルト アクセスの削除
カーネルの perf システムはパフォーマンス測定の基盤となっており、カーネルとユーザー空間アプリケーションの両方を解析することができます。perf はデベロッパーにとっては貴重なツールですが、大半の Android ユーザーにとっては、不要な攻撃対象領域を増やすものです。Android Nougat では、デフォルトで perf へのアクセスがブロックされます。デベロッパーは、デベロッパー設定を有効にし、adb を使用して "adb shell setprop security.perf_harden 0" プロパティを設定することによって、perf にアクセスすることができます。perf へのアクセスをブロックするパッチセットは、カーネル部とユーザー空間部に分けて考えた方がよいかもしれません。カーネルパッチは Ben Hutchings 氏によるもので、Brad Spengler 氏による Grsecurity の CONFIG_GRKERNSEC_PERF_HARDEN から派生しています。ユーザー空間の変更は、Daniel Micay 氏によるものです。perf のセキュリティ脆弱性を責任を持って開示してくださった Wish Wu 氏をはじめとする方々にお礼を申し上げます。
アプリからの ioctl コマンドへのアクセスの制限
Android セキュリティ モデルの多くは、SELinux によって記述、強制されるものです。ioctl() システムコールには、SELinux によって強制される粒度との間に大きなギャップがあります。ioctl システムコールにコマンドごとの制御を提供する手段として、SELinux における ioctl コマンドのホワイトリスト登録が追加されました。Android で報告されているカーネル脆弱性の大半は、ドライバで ioctl システムコールを使用することによって起きています。その例が、CVE-2016-0820 などです。サードパーティ アプリケーションの中には、いくつかの ioctl コマンドが必要なものもありますが、ほとんどのアプリケーションはそうではなく、ioctl コマンドへのアクセスは正規の機能を損なわずに制限できます。Android Nougat では、アプリケーションが利用できるのはごくわずかなソケット ioctl コマンドのホワイトリストのみとなっています。一部の端末では、アプリケーションからの GPU ioctl へのアクセスも同様に制限されています。
seccomp-bpf の強制
seccomp は、追加のサンドボックス化メカニズムを提供しています。これにより、プロセスは設定変更可能なフィルタを使って、利用できるシステムコールやシステムコールの引数を制限できるようになります。システムコールの利用が制限されることによって、公開されるカーネルの攻撃対象領域は劇的に減少します。Lollipop 搭載の Nexus 端末に seccomp が初めて導入されてから、Android エコシステム全体での seccomp の導入率は着実に増加しています。Android Nougat では、seccomp のサポートは全端末で必須となります。Android Nougat では、メディアのセキュリティ強化の一環として、メディア抽出やメディアコーデックの処理で seccomp を使用しています。進行中の作業
他にもカーネル保護を目的としたプロジェクトが進行中です。- Kernel Self Protection Project では、アップストリーム カーネルのランタイムやコンパイラを保護する仕組みが開発されています。
- AOSP では、SELinux によるさらなるサンドボックスの強化と攻撃対象領域の削減が進行中です。
- Minijail では、seccomp フィルタや名前空間など、カーネルが提供する多くの封じ込め機能やサンドボックス機能を便利に適用するための仕組みが提供されています。
- kasan や kcov などのプロジェクトは、ファジング ツールを使ったクラッシュの根本原因追求や、コードのカバレッジを増やすテストケースのスマートな作成を通して、究極的にバグ対応プロセスを効率化することを目指しています。
このような作業によって、カーネルのセキュリティはますます強化されていきます。いつものように、作業に対するフィードバックや Android の改善提案は大歓迎です。security@android.com までご連絡ください。
Posted by Yuichi Araki - Developer Relations Team