TOMOYO Linux on Android
このページでは、 TOMOYO Linux を arm 用 Android エミュレータ上で動作させる手順について説明します。ホスト環境として x86_64 上で動作している Ubuntu 10.04.3 を使用します。
ステップ1:必要なパッケージのインストール
https://source.android.com/source/download.html に示されているとおり、必要なパッケージをインストールします。
sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner" sudo add-apt-repository "deb-src http://archive.canonical.com/ubuntu lucid partner" sudo apt-get update sudo apt-get install sun-java6-jdk sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev \ lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev \ libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils xsltproc
ステップ2:環境変数の設定
以下の内容を環境変数として指定します。 ~/.bashrc などに追加しておくことをお勧めします。
export ANDROID_HOME=$HOME/mydroid/ export ANDROID_IMG=$ANDROID_HOME/image/
必要なディレクトリを作成します。
mkdir -p $ANDROID_HOME mkdir -p $ANDROID_HOME/tmp mkdir -p $ANDROID_HOME/tmp/policy mkdir -p $ANDROID_IMG mkdir -p $ANDROID_IMG/tmp sudo mkdir -p /var/log/tomoyo sudo chown -R `id -u` /var/log/tomoyo/
ステップ3: Android 環境の構築
エミュレータをコンパイルします。
cd $ANDROID_HOME wget https://dl-ssl.google.com/dl/googlesource/git-repo/repo chmod 755 repo ./repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1 ./repo sync source build/envsetup.sh lunch full-eng make
ステップ4:ホスト環境用ツールのインストール
Android エミュレータを遠隔操作するために、ホスト側に TOMOYO Linux のツールをインストールします。
cd $ANDROID_HOME/tmp/ wget https://sourceforge.net/projects/tomoyo/files/tomoyo-tools/2.5/tomoyo-tools-2.5.0-20170102.tar.gz wget https://sourceforge.net/projects/tomoyo/files/tomoyo-tools/2.5/tomoyo-tools-2.5.0-20170102.tar.gz.asc wget https://tomoyo.sourceforge.net/kumaneko-key gpg --import kumaneko-key gpg tomoyo-tools-2.5.0-20170102.tar.gz.asc tar -zxf tomoyo-tools-2.5.0-20170102.tar.gz cd tomoyo-tools make sudo make install
また、ポリシーをチューニングするためのツールを使うので、そのための準備を行います。
sudo /usr/lib/tomoyo/init_policy sudo chown -R `id -u` /etc/tomoyo/ echo 'rewrite head_pattern /acct/uid/\$/' >> /etc/tomoyo/tools/patternize.conf
ステップ5:エミュレータ環境用ツールのインストール
Android エミュレータ側にインストールするためのエージェントをコンパイルします。
cd $ANDROID_HOME/tmp/ wget -O agcc https://plausible.org/andy/agcc sed -i -e 's@4\.2\.1@4.4.3@g' -e 's@interwork/@@g' -- agcc chmod 755 agcc ./agcc -o tomoyo-editpolicy-agent $ANDROID_HOME/tmp/tomoyo-tools/usr_lib_tomoyo/tomoyo-editpolicy-agent.c chmod 700 tomoyo-editpolicy-agent
ステップ6:初期ポリシーの作成
カーネル内に埋め込んでおくためのポリシーを作成します。
- 全てのドメインを学習モードに設定する。
- 予めある程度のアクセス許可を与えておく
- ポリシーを変更できるのは /sbin/tomoyo-editpolicy-agent のみとする
という設定での例を示します。
cd $ANDROID_HOME/tmp/policy/ cat > profile.conf << "EOF" PROFILE_VERSION=20100903 0-COMMENT=-----Disabled Mode----- 0-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 } 0-CONFIG={ mode=disabled grant_log=no reject_log=yes } 1-COMMENT=-----Learning Mode----- 1-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 } 1-CONFIG={ mode=learning grant_log=no reject_log=yes } 2-COMMENT=-----Permissive Mode----- 2-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 } 2-CONFIG={ mode=permissive grant_log=no reject_log=yes } 3-COMMENT=-----Enforcing Mode----- 3-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 } 3-CONFIG={ mode=enforcing grant_log=no reject_log=yes } EOF cat > exception_policy.conf << "EOF" path_group ANY_PATHNAME / path_group ANY_PATHNAME /\{\*\}/ path_group ANY_PATHNAME /\{\*\}/\* path_group ANY_PATHNAME /\* path_group ANY_PATHNAME \*:/ path_group ANY_PATHNAME \*:/\{\*\}/ path_group ANY_PATHNAME \*:/\{\*\}/\* path_group ANY_PATHNAME \*:/\* path_group ANY_PATHNAME \*:[\$] path_group ANY_PATHNAME socket:[family=\$:type=\$:protocol=\$] acl_group 0 file getattr @ANY_PATHNAME acl_group 0 file ioctl @ANY_PATHNAME 0-0xFFFFFFFF acl_group 0 file read /dev/urandom acl_group 0 file read /system/bin/linker acl_group 0 file read /system/lib/lib\*.so acl_group 0 misc env _ acl_group 0 misc env ANDROID_ASSETS acl_group 0 misc env ANDROID_BOOTLOGO acl_group 0 misc env ANDROID_DATA acl_group 0 misc env ANDROID_DNS_MODE acl_group 0 misc env ANDROID_PROPERTY_WORKSPACE acl_group 0 misc env ANDROID_ROOT acl_group 0 misc env ANDROID_SOCKET_\* acl_group 0 misc env ASEC_MOUNTPOINT acl_group 0 misc env BOOTCLASSPATH acl_group 0 misc env EXTERNAL_STORAGE acl_group 0 misc env HOME acl_group 0 misc env LD_LIBRARY_PATH acl_group 0 misc env LOOP_MOUNTPOINT acl_group 0 misc env ndns acl_group 0 misc env PATH acl_group 0 misc env qemu acl_group 0 misc env RANDOM acl_group 0 misc env SHELL acl_group 0 misc env TERM EOF cat > domain_policy.conf << "EOF" <kernel> use_profile 1 use_group 0 EOF echo /sbin/tomoyo-editpolicy-agent > manager.conf echo > stat.conf
ステップ7: Android 用カーネルの構築
Linux 2.6.33 以降のカーネルのソースコードをダウンロードして展開して、そのディレクトリへと移動します。以後、そのディレクトリを $ANDROID_HOME/tmp/common/ と表記します。
cd $ANDROID_HOME/tmp/common/
次に、もし Linux 2.6.33 ~ 3.3 を使うのであれば、 Linux 3.4 をダウンロードして、 security/tomoyo/ ディレクトリだけを展開して上書きします。
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.4.tar.bz2 tar -jxf linux-3.4.tar.bz2 --strip 1 linux-3.4/security/tomoyo/
次に、もし Linux 2.6.33 ~ 3.2 を使うのであれば、 https://tomoyo.sourceforge.net/2.5/patches/ からバックポートパッチをダウンロードして適用します。
その後、デフォルトのカーネルコンフィグを作成します。
ARCH=arm CROSS_COMPILE=$ANDROID_EABI_TOOLCHAIN/arm-linux-androideabi- make -s goldfish_armv7_defconfig
TOMOYO Linux を有効にします。
cd $ANDROID_HOME/tmp/common/ sed -i -e 's/# CONFIG_SECURITY_TOMOYO is not set/CONFIG_SECURITY_TOMOYO=y/' -e 's/# CONFIG_DEFAULT_SECURITY_TOMOYO is not set/CONFIG_DEFAULT_SECURITY_TOMOYO=y/' -- .config sed -i -e 's/# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set/CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER=y/' -- .config mkdir -p security/tomoyo/policy/ cp -p $ANDROID_HOME/tmp/policy/*.conf security/tomoyo/policy/
カーネルをコンパイルします。
cd $ANDROID_HOME/tmp/common/ ARCH=arm CROSS_COMPILE=$ANDROID_EABI_TOOLCHAIN/arm-linux-androideabi- make -s cp -p arch/arm/boot/zImage $ANDROID_IMG/kernel.img
ステップ8:イメージファイルのコピー
Android エミュレータで指定するためのイメージファイルをコピーします。
cd $ANDROID_HOME/out/target/product/generic/ cp -p system.img ramdisk.img userdata.img $ANDROID_IMG
ステップ9:RAMディスクの編集
Android エミュレータで使用するRAMディスクにエージェントをコピーし、自動的に起動されるようにします。
cd $ANDROID_IMG/tmp/ zcat ../ramdisk.img | cpio -id echo >> init.rc echo 'service tomoyo_agent /sbin/tomoyo-editpolicy-agent 0.0.0.0:7000' >> init.rc echo ' class core' >> init.rc echo ' oneshot' >> init.rc cp -p $ANDROID_HOME/tmp/tomoyo-editpolicy-agent sbin/ find . -print0 | cpio -o0 -H newc | gzip -9 > ../ramdisk.img
ステップ10:エミュレータの起動
Android エミュレータを起動します。カーネルはステップ7で作成したものを、RAMディスクはステップ9で作成したものを指定します。
emulator -kernel $ANDROID_IMG/kernel.img -ramdisk $ANDROID_IMG/ramdisk.img -sysdir $ANDROID_IMG \ -data $ANDROID_IMG/userdata.img -show-kernel
ステップ11:ポート転送の指定
エミュレータ内で動作しているエージェントと通信するために、ポート転送を指定します。以下のように指定した場合、ホスト側でのポート 10000 への TCP 接続は、エミュレータ側でのポート 7000 へと転送されます。ステップ9で tomoyo-editpolicy-agent をポート 7000 で待機するように指定しているので、ホスト側でポート 10000 へ接続することにより、エージェントとの通信が可能になります。
adb forward tcp:10000 tcp:7000
ステップ12:エージェント経由での操作
以下のように tomoyo-editpolicy を起動すると、エミュレータ内のエージェント経由で ポリシーを閲覧/編集できます。
/usr/sbin/tomoyo-editpolicy 127.0.0.1:10000
以下のように tomoyo-auditd を起動すると、エミュレータ内のエージェント経由でアクセス許可ログ/拒否ログを取得して保存することができます。なお、アクセスログは大量に出力されるため、ディスクの空き容量に注意してください。
/usr/sbin/tomoyo-auditd 127.0.0.1:10000
以下のように tomoyo-queryd を実行すると、エミュレータ内のエージェント経由で、強制モードでのポリシー違反を対話的に処理できます。 tomoyo-queryd を終了させるには Ctrl-C を押してください。
/usr/sbin/tomoyo-queryd 127.0.0.1:10000
ワイルドカード化を行うには以下のようにしてください。ワイルドカード化のルールは /etc/tomoyo/tools/patternize.conf で定義されているので、適宜編集してください。
cd $ANDROID_HOME/tmp/policy/ /usr/sbin/tomoyo-savepolicy -d 127.0.0.1:10000 > domain_policy.old /usr/sbin/tomoyo-patternize < domain_policy.old > domain_policy.new /usr/sbin/tomoyo-diffpolicy domain_policy.old domain_policy.new > domain_policy.diff less domain_policy.diff /usr/sbin/tomoyo-loadpolicy -d 127.0.0.1:10000 < domain_policy.diff
ステップ13:ポリシーのアップデート
ポリシーはメモリ上にのみ存在しているため、エミュレータを終了すると失われてしまいます。エミュレータを終了する前に忘れずにポリシーを保存するようにしてください。
cd $ANDROID_HOME/tmp/policy/ /usr/sbin/tomoyo-savepolicy -e 127.0.0.1:10000 > exception_policy.conf /usr/sbin/tomoyo-savepolicy -d 127.0.0.1:10000 > domain_policy.conf /usr/sbin/tomoyo-savepolicy -p 127.0.0.1:10000 > profile.conf
また、保存したポリシーをカーネル内に埋め込むには以下のように行ってください。
cp -p $ANDROID_HOME/tmp/policy/*.conf $ANDROID_HOME/tmp/common/security/tomoyo/policy/
カーネルを再コンパイルします。
cd $ANDROID_HOME/tmp/common/ ARCH=arm CROSS_COMPILE=$ANDROID_EABI_TOOLCHAIN/arm-linux-androideabi- make -s cp -p arch/arm/boot/zImage $ANDROID_IMG/kernel.img
再度エミュレータを実行します。
emulator -kernel $ANDROID_IMG/kernel.img -ramdisk $ANDROID_IMG/ramdisk.img -sysdir $ANDROID_IMG \ -data $ANDROID_IMG/userdata.img -show-kernel
最終的なポリシーが完成したら、カーネル内に埋め込まれている domain_policy.conf に enforcing mode 用のプロファイルを割り当てておく( use_profile 3 )ことにより、 /init が実行される時点からアクセス制御を有効にすることができます。その状態で正常に動作することを確認したら、ステップ9で追加した /sbin/tomoyo-editpolicy-agent を削除します。また、 /init.rc およびカーネル内に埋め込まれた profile.conf からも tomoyo-editpolicy-agent を削除します。
補足:ポリシーの更新を認めたい場合のヒント
Android ではユーザがアプリケーションを追加することができます。そのため、追加されるアプリケーションによっては、ポリシーを更新したい場合があるかもしれません。そのような場合、起動時に必要になるポリシーとしてカーネル内に埋め込む固定分と、起動後に必要になるポリシーとしてカーネル内には埋め込まない変動分とを分離することで対処するという方法が考えられます。
起動時に必要となるポリシーはカーネルを読み込み専用のパーティションに配置することで、改ざんされる可能性を減らすことができます。起動後に必要になるポリシーは読み書きが可能なパーティションに配置することになるので改ざんされる可能性が高くなります。そのため、例えば GPG で署名し、改ざんされていないことを確認できた場合にのみポリシーを追加読み込みするという方法が考えられます。
TOMOYO Linux では強制モードにおけるポリシー違反を契機として外部のプログラムに問い合わせを行うことができます。 tomoyo-queryd 相当の処理を実装し、 tomoyo-editpolicy-agent の代わりに常駐させておくという方法を利用できます。
補足:ポリシーをカーネル内に埋め込みたくない場合のヒント
何かの理由によりポリシーをカーネル内に埋め込みたくない場合、ステップ7の
sed -i -e 's/# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set/CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER=y/' -- .config mkdir -p security/tomoyo/policy/ cp -p $ANDROID_HOME/tmp/policy/*.conf security/tomoyo/policy/
という部分を
sed -i -e 's@CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init"@CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/init"@' -- .config
に置き換えてください。このようにした場合、ポリシーローダとして /sbin/tomoyo-init (および /sbin/tomoyo-init が依存するファイルとして /system/bin/linker /system/lib/libc.so /system/lib/libm.so )もRAMディスク内にコピーしてください。 /sbin/tomoyo-init が実行される時点では /system/ パーティションがマウントされていないため、シンボリックリンクでの代用はできません。また、 tomoyo-init.c はポリシーを /etc/tomoyo/ から読み込むようになっていますので、適宜修正(例えば $ANDROID_HOME/tmp/policy/*.conf の内容を tomoyo-init.c に埋め込んでしまうなど)してください。 Android エミュレータで使用するRAMディスクに含まれている /init.rc が /etc という名前で /system/etc/ ディレクトリへのシンボリックリンクを作成するため、以下の例では、ポリシーを /tomoyo/ ディレクトリから読み込むように修正しています。
cd $ANDROID_HOME/tmp/ sed -e 's:etc/tomoyo:tomoyo:g' $ANDROID_HOME/tmp/tomoyo-tools/sbin/tomoyo-init.c > $ANDROID_HOME/tmp/tomoyo-tools/sbin/tomoyo-init2.c ./agcc -o tomoyo-init $ANDROID_HOME/tmp/tomoyo-tools/sbin/tomoyo-init2.c cd $ANDROID_IMG/tmp/ mkdir -p sbin system/bin system/lib cp -p $ANDROID_HOME/tmp/tomoyo-init sbin/ cp -p $ANDROID_HOME/out/target/product/generic/system/bin/linker system/bin/ cp -p $ANDROID_HOME/out/target/product/generic/system/lib/libc.so system/lib/ cp -p $ANDROID_HOME/out/target/product/generic/system/lib/libm.so system/lib/ chmod 700 sbin/tomoyo-init system/bin/linker system/lib/libc.so system/lib/libm.so find . -print0 | cpio -o0 -H newc | gzip -9 > ../ramdisk.img