Chrome OS 上で動作している Android に SuperSu をインストールしてみる

#　はじめに
　ご承知のように、現在（2017/01/01）いくつかのChromeBookではAndroidが稼働しており、これによりChromeOSアプリだけでなくAndroidアプリが実行可能です。私が所持しているAsus Flipもそうした機種の一つであり、これにより活用の幅が随分広がったと言えます。
 　さて、このAndroidなのですが、ディベロッパーモード上では、sudo android-sh で、ターミナルからいきなりroot権限を持ったAndoid Shell に入ることができます。ADBで接続してみたらroot権限が取得できている、というような状態です。しかしもちろん、Andoidアプリ側からは、SuperSuが存在しないので、root権限は取得できません。
　そして、こうなるとSuperSuを放り込んで、アプリ側からもroot権限を取得できるようにしたい、と考えるのが人情というものです。
　で、やってみました。
 
　まず、android-shで単純にSuperSuを放り込むだけでいいように思うのは、間違いです。
　そもそも、単純には放り込めない。無理に放り込んでも、正常には認識してもらえない。仮に認識させることができても、再起動すると消えてしまう。
　理由は、以下です。
 
 - ChromeOS のシステム領域がデフォルトでは書き込み禁止に設定されいる。
 - ChromeOS、Android6 とも Selinux が動作している。
 - ChromeOS の Android は、ChromeOS のイメージファイルとして提供されている。
 
　上記をふまえてSuperSUを放り込むのは、結構な長手順を要します。
　しかしながら、スマホで稼働しているAndroidをroot化するよりは、はるかに安全に、かつ失敗しても一瞬で作業をリセット可能です。nandの書込に失敗して文鎮化する心配もありませんし、ストックROMを入手せずに決行して元に戻せなくなり、OSバージョンアップが不可能になったりもしません。
　以下の作業は、要するにイメージファイルのコピーを作成して、そのコピーを改変し、システム設定を変更して、改変側のイメージファイルをAndroidシステムとして起動させる、という一連の手順です。オリジナルはそのまま残しておくので、何か都合の悪いことがあれば元に付け替えれば済むのです。
 
　なおこの実験は、Asus Flip でのみ動作確認しております。
　というか、私が日常実際に使っている環境を書いているだけです。
　root権限を使うアプリで実際に長期間インストールして使っているのは、Adaway, xploreの２つだけです。これらは、問題なく使えています。その他一時的にインストールして稼働テストしたものも、すべて正常動作しました。
　ただし、xposed系は正常動作しない可能性が大きい、と私は考えております。私は、xposedは使う予定がありませんので、直接確認しませんが、たぶん正常動作させるのは簡単だが、めんどうだと思います。
　安全に使うには、SuperSUと同様に、あらかじめ手動でイメージファイルの中に書き込んでおく必要があると思います。加えて、使いたい拡張モジュールもxposedのインストーラーに任せず、手動インストールしたほう安全だと思います。でも、使いたい方はやってみてくださいね。失敗しても気にしない。元に戻せば済みますので。何度でもトライしてください。
# 準備
　何かと便利なので、一応入れておく。
```
wget -q -O - https://raw.github.com/jam7/chromebrew/master/install.sh | bash
```

