2012年7月24日火曜日

androidのグループIDがよく分からない。

プリファレンスを操作するコードを書いてて、複数のデータをちゃんと扱えているかテストするのに楽しようとcpでコピーしたら、ファイルの所有ユーザーID/グループIDはrootになってしまい、データを読み出せずにテストに失敗して原因調査に余計な時間を使うハメに…。

ちなみに実機でdata/data領域を操作するにはroot化してsuを入れないとダメです。cpなどのコマンドもマーケットからBusyBoxを導入する必要があります。

BusyBoxを導入すればユーザーIDを操作できるchownコマンドも使えるようになるので、そのアプリが生成したほかのファイルを見て、同じアプリID(アプリ毎にユニークな^app_\d+$みたいなID)をユーザーIDとして指定すれば、ちゃんと読み込んでくれます。

グループIDも、ユーザーIDと同じアプリIDが設定されていたので、chgrpコマンドで指定してみたのだけど、こちらはエラーが出て失敗。そんなグループIDは存在しない、らしい。ちゃんと設定されてるファイルもあるのに。

----

androidのシステムは存在しないはずのグループIDをどうやってファイルに付与してるの?わたし、気になります。

Linux自体詳しくないからそこから調べたんだけど、本来ユーザーやグループは/etc/userや/etc/groupで管理されているらしく、そこにアクセスすればユーザー一覧、グループ一覧を見れるはずが、androidはそれらは存在しないと言われてしまう。

セキュリティのためなのだろうか?

androidの本体のソースコードから、

/system/core/include/private/android_filesystem_config.h

を見ると、android_id_info構造体という形で定義されている初期のUIDとGIDのリストを参照することはできる。ここで読み込まれた構造体の値を、/etc/userや/etc/groupの代わりに渡すスタブが存在するらしい。

/bionic/libc/bionic/stubs.c

これがスタブの役割を果たしているコードなのかな?

全然謎が解けない。

----

もう少し調べてみる。

ごく基本な話として、LinuxにおいてユーザーIDはユーザーに対して付与されるけど、androidではアプリに対して付与される。

Context.MODE_PRIVATEでプリファレンスなどを生成するということは、アプリに対して付与されたユニークなユーザーIDでのみ操作することを許可する、ということ。これがandroidのセキュリティの基礎になっている。

では複数のアプリでファイルを共有する場合にはどうしているのか?ここでグループIDを使っているのではないか?と思うところだけど、そんなことはなかった。

複数のアプリでMODE_PRIVATEなファイルを共有したい場合は、それぞれのアプリのandroidmanifestのsharedUserIdに任意の同じ文字列を付与すればよい。ここで指定したidがユーザーIDになるわけではなくて、やっぱり^app_\d+$というユーザーIDになるんだけど、同じ証明書でかつ同じsharedUserIdを持つアプリの場合は、同じユーザーIDが割り当てられる。

複数アプリで同じユーザーIDを共有できるので、同じプロセスでアプリを立ち上げることができ、MODE_PRIVATEなファイルも共有することもできる。

結局androidにおけるグループIDは何なんだろう。どこで使ってるんだろう。

----

androidの巷のセキュリティ本を見ると、「androidはLinuxベースなのでユーザーIDとグループIDを使っている」と書いてあるけど、android_filesystem_config.hで定義されてるシステム周りのファイルを除いては、グループIDの存在意義があるとも思えないし、ユーザーの手が届く領域については「ユーザーIDだけで管理されている」とみなしていいような気がするんだけど、どうなんだろう?

アプリがインストールされた時にユーザーIDを付与してるコードを探し出そうと思うけどもう気力が尽きたー。

Process.javaからnativeのC++コードからgidやuidを読み込んでいるってのは分かったけど、何の役にも立ちそうにない。

javaコードでもグループIDを読み出せるようにしているってことは、きっとどこかで使ってはいると思うのだけど…。

0 件のコメント:

コメントを投稿