アンドロイド - UID(User Id)、GID(Group Id)とSecurity

By JS | Last updated: August 07, 2019

Androidは、LinuxのUID(User Id)とGID(Group Id)を使用してアプリごとに異なるアクセス権を設定することができます。

たとえば、アプリに割り当てられているUIDはRootまたはSystemではないので、 /systemフォルダにアクセスすることはできません。 逆に、アプリがGID media_rwを持っていればsdcardにアクセスすることができます。 この方法で、システムはアプリごとに異なる権限を付与することができ、セキュリティを維持することができます。

UID(User ID)

UIDは、ユーザーのIDです。 Androidはアプリごとに異なるUIDを割り当てます。 このようにする理由は、異なるアプリのデータにアクセスできないように作るためです。 アプリは、自分のデータフォルダのみアクセス可能であり、システムや他のアプリのフォルダにアクセスすることはできません。

たとえば、ルーティングされたデバイスのshellで以下のようにアプリのデータフォルダーの権限とUIDを見ることができます。

generic_x86:/data/data # ls -aln
# Permission   [UID] [GID]                        [File name]
drwx------  10 10126 10126 4096 2019-08-08 20:17 com.google.android.apps.maps
drwx------   8 10108 10108 4096 2019-08-08 20:17 com.google.android.apps.messaging
drwx------   8 10129 10129 4096 2019-08-08 20:17 com.google.android.youtube

左側にあるパーミッションを見ると、Userだけrwx権限があり、GroupとOthersは何の権限もありません。そしてUIDを見ると、アプリごとに異なるUIDが設定されています。 したがって、Rootを除くすべてのアプリは、お互いのファイルにアクセスすることができません。

アプリUIDチェック

adb shellで ps -efコマンドを入力すると、プロセスのUIDを確認することができます。

127|generic_x86:/ $ ps -ef
UID            PID  PPID C STIME TTY          TIME CMD
root             1     0 0 09:02 ?        00:00:01 init second_stage
audioserver   1706     1 0 09:06 ?        00:00:00 android.hardware.audio@2.0-service
cameraserver  1708     1 0 09:06 ?        00:00:00 android.hardware.camera.provider@2.4-service
media         1709     1 0 09:06 ?        00:00:00 android.hardware.cas@1.1-service
system        1710     1 0 09:06 ?        00:00:00 android.hardware.configstore@1.1-service
media         1711     1 0 09:06 ?        00:00:00 android.hardware.drm@1.0-service
tombstoned    1774     1 0 09:07 ?        00:00:00 tombstoned
radio         2110  1701 0 09:12 ?        00:00:07 com.android.phone
u0_a114       2113  1701 0 09:12 ?        00:00:02 com.google.android.inputmethod.latin
u0_a93        2114  1701 0 09:12 ?        00:00:01 com.google.android.apps.nexuslauncher

上に見えるUIDの名前は、それぞれ別の数値に割り当てられています。 UIDの名前ではなく、数字で見ることを望む ps -efnコマンドを使用します。

GID(Group ID)

GIDは、Group Idです。 Userは、1つのPrimary groupと1つ以上のSupplementary groupを持つことができます。 結論として、Userは複数のGIDを持つことができます。

アプリが特定のファイルへのアクセス権が必要な場合、その権限に関連するGIDを受けています。 例えば、もしアプリが android.permission.INTERNETパーミッションを取得し、システムは、アプリのGIDinetを追加します。 アプリは inetにアクセス可能な領域にアクセスできるようになります。

GIDもUIDのように ls -alコマンドでファイルのアクセス権を確認することができます。以下は、 /sdcardファイルのGID情報です。(GIDを数値として表示するにはls -alnを使用してください)

generic_x86:/sdcard # ls -al
# Permission  [UID] [GID]                          [File name]
drwxrwx--x  2 root sdcard_rw 4096 2019-07-19 22:04 Alarms
drwxrwx--x  3 root sdcard_rw 4096 2019-07-19 22:04 Android
drwxrwx--x  2 root sdcard_rw 4096 2019-07-19 22:04 DCIM
drwxrwx--x  2 root sdcard_rw 4096 2019-08-01 23:36 Download
drwxrwx--x  2 root sdcard_rw 4096 2019-07-19 22:04 Movies
drwxrwx--x  2 root sdcard_rw 4096 2019-07-19 22:04 Music
....

上記の結果から、左パーミッションを見ると、UserとGroup rwxを権限があります。 したがって、アプリが /sdcard領域にアクセスするには、rootになったり、sdcard_rw Groupに属している必要あります。

事実アプリがWRITE_EXTERNAL_STORAGE権限を受け取るsdcard_rw GIDを受けません。実際には、アプリのmountinfo情報が変更され、/sdcardにアクセスできるようになります。

そしてちなみに、AndroidのQは、Scoped Storageにより、外部リポジトリにアクセスする権限、および方法が、以前とは少し変わりました。

アプリGID確認

アプリのGIDを確認することはUIDよりも少し面倒です。まず確認したいのUIDを知る必要があります。

たとえば、LauncherアプリのGIDを確認するには、以下のようなコマンドでUIDを検索します。

