カーネルコマンドラインを使わずにSELinuxを静かにする方法

20:00
SELinuxはデバイスのセキュリティを強固にするには有用ですが、アクセスの許可/拒否ルールを正しく設定しないと起動の段階でinitプロセスが延々とループするなど問題も多いです。

Android 4.3

Android 4.3でSELinuxが導入された時は、デフォルトでPermissiveで動作するようになっていたので、アクセスルールがおかしくてもログが氾濫するだけで実害はありませんでした。

Android 4.4

Android 4.4では動作モードがEnforcingに変更され、単にアクセスログを取るだけではなく、実際にアクセスを制限するようになったので、ルール設定がおかしいと動作しない機能が出るようになりました。

例えば、Xperia GX用のCM11やCM12.1でベースバンドが読めなくなるのは、rmt_storageに正しいアクセスルールが設定されていないため、modemst1パーティションなどのバンド情報を取得できないために起こります。

もっとも、Android 4.4の段階では多くのプロセスがunconfinedドメインに指定されていたので、多少設定が不正だとしても致命的なエラーは出ないようになっていました。

*1 unconfinedドメインとは、SELinuxによって制限されないドメインのことで、全てのアクセスを許可するように設定されています。

*2 SELinuxの動作モードとは別に、permissiveドメインという、動作モードに関わらずログ出力だけされる設定もあります。

Android 5.0

ところが、Android 5.0から、unconfinedドメインの指定が狭まり、今までは見逃されていたプロセスもアクセス制御を受けるようになりました。
また、アクセスポリシーを管理するsepolicyのソースにも変更が加えられ、permissiveドメインの設定で見逃されていたプロセスも、unconfinedかEnforcingかで厳密に管理されるようになりました。

ただし、この段階では、
android_external_sepolicy/Android.mkにFORCE_PERMISSIVE_TO_UNCONFINEDというフラグが設定されているので、これをfalseにすることで、Android 4.4までと同じ挙動にすることが出来ました。

*3 GXでも、このフラグをfalseにしなければ起動時にinitが延々とループすることになります。

Android 6.0

Android 6.0では、いよいよこのフラグも廃止され、完全なアクセスポリシーを定義する必要がでてきたので、SELinuxのポリシー設定に詳しくない一般開発者にとっては厳しい状況になりました。

SELinuxを静かにするには

通常は、起動時にSELinuxをPermissiveモードにするためにカーネルコマンドラインという、カーネルからAndroidのinitプロセスに渡されるパラメーターでPermissiveを指定することで回避できますが、ブートローダーがロックされていて、任意のカーネルコマンドラインを指定できないGXではこの方法が使えません。

*4 カーネルコマンドラインはデバイスソースのBoardConfig.mkで、
BOARD_KERNEL_CMDLINE  := androidboot.selinux=permissiveの形で指定できます。

仕方が無いので、カーネルコマンドラインを受け取って処理しているinitプロセスのソースまで遡って、SELinuxの初期化処理自体をしないように変更することにしました。

android_system_core/init/init.cppのmain関数内の処理をコメントアウトします。


    // Set up SELinux, including loading the SELinux policy if we're in the kernel domain.

    // selinux_initialize(is_first_stage);

こうすることで、SELinuxをそもそも有効にしない、Disabledの状態にして、ブートさせることが出来ました。

関連する記事

次の記事
« 前の投稿
前の記事
次の投稿 »