　SuperSUの準備
```
wget https://download.chainfire.eu/1016/SuperSU/UPDATE-SuperSU-v2.79-20161211114519.zip
```
　arm7, commonのディレクトリだけ取り出しておく。
# ルートファイルシステム書込禁止を解除
```
 /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification
```
# カスタムな実行イメージファイル（ SuperSu 仕込み済)を作成
空のブートイメージファイルの作成
```
cd /usr/local/
mkdir AndImg
cd AndImg
dd if=/dev/zero of=system.raw.expanded.img count=860000 bs=1024 status=progress
mkfs ext3 -F system.raw.expanded.img
```
空のブートイメージファイルをループバックマウント
```
mkdir -p MyImg
mount -o loop,rw,sync system.raw.expanded.img MyImg
```
オリジナル android イメージファイルをループバックマウント
```
mkdir OrgImg
mount -o loop,rw,sync /opt/google/containers/android/system.raw.img OrgImg
```
オリジナル android イメージを空のブートイメージに全コピー
```
setenforce 0
cp -a -r OrgImg/* MyImg
umount OrgImg
rm -r Orgimg
```
コピーしたブートイメージの改造開始
```
ARCH=/home/chronos/user/Downloads/armv7
common=/home/chronos/user/Downloads/common
system=/usr/local/AndImg/MyImg/system
```
SuperSU.apk を android の /system/app/SuperSU ディレクトリにインストール
```
mkdir $system/app/SuperSU
cp $common/Superuser.apk $system/app/SuperSU/SuperSU.apk
chmod 0644 $system/app/SuperSU/SuperSU.apk
chcon u:object_r:system_file:s0 $system/app/SuperSU/SuperSU.apk
```
android /system/xbin, /system/bin, /system/bin/.ext, /system/lib に SuperSU の各配布ファイルをコピー
```
cd $system/xbin/
cp $ARCH/su su
cp $ARCH/su daemonsu
cp $ARCH/su sugote
chmod 0755 su
chmod 0755 daemonsu
chmod 0755 sugote
chcon u:object_r:system_file:s0 su
chcon u:object_r:system_file:s0 daemonsu
chcon u:object_r:zygote_exec:s0 sugote
``` ```
cd $system/bin
mkdir .ext/
cd .ext
cp $ARCH/su .su
chmod 0755 .su
chcon u:object_r:system_file:s0 .su
``` ```
cd $system/xbin/
cp $ARCH/supolicy supolicy
chmod 0755 supolicy
chcon u:object_r:system_file:s0 supolicy
``` ```
cd $system/lib/
cp $ARCH/libsupol.so libsupol.so
chmod 0644 libsupol.so
chcon u:object_r:system_file:s0 libsupol.so
``` ```
cd $system/xbin/
cp ../bin/sh sugote-mksh
chmod 0755 sugote-mksh
chcon u:object_r:system_file:s0 sugote-mksh
```
app_process, app_process32 の改造
```
cd $system/bin
cp app_process32 app_process32_org
chmod 0755 app_process32_org
chcon u:object_r:zygote_exec:s0 app_process32_org
cp app_process32 app_process_init
chmod 0755 app_process_init
chcon u:object_r:system_file:s0 app_process_init
rm app_process
rm app_process32
cd $system/xbin/
ln -s -r daemonsu ../bin/app_process
ln -s -r daemonsu ../bin/app_process32
```
/system/etc/ に .installed_su_daemon 作成
```
cd $system/etc
touch .installed_su_daemon
chmod 0644 .installed_su_daemon
chcon u:object_r:system_file:s0 .installed_su_daemon
```
/system/etc/ に SuperSU 配布ファイルから install-recovery.sh をコピー
```
cp $common/install-recovery.sh install-recovery.sh
chmod 0755 install-recovery.sh
chcon u:object_r:toolbox_exec:s0 install-recovery.sh
ln -s -r install-recovery.sh ../bin/install-recovery.sh
```
# chrome OS 側の変更
arc-system-mount.conf の変更とバックアップ
```
cd /usr/local/
mkdir Backup
cp -a /etc/init/arc-system-mount.conf /usr/local/Backup/arc-system-mount.conf.old
cp -a /etc/init/arc-system-mount.conf /etc/init/arc-system-mount.conf.old
sed -i 's/env WRITABLE_MOUNT=0/env WRITABLE_MOUNT=1/g' /etc/init/arc-system-mount.conf
sed -i 's+SYSTEM_IMAGE=/opt/google/containers/android/system.raw.img+SYSTEM_IMAGE=/usr/local/AndImg/system.raw.expanded.img+g' /etc/init/arc-system-mount.conf
```
arc-ureadahead.conf の変更とバックアップ
```
cp -a /etc/init/arc-ureadahead.conf /usr/local/Backup/arc-ureadahead.conf.old
cp -a /etc/init/arc-ureadahead.conf /etc/init/arc-ureadahead.conf.old
sed -i 's+SYSTEM_IMAGE=/opt/google/containers/android/system.raw.img+SYSTEM_IMAGE=/usr/local/AndImg/system.raw.expanded.img+g' /etc/init/arc-ureadahead.conf
```
android-ureadahead.conf の変更とバックアップ
```
cp -a /etc/init/android-ureadahead.conf /usr/local/Backup/android-ureadahead.conf.old
cp -a /etc/init/android-ureadahead.conf /etc/init/android-ureadahead.conf.old
sed -i 's+SYSTEM_IMAGE=/opt/google/containers/android/system.raw.img+SYSTEM_IMAGE=/usr/local/AndImg/system.raw.expanded.img+g' /etc/init/android-ureadahead.conf
```
　何をやっているかというと、Androidの起動に改造イメージを使うように、かつその改造イメージシステムは書込可能状態で起動するよう、ということです。
# システムリブート
　これで、第一段階の仕込み終了。ChromeOSを一旦リブートする。
# 最後に、SeLinuxの設定を変更
```
cp /etc/selinux/arc/policy/policy.30 /etc/selinux/arc/policy/policy.30.old
cp /etc/selinux/arc/policy/policy.30 /usr/local/Backup/policy.30.old
cp -a /etc/selinux/arc/policy/policy.30 /home/chronos/user/Downloads/policy.30
setenforce 0

```
次は、android-shで実行
```
su -c "supolicy --file /sdcard/Download/policy.30 /sdcard/Download/policy.30_out
su -c "chmod 0644 /sdcard/Download/policy.30_out
exit
```
ChromeOS側で、実行
```
cp -a /home/chronos/user/Downloads/policy.30_out /etc/selinux/arc/policy/policy.30
```
　全体のセキュリティーが低下しますので、気になる方はこの実験をやめたほうがいいでしょう。
# システムリブート
　これで、終了。もう一度ChromeOSをリブートする。
　リブートしたら、Android上でrootチェッカーアプリ等で確認する。
　疲れますね、ちょっと面倒です。

　さて、この状態でChromeOSがアップデートされたとき、Android側がどうなるかは、わかりません。アップデートする前に、元に戻しておいたほうがいいかもしれません。Androidだけが、いつまでも古い改造イメージで起動されるかもしれませんので。

　なお、イメージファイルの改変時には、何もSuperSUの仕込みだけでなく、Androidの初期化プロセスに追加のアクションを設定してみるのもおもしろいと思います。たとえば、ダウンロードフォルダーに置かれた特定のスクリプトを、立ち上げ時にrc.localのように実行するとか。これにより一般ユーザ権限で、かなりのことができるはずです。手動のxposedといったところでしょうか。昔、シャープのスマホを持っていた頃、これをやっていてとても便利でした。
　折角、root権限付きのshellが使え、比較的安全にAndoroid OSのイメージファイルをコピーしていじれるのですから、いろいろ遊んでみたら楽しいと思います。
　最後に、変なことをしてChromeOSごと立ち上がらなくなっても、私は知りませんから。理解できる範囲で、各自遊びましょう。