SlideShare a Scribd company logo
Android と SELinux
@androidsola
自己紹介
• twitter
@androidsola
• blog
http://blog.sola-dolphin-1.net/
• AndroidベースのカスタムROM(JCROM)を開発して
ます
https://sites.google.com/site/jcromproject/
※サーバ移行中なので一部リンク切れてます
SELinuxにはJCROMの開発で遭遇。
本日の内容
• SELinuxとは
• Platform開発者がやること
• 開発で遭遇したこと
SELinuxとは
SELinuxとは
• Linuxインストール時や直後によく無効化されるやつ
SELinuxとは(Wikipediaより)
• SELinux(Security-Enhanced Linux : エスイーリナッ
クス)は、アメリカ国家安全保障局がGPL下で提供し
ているLinuxのカーネルに強制アクセス制御(MAC)機
能を付加するモジュールの名称。名前から勘違いされ
ることが多いが Linuxディストリビューションの一つ
ではない。
SELinuxとは
• SELinuxの効果
• SELinuxの特徴
SELinuxの効果
SELinuxを使用しない場合
Process A Linux Kernel
File A
File B
File C
-rw-r--r–- hoge hoge (省略)File A
-rw-r---–- hoge hoge (省略)File B
-rw------– hoge hoge (省略)File C
sola
solaは管理者権限を持たない一般ユーザ
hogeのグループには属していない
solaがProcess Aを実行してFile A, File B, File Cにアクセス(read)する例。
SELinuxを使用しない場合
Process A Linux Kernel
File A
File B
File C
-rw-r--r–- hoge hoge (省略)File A
-rw-r---–- hoge hoge (省略)File B
-rw------– hoge hoge (省略)File C
sola
solaは管理者権限を持たない一般ユーザ
hogeのグループには属していない
乗っ取られてProcess Aがroot権限を持ってしまった時は、
File A, File B, File C全てにアクセスされる。
乗っ取り
SELinuxを使用した場合
Process A
Linux Kernel
File A
File B
File C
-rw-r--r–- hoge hoge (省略)File A
-rw-r---–- hoge hoge (省略)File B
-rw------– hoge hoge (省略)File C
sola
solaは管理者権限を持たない一般ユーザ
hogeのグループには属していない
SELinuxを使用するとパーミッションによるアクセス制御の他に、
セキュリティポリシーによる制御が行われる。
SELinux
Security
policy
File B, File Cはrootで
あってもアクセス出来な
いようにSecurity policy
を定義する
SELinuxを使用した場合
Process A
Linux Kernel
File A
File B
File C
-rw-r--r–- hoge hoge (省略)File A
-rw-r---–- hoge hoge (省略)File B
-rw------– hoge hoge (省略)File C
sola
solaは管理者権限を持たない一般ユーザ
hogeのグループには属していない
乗っ取られてProcess Aがroot権限を持ってしまっても
Security policyの定義に従うので、File BやFile Cを守れる。
SELinux
Security
policy
File B, File Cはrootで
あってもアクセス出来な
いようにSecurity policy
を定義する
乗っ取り
SELinuxの特徴
SELinuxの特徴
• TE(Type Enforcement)
• ドメイン遷移(Domain transition)
• RBAC(Role Base Access Control)
TE(Type Enforcement)
• プロセスがアクセスできるリソースを制限するための
仕組み。
• プロセスには「ドメイン」、リソースには「タイプ」
といったラベルをそれぞれ付与する。
• 「ドメイン」が「タイプ」に対して、どのような操作
を実行できるのかを設定する。
• 設定する操作は「アクセスベクタ」と呼ぶ。
TE(Type Enforcement)
TE の記述例
allow ドメインA タイプA アクセスベクタA;
allow ドメインA タイプB アクセスベクタB;
ドメインA がタイプA を read することを許可
ドメインA がタイプB を write することを許可
ドメインA
(プロセス)
タイプA
(リソース)
タイプB
(リソース)
アクセスベクタA(例:read)
アクセスベクタB(例:write)
• 簡単に表現すると、プロセスがファイル等のリソース
に対して出来る事を定義するもの
ドメイン遷移
• 遷移元ドメイン(親プロセス)から遷移先ドメイン
(子プロセス)に遷移する時、異なるドメインを割り
当てる仕組み。
• 親から子へは権限を引き継ぐのが通常だが、このドメ
イン遷移の仕組みより、異なる権限を与える事が出来
る。
RBAC(Role Base Access
Control)
• RBAC は「ロール」と呼ばれるいくつかのドメインを
束ねたものを設定し、それをユーザに付与する仕組み。
• ユーザは付与されたロール内のドメインの権限でのみ
ファイルにアクセス可能。この機能により各ユーザ毎
に細かく権限を付与、制限することが可能。
Platform開発者がやること
Platform開発者がやること
• Linux Kernelの確認
• Filesystemの確認
• Security Policyの作成
Linux Kernelの確認
• Linux KernelでSELinuxの機能を有効にする
kernel configでCONFIG_SECURITY_SELINUXをyにする。
Linux Kernelに入っている機能なので、kernel config
で有効にするだけで使用することが出来る。
BSPとして提供された環境では最初は有効になってな
いこともあるので、確認する。
AndroidとSELinux
Filesystemの確認
• SELinuxを使用するには拡張ファイル属性(xattr)が
必要。
ext4の場合、kernel configでCONFIG_EXT4_FS_XATTR
とCONFIG_EXT4_FS_SECURITYをyにする。
SELinuxを使用しない場合は不要なので無効になってい
ることがある。SELinuxを使う場合は確認する。
• 商用のFilesystemを使用する場合、拡張ファイル属性
(xattr)が実装されてるか確認すること。
AndroidとSELinux
Security Policyの作成
• AOSP(Android Open Source Project)に無いものを
自分で作成する
ターゲット毎に異なるデバイス(/dev/***など)
独自の機能(アプリやサービス)
• AOSPにあるSecurity Policyは(基本的に)変更しない
自分のデバイスツリー配下に追加する
(Nexus5だとdevice/lge/hammerhead配下)
vendor配下に置くものはvendor配下に追加する
AOSPのSecurity Policy
• AOSPのSecurity Policyはexternal/sepolicyにある
https://android.googlesource.com/platform/external
/sepolicy/
AOSPのSecurity Policy
Security Policyの多くはTE
TEの読み方(初級編)
• タイプの設定
• TEの記述
• ドメイン遷移の記述
• 便利なマクロ
bootanimationのSecurity Policy
bootanim.te
type bootanim, domain;
type bootanim_exec, exec_type, file_type;
init_daemon_domain(bootanim)
binder_use(bootanim)
binder_call(bootanim, surfaceflinger)
allow bootanim gpu_device:chr_file rw_file_perms;
allow bootanim oemfs:dir search;
allow bootanim oemfs:file r_file_perms;
allow bootanim audio_device:dir r_dir_perms;
allow bootanim audio_device:chr_file rw_file_perms;
タイプの設定
bootanim.te
type bootanim, domain;
type bootanim_exec, exec_type, file_type;
init_daemon_domain(bootanim)
binder_use(bootanim)
binder_call(bootanim, surfaceflinger)
allow bootanim gpu_device:chr_file rw_file_perms;
allow bootanim oemfs:dir search;
allow bootanim oemfs:file r_file_perms;
allow bootanim audio_device:dir r_dir_perms;
allow bootanim audio_device:chr_file rw_file_perms;
タイプの設定
書き方
type ラベル, タイプ...
例1
type bootanim, domain;
bootanimというドメイン名の定義(bootanimationのこと)
例2
type bootanim_exec, exec_type, file_type;
bootanim_execは実行可能ファイルであることの定義。
タイプ...には複数記述出来る。
(実行可能ではない)通常のファイルの場合はfile_typeのみにす
る。
TEの記述
bootanim.te
type bootanim, domain;
type bootanim_exec, exec_type, file_type;
init_daemon_domain(bootanim)
binder_use(bootanim)
binder_call(bootanim, surfaceflinger)
allow bootanim gpu_device:chr_file rw_file_perms;
allow bootanim oemfs:dir search;
allow bootanim oemfs:file r_file_perms;
allow bootanim audio_device:dir r_dir_perms;
allow bootanim audio_device:chr_file rw_file_perms;
TEの記述
書き方
allow ドメイン タイプ:オブジェクトクラス アクセスベクタ;
ドメインはプロセス
タイプ:オブジェクトクラスはリソース
アクセスベクタはプロセスがリソースに対して行える操作
例
allow bootanim gpu_device:chr_file rw_file_perms;
bootanimがGPUデバイス(gpu_device:chr_file)に対して読み書
きする(rw_file_perms)のを許可する(allow)ルール。
TEの記述
例
allow bootanim gpu_device:chr_file rw_file_perms;
bootanimがGPUデバイス(gpu_device:chr_file)に対して読み書
きする(rw_file_perms)のを許可する(allow)ルール。
gpu_device:chr_file
gpu_deviceはfile_contextsというファイルで定義。
AOSPでは/dev/pvrsrvkmというデバイスファイルを指す。
※ターゲット毎に変更する必要有り。方法は後述。
chr_fileはsecurity_classesというファイルで定義。
chr_fileはキャラクタデバイス用。
ブロックデバイスだとblk_fileとなる。
TEの記述
例
allow bootanim gpu_device:chr_file rw_file_perms;
bootanimがGPUデバイス(gpu_device:chr_file)に対して読み書
きする(rw_file_perms)のを許可する(allow)ルール。
捕捉
allowで始まるルールは許可するものを書く。
許可したくないものは何も書かないか、neverallowを使用する。
neverallowを書いてるのにもかかわらずallowを書いていた場合、
コンパイル時にエラーとなる。
便利?なマクロ
type bootanim, domain;
type bootanim_exec, exec_type, file_type;
init_daemon_domain(bootanim)
binder_use(bootanim)
binder_call(bootanim, surfaceflinger)
allow bootanim gpu_device:chr_file rw_file_perms;
allow bootanim oemfs:dir search;
allow bootanim oemfs:file r_file_perms;
allow bootanim audio_device:dir r_dir_perms;
allow bootanim audio_device:chr_file rw_file_perms;
便利?なマクロ
init_daemon_domain(bootanim)はマクロ
define(`init_daemon_domain', `
domain_auto_trans(init, $1_exec, $1)
tmpfs_domain($1)
')
domain_auto_transもマクロ
define(`domain_auto_trans', `
domain_trans($1,$2,$3)
type_transition $1 $2:process $3;
')
domain_transもマクロ(以下省略)
これらはte_macrosに定義があります。
ドメイン遷移の記述
書き方
type_transition 遷移元 ラベル 遷移先;
遷移元は遷移元のドメイン
ラベルは実行ファイルに設定されたラベル
遷移先は遷移先のドメイン
例
type_transition init bootanim_exec:process bootanim;
initからbootanimが起動する。
このルールがあるとbootanimはbootanimドメインで動作する。
便利なマクロ
ここで前に出てきたマクロが便利に感じるかもしれない。
(記述の簡略化と見た目の分かりやすさ)
type_transitionを使用する場合
type_transition init bootanim_exec:process bootanim;
domain_auto_transを使用する場合
domain_auto_trans(init, bootanim_exec, bootanim)
initデーモンであれば更に簡略化
init_daemon_domain(bootanim)
作成したSecurity Policyの格納
• 全体の設定(ここは変更しない)
external/sepolicy
• 各ターゲット毎の設定
device/xxx/zzz/sepolicyに置く
置き場は自由に決められる
Nexus5の例
device/lge/hammerhead/sepolicy
作成したSecurity Policyの組込み
• Security Policyはビルド時にテキストから専用の形式に
変換される。
• ビルド時に以下4つの変数を参照する。
BOARD_SEPOLICY_DIRS
BOARD_SEPOLICY_REPLACE
BOARD_SEPOLICY_UNION
BOARD_SEPOLICY_IGNORE
BOARD_SEPOLICY_DIRS
Security Policyの格納場所を定義する。
次のようにしてターゲット毎の格納場所を定義する。
使用例(Nexus5の場合)
BOARD_SEPOLICY_DIRS += ¥
device/lge/hammerhead/sepolicy
場所はBOARD_SEPOLICY_DIRSで自由に決められるが、Nexus5の
例のようにして格納するのが分かりやすくて良いと思います。
BOARD_SEPOLICY_REPLACE
Security Policyの置き換えに使用する。
全体の設定を使用せずに、自分で作成したSecurity Policyを使いた
い場合は定義する。
使用例
BOARD_SEPOLICY_REPLACE += ¥
app.te ¥
device.te ¥
te_macros
BOARD_SEPOLICY_UNION
Security Policyの追加に使用する。
全体の設定に対して、自分で作成したSecurity Policyを追加したい
場合に使用する。
使用例
BOARD_SEPOLICY_UNION += ¥
app.te ¥
device.te ¥
te_macros
Nexus5ではこれを使用してSecurity Policyを追加している。使用
するのはほぼこれだと思います。
BOARD_SEPOLICY_IGNORE
Security Policyにフィルターをかける。
全体の設定から削除したいSecurity Policyを定義する。
使用例
BOARD_SEPOLICY_IGNORE += ¥
app.te ¥
device.te ¥
te_macros
Nexus5用のSecurity Policy
ターゲット用のSecurity Policyの例としてNexus5。
Nexus5用だけでもこれだけあります。
Nexus5用のSecurity Policy
bootanimationのTEファイルで出てきたgpu_deviceをNexus5用に
定義するところを確認します。
BOARD_SEPOLICY_DIRS += ¥
device/lge/hammerhead/sepolicy
BOARD_SEPOLICY_UNION += ¥
file_contexts
file_contextsの内容(GPU deviceのところだけ)
# GPU device
/dev/kgsl-3d0 u:object_r:gpu_device:s0
/dev/kgsl u:object_r:gpu_device:s0
Security Policyの作成(まとめ)
• AOSPで用意されている全体のSecurity Policyは変更し
ない
• ターゲット毎に必要なSecurity Policyはデバイスツリー
(例:device/xxx/zzz/sepolicy)に格納する
• Security Policyの記述は単純だが、数が多くて全体の把
握&漏れが無いかの確認が大変。全体を把握できる人
が必要だと思う。
開発で遭遇したこと
JCROM開発での例
• 遭遇した問題
• 問題への対処
遭遇した問題
• JCROMは見た目のカスタマイズを出来るようにしてい
る。(bootanimationやサウンドも変更出来る)
テーマ選択 テーマ反映
遭遇した問題
• KitKatからLollipopにバージョンアップした時、インス
トールしたテーマに含まれるbootanimationが表示さ
れなかった。
問題の原因調査
• 動作を追いかけると、bootanimation.zip(ブートアニ
メーションで使用するファイル)にアクセス出来ない
というエラーが返ってきている
• bootanimation.zipを読み込むためのパーミッションは
問題無いので、何故?となる
shell@jcrom:/ # ls -l /data/theme/
drwxrwxr-x system system 2015-04-25 00:00 bootanime
shell@jcrom:/ # ls -l /data/theme/bootanime/
-rw-r--r-- system system 1337396 2015-04-25 00:00
bootanimation.zip
問題の原因調査
• 解析時の基本、ログの調査。
(dmesg、logcatで同じログが出るので、どちらか)
<36>[ 0.997773] type=1400 audit(1429875733.980:4): avc:
denied { open } for pid=1017 comm="BootAnimation"
name="bootanimation.zip" dev="mtdblock1" ino=21154
scontext=u:r:bootanim:s0
tcontext=u:object_r:system_data_file:s0 tclass=file
permissive=0
<36>[ 0.997963] type=1400 audit(1429875733.980:5): avc:
denied { read } for pid=1017 comm="BootAnimation"
name="bootanime" dev="mtdblock1" ino=21155
scontext=u:r:bootanim:s0
tcontext=u:object_r:system_data_file:s0 tclass=dir
permissive=0
問題の原因調査
• ログに出てきている拒否の部分「avc: denied」等を
キーワードに検索してみると、SELinuxにたどり着く。
SELinuxが原因かの切り分け
• ログからSELinuxが怪しいと分かったので、SELinuxか
どうかを切り分ける。
• 切り分けのため、SELinuxを無効にしてみる。
SELinuxを無効にする方法
• コマンドで有効、無効を切り替える
• Linux KernelでSELinuxを無効化して、Kernelを差し替
える
• Linux Kernelのブートパラメータで有効、無効を指定
する
SELinuxを無効にする方法
• コマンドラインからsetenforceを実行する。
root権限が必要(userビルド環境では不可)
無効化
# setenforce 0
これは厳密には有効のまま。ログにアクセス拒否のログが出るだけ
で、実際にはアクセス拒否はしない。
この状態はPermissiveモードと言います。
有効化
# setenforce 1
有効な状態はEnforcingモードと言います。
SELinuxを無効にする方法
• Linux KernelでSELinuxを無効化はconfigで無効化する
だけなので方法は省略
• 無効化したLinux Kernelを用意しておいて、切り替え
るのが楽。
SELinuxを無効にする方法
• Linux Kernelのブートパラメータで指定する。
開発時にはこれが便利。
無効化
CONFIG_CMDLINE="androidboot.selinux=disabled"
有効化
androidboot.selinuxにdisabledが設定されていなければ有効
SELinuxが原因かの切り分け
• SELinuxを無効化したところ、インストールしたテーマ
に含まれるbootanimationが表示された。
• SELinuxが原因と判明したので、Security Policyの定義
を見直す。
bootanimationのSecurity Policy
• KitKatとLollipopを比較したところ、KitKatには
bootanimation用のSecurity Policyの定義は無かった。
• 無い≒アクセス制限されない。
KitKatで動いていた理由はこれで、Lollipopでは真面目
にSecurity Policyの定義をされてしまったので拒否され
ていた。
• KitKat→LollipopではSecurity Policyの定義が厳しく
なっているので、こういうケースは実は結構あるかも
しれない。
bootanimationのSecurity Policy
bootanim.teの内容
type bootanim, domain;
type bootanim_exec, exec_type, file_type;
init_daemon_domain(bootanim)
binder_use(bootanim)
binder_call(bootanim, surfaceflinger)
allow bootanim gpu_device:chr_file rw_file_perms;
allow bootanim oemfs:dir search;
allow bootanim oemfs:file r_file_perms;
allow bootanim audio_device:dir r_dir_perms;
allow bootanim audio_device:chr_file rw_file_perms;
※/data/theme配下へのアクセス許可が存在しないので拒否される
問題への対処
• Security Policyの追加
JCROMでは/data/theme配下にテーマデータをインス
トールするので、テーマデータにアクセスするプロセ
スからアクセス出来るようにする。
必要なSecurity Policy
• /data/theme配下へのアクセス許可
/data/theme 配下のファイルを読めれば良い。
• 変更するファイルは次の4つ
file.te
file_contexts
domain.te
bootanim.te
file.teとfile_contextsの追加
file.te
theme_data_fileという名前の定義を作る。
# /data/theme
type theme_data_file, file_type, data_file_type;
file_contexts
/data/themeを定義する。
ここでtheme_data_fileという名前を使う。
/data/theme(/.*)? u:object_r:theme_data_file:s0
domain.teとbootanim.teの追加
theme_data_fileのアクセスを追加する。
必要なのは読み込みなので、書き込みは許可しない。
domain.te
# Read files already opened under /data/theme.
allow domain theme_data_file:dir { search getattr };
allow domain theme_data_file:file { getattr read };
allow domain theme_data_file:lnk_file r_file_perms;
bootanim.te
allow bootanim theme_data_file:dir r_dir_perms;
allow bootanim theme_data_file:file r_file_perms;
応用編
• 新しい機能の追加した時のSecurity Policyを作成
新しい機能の追加
kassy_kzというサービスを作る。
出来ることは「ユーザデータ(/data)を読んでXXXを実行する」
サービス起動に関しては、init.rcに以下を定義
service kassy_kz /system/bin/kassy_kz
disabled
oneshot
コマンドラインから起動方法は、
「/system/bin/setprop ctl.start kassy_kz」
Security Policyを作らない場合
Security Policyを作れとログが出るだけ。
<3>init: Warning! Service kassy_kz needs a SELinux domain
defined; please fix!
この状態でkassy_kzが乗っ取られたりすると危険。
Security Policyを作成する
bootanimの時同様Security Policyの定義が無いのが原因なので、
kassy_kz.teを作成する。内容は以下の通り。
# kassy_kz oneshot service
type kassy_kz, domain;
type kassy_kz_exec, exec_type, file_type;
init_daemon_domain(kassy_kz)
file_contextsにラベルを追加。
/system/bin/kassy_kz u:object_r:kassy_kz_exec:s0
まずは、ほとんど何も許可してない状態にします。
効果の確認
/system/bin/kassy_kzを起動した結果
<4>type=1400 audit(1399014089.820:28): avc: denied
{ open } for pid=1987 comm=“kassy_kz”
name=“cocoa_chino.jpg” dev=“mtdblock1” ino=412
scontext=u:r:kassy_kz:s0
tcontext=u:object_r:system_data_file:s0 tclass=file
permissive=0
/data/picture/gochiusa/cocoa_chino.jpgを覗きに行ったけど、
SELinuxによってアクセスが拒否されたので、Security Policyの設定
に成功した事になります。
この後、必要な操作だけallowを追加していきます。
開発で役立ったこと
開発で役立ったこと
• ls -Z
• ps –Z
• loadpolicy
ls -Z
lsの結果にラベル表示してくれる。
shell@jcrom:/ # ls –Z
drwxrwx--x system system u:object_r:system_data_file:s0
data
-rwxr-x--- root root u:object_r:rootfs:s0 init
-rwxr-x--- root root u:object_r:rootfs:s0 init.rc
drwxr-x--x root sdcard_r u:object_r:rootfs:s0 storage
ps -Z
psの結果にラベル表示してくれる
shell@jcrom:/ # ps -Z
LABEL USER PID PPID NAME
u:r:init:s0 root 1 0 /init
u:r:shell:s0 shell 66 1 /system/bin/sh
u:r:adbd:s0 shell 67 1 /sbin/adbd
u:r:kernel:s0 root 139 2 kworker/0:2
u:r:system_server:s0 system 376 55 system_server
loadpolicy
Security Policyを読み込む。
開発時にSecurity Policyを修正して確認する時に楽。
shell@jcrom:/ # loadpolicy policy-file
loadpolicyの引数にSecurity Policyを指定する。
場所は(読めるところなら)どこでも良い。
今後
今後
• 今回はSELinuxの概要とAndroidでの簡単なポリシー作
成まで
• SELinuxの実装によりAndroidにどのような変更が入っ
てるのか、より細かいSecurity Policyの作成はどうする
のか...はどこか(ブログか横浜PF部あたり)で公開し
ます

More Related Content

AndroidとSELinux