generic_x86:/ $ ps -ef | grep launcher
u0_a93        2114  1701 0 22:09:12 ?     00:00:01 com.google.android.apps.nexuslauncher

そして、 /proc/[pid]/statusファイルを確認するとGIDを知ることができます。 私の場合、PIDが2114であり、確認した結果は以下の通りです。

generic_x86:/ $ cat /proc/2114/status                                                          
Name:	s.nexuslauncher
Umask:	0077
State:	S (sleeping)
Tgid:	2114
Ngid:	0
Pid:	2114
PPid:	1701
TracerPid:	0
Uid:	10093	10093	10093	10093
Gid:	10093	10093	10093	10093
FDSize:	128
Groups:	9997 20093 50093

上記の結果からGidはPrimary groupに1つだけ設定されており、 Groupsは、Supplementary groupに複数のGIDが設定されています。

アプリのUIDは、誰がいつ割り当てか?

アプリのUIDは、アプリがインストールされるときに決定されます。 PackageManagerは、システムにアプリをインストールするときにアプリごとに異なるIDを付与します。

システムアプリではなく、一般的な3rd partyアプリは10000〜20000の間の数でUIDが割り当てられます。 しかしshell、root、installdなどは、固定されたシステムUIDであり、このような予約されたUIDは、10000未満の値に設定されます。

固定された(スケジュールされた)UIDは、Androidのコード android_filesystem_config.hに定義されています。

#define AID_RADIO 1001           /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002       /* bluetooth subsystem */
#define AID_GRAPHICS 1003        /* graphics devices */
#define AID_INPUT 1004           /* input devices */
#define AID_AUDIO 1005           /* audio devices */
#define AID_CAMERA 1006          /* camera devices */
#define AID_LOG 1007             /* log devices */
#define AID_COMPASS 1008         /* compass device */
....

しかし、アプリごとにUIDが同じ場合もあります。アンドロイドにSharedUserIdという概念があり、いくつかのアプリが同じUIDを使用できるようにします。

以下のようにアプリのAndroidManifest.xmlに sharedUserId属性にIDを指定することができます。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.codechacha.sample"
    android:sharedUserId="android.uid.codechacha">

複数のアプリを上記と同じようにsharedUserIdを設定すれば、アプリが端末にインストールされたときと同じUIDを割り当てられます。 重要なのは、SharedUserIdを設定するときエプドゥル同士同じSignatureに署名する必要があります。それ以外の場合、アプリがインストールされていません。

アプリのGIDは、誰がいつ割り当てか?

固定的なGIDは、アプリのUIDと同じように設定され、アプリごとにGIDが追加されることがあります。 上で紹介したように、システムは、アプリがどのようなパーミッションを持っているときにどのようGIDを割り当てることか参考にして、テーブルがあります。

アンドロイドコード frameworks/base/data/etc/platform.xmlがそのテーブルです。 以下のようにパーミッションごとにどのようなGIDが割り当てられて書かれています。

<permission name="android.permission.INTERNET" >
    <group gid="inet" />
</permission>
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
    <group gid="media_rw" />
</permission>
<permission name="android.permission.LOOP_RADIO" >
    <group gid="loop_radio" />
</permission>

上記のパーミッションがアプリに割り当てられた場合dumpsysログでGIDが割り当てられたことを確認することができます。

adb shell dumpsys package [package name]を入力すると、以下のようなログが出力され、ここで gids=[3003]のように割り当てられているGIDを示しています。 GID 3003はinetです。

Packages:
  Package [com.codechacha.sample] (e5cd86f):
    userId=10085
    pkg=Package{9a1a3a5 com.codechacha.sample}
    codePath=/data/app/com.codechacha.sample-UC4OqmKDH97R9vhuk7qtDw==
    ......
    install permissions:
      android.permission.INTERNET: granted=true
    User 0: ceDataInode=-4294952062 installed=true hidden=false suspended=false stopped=false notLaunched=false enabled=0 instant=false virtual=false
      gids=[3003]

セキュリティの観点からUIDとGID

アンドロイドはパーミッションシステムがあります。アプリは、AndroidManifest.xmlにパーミッションを宣言することができ、ユーザーが許可すると、システム内でその権限に関連するAPIを使用することができます。

パーミッションシステムとは別に、Androidはアプリごとに異なる権限を付与するUIDとGIDを使用します。 例えば、いくつかのシステムAPIを呼び出すときに、APIは、関数を呼び出すUIDをチェックしていくつかのUIDが、そのAPIを使用できるようにします。 したがって、任意のAPIは、UIDがsystemであるプロセスのみを使用することができますものもあります。

そのほか、他の権限とセキュリティ(Security)

そのほか、Androidはselinuxを使用します。アプリがファイルにアクセスすることができるUID、GID権限をすべて持っていてもselinux権限がないアクセスがない場合があります。 selinuxファイルごとにlabelをつけ、アプリのプロセスがそのlabelのアクセス権がない場合は読み書きできません。

まとめ

LinuxののUIDとGIDがAndroid上でどのように使用されるかを知ってみました。 また、アプリがどのようにUIDとGIDを得るか、どのような方法での権限を確認することができるか調べました。 そして、セキュリティの面でどのように使用されるかを知ってみました。

参考

Related Posts

codechachaCopyright ©2019 codechacha