Linux-stable のマージ

アップストリームの Linux カーネルには、日々かなりの数の変更がコミットされています。こうした変更については通常、セキュリティ上の影響が評価されませんが、実際にはその多くがカーネルのセキュリティに影響する可能性があります。 それぞれの変更がセキュリティに及ぼす影響を評価することは、コストの点から現実的ではありません。これに対し、持続可能なアプローチになるのが、アップストリームの Linux カーネルと定期的に変更を同期する方法です。

新しい長期サポート(LTS)カーネルによってデバイスを定期的に更新することをおすすめします。定期的な LTS 更新により、2019 年初めの Project Zero レポートにあったような不明なセキュリティ上の脆弱性を、一般開示前に、または悪意のある攻撃者が発見する前に解決できます。

要件

  • Android 共通カーネル ブランチ(AOSP)
  • ターゲット デバイス カーネルの LTS マージ ステージング ブランチ
  • デバイス カーネルのリリース ブランチ
  • Git リポジトリ
  • カーネルビルド ツールチェーン

LTS 変更とマージする

LTS 変更のマージ
図 1: LTS 変更のマージ

LTS マージの一般的な手順の概要は以下のとおりです。

  • ターゲット カーネルのリリース ブランチを -LTS ステージング ブランチにバックマージします
  • Linux-stable または Android 共通カーネルを -LTS ステージング ブランチにローカルでマージします
  • マージ競合を解決します(必要に応じてエリア / コードの所有者に問い合わせる)
  • ローカルでビルドし、健全性テスト / 単体テストを実施します(以下のテスト セクションを参照)
  • Android 共通の変更をアップロードし、LTS ステージング ブランチにマージします
  • -LTS ステージング ブランチを使用して徹底的にテストします(以下のテスト セクションを参照)
  • テスト結果を確認します
  • 必要に応じて回帰、bisect マージを解決します
  • -LTS ステージング ブランチをメインのデバイス カーネルのリリース ブランチにマージします
  • デバイス用にステージング LTS カーネルを含む新しい Android ビルドを作成します
  • 新しいカーネルを使用して、リリースビルド / ROM をコンパイルします

LTS とのマージの例

android-4.9 を main に(LTS ステージング経由で)マージし、LTS ステージング ブランチをチェックアウトして同期します。

repo init -b <Device kernel LTS staging branch>  # init
repo sync
git checkout -b lts <Device kernel LTS staging branch>
git merge <Device kernel release branch>         # back-merge
git commit

ここで、ソースリモートにバックマージをプッシュしてから続行することをおすすめします。次に、Android 共通カーネルを LTS ステージングにマージします。

git merge -X patience android-4.9-q            # LTS merge

マージの競合を解決する

ほとんどの場合、Android 共通カーネルと -LTS ステージング ブランチ間で競合が発生します。LTS マージ中にマージの競合を解決することは困難です。その際に役立つヒントを以下に示します。

増分マージ

デバイス カーネルを LTS によって更新してからかなりの時間が経過している場合は、前回のマージ更新がアップストリームにリリースされて以降、多数(50 以上)の安定版リリースが公開されている可能性があります。これに対処するには、一度に少数のリリース(5 つ以下のマイナー バージョン)をマージしながら、そのたびにテストを実施していくことをおすすめします。

たとえば、デバイス カーネルのバージョンのサブレベルが 4.14.100 で、アップストリームの安定サブレベルが 4.14.155 である場合は、少しずつマージを進め、確認とテストを十分に行えるだけの変更を加えていくとよいでしょう。

一般的に、一度にマージして増やすマイナー リリースを 5 つまでにすれば、パッチを確実に管理できます。

テスト

クイックブート テスト

クイックブート テストを実行するには、先に LTS の変更をローカルでマージし、カーネルをビルドしておく必要があります。以下に、クイックブート テストの手順を示します。

ターゲット デバイスを USB ケーブルでパソコンに接続し、Android Debug Bridge(ADB)を使用して .ko をデバイスにプッシュします。

adb root
adb disable-verity
adb reboot
(wait for device boot-to-home)
adb root
adb remount
adb push *.ko vendor/lib/modules/
adb reboot bootloader

dtbo をブートし、カーネル イメージをサイドローディングします。

fastboot boot --header-version=2 Image.lz4 (redo again if device rebooted)

/dev/kmsg ログでエラーをチェックします。

adb shell
su
cat /dev/kmsg (inspect kernel log for obvious new errors)

Android テスト

まずローカルで、新しい LTS カーネルとモジュールを使用して -userdebug イメージをビルドします。

/dev/kmsg でエラーがないことをチェックして、次に進みます。以下の事項をテストして、動作に問題がないことを確認します。

  • Wi-Fi 速度
  • Chrome ブラウザ
  • カメラアプリによる画像と動画の撮影
  • 内蔵スピーカーと Bluetooth ヘッドセットを使用した YouTube 動画の再生
  • 携帯通信会社のネットワーク経由の通話
  • Wi-Fi 経由のビデオ通話

自動テストスイート

最後に、ベンダー テストスイート(VTS)から入手できるテストスイートと、自動安定ストレステストを使用して、商品画像の回帰がないことを確認します。