Android OSの仕組み

概要

アプリが他のアプリのデータにアクセスしたり、OSの機能や他のアプリの機能を利用したりできる事について説明してきました。 しかし、アプリが自由に他のアプリの情報やOSの機能を使用できるわけではありません。 想定外のアプリからデータや機能を使用される事がないように、Android OSはセキュリティを維持するための仕組みを持っています。
Androidアプリのセキュリティを維持するための基本的な仕組みは以下の通りです。
  • ID
    LinuxのユーザID、グループIDに相当するものです。 Android OSでは、アプリ単位に個別のIDが割り当てられます。 Android OSではIDベースのファイルアクセス許可が設定されるため、明示的に指定しない限り、アプリは他のアプリのデータに対して基本的に読み込み、書き込みを行うことができません。

  • ファイルのアクセス許可設定
    上の「ID」で説明したとおり、 Android OSではIDベースのファイルアクセス許可が設定されますが、アプリが明示的にアクセス許可を設定することもできます。

  • Permission
    アプリがOSの提供する機能や他のアプリの情報にアクセスするためには、Permissionを使用する必要があります。
    また、アプリが公開する機能や情報をPermissionで保護する事もできます。

  • 証明書
    アプリには署名をする必要があります。署名されていないアプリは、不正なアプリファイルと認識され、端末にインストールできません。 署名に使用する証明書はアプリ開発者を識別する目的の他、アプリ間の信頼関係の確立手段として使用します。


Android OSはこれらの要素を組み合わせる事によって、
  • アプリはお互いのデータに直接アクセスする事はできない。
  • アプリはOSの機能のうち、限定された部分にのみアクセスできる。
という構造を実現しています。


以降、権限の制限およびデータ共有や機能連携を行うための仕組みについて解説します。
解説する内容は以下のとおりです。

権限の制限およびデータ共有や機能連携を行うための仕組み
名称 種類 用途
権限を制限するための仕組み 権限の許可 アプリの実行権限を制限する。
ファイルのアクセス許可 他のアプリからの直接のファイルアクセスを制限する。
データ共有や機能連携するための仕組み ContentProvider 他のアプリとデータを共有する。
Intent 他のアプリの機能を呼び出す。

権限の許可

アプリがOSの提供する機能や他のアプリの情報にアクセスするためには、Permissionを使用する必要があります。
例えば、アプリから電話発信したい場合や位置情報を取得したい場合、他のアプリの機能を使用したい場合には、それぞれについてPermissionが必要になります。 アプリが使用したい機能やデータに対するPermissionを持っていない場合、処理は正常に実行されません。 アプリが使用するPermissionはアプリのインストール時に利用者に表示され、利用者が内容を確認してインストールを実行した段階でアプリに付与されます。

アプリのインストール時にPermissionが表示される


以下に、OSが提供するPermissionの例を挙げます。

OSが提供するPermissionの例
Permission名 説明
INTERNET アプリがインターネットに接続することを許可する
READ_CONTACTS アドレス帳に登録した連絡先の読み取りを許可する
READ_LOGS システムログファイルの読み取りを許可する
ACCESS_FINE_LOCATION GPSなどを使用した、端末の詳細な位置情報へのアクセスを許可する
ACCESS_COARSE_LOCATION 携帯電話の基地局や無線LANのアクセスポイントを使用した、端末のおおまかな位置情報へのアクセスを許可する
CAMERA カメラの使用を許可する
RECEIVE_BOOT_COMPLETED 「端末が起動した」という内部的通知を受け取ることを許可する(当該アプリを、端末起動後に自動的に開始させる場合などに使用される)

アプリがOSの機能を使用する場合には、OSが定義したPermissionを利用することになります。また、アプリが自身の情報を保護するために独自のPermissionを定義することもできます。

ファイルのアクセス許可

Android OSは、Linuxカーネルをベースとしており、Linuxと同様にIDベースのファイルアクセス許可を実施しています。Android OSは、アプリ毎に異なるユーザIDとグループIDを割り当てるため、アプリが作成したファイルやディレクトリは、ファイルを作成したアプリが許可しない限り、他のアプリからは読み書きできません。

ファイルのアクセス許可による制限例

初期状態でのアクセス許可設定
アプリは、ファイルやディレクトリに対して、「所有ユーザ」「所属グループ」「その他のユーザ」毎に、 読み取り[r]、書き込み[w]、実行[x]などのアクセス許可の設定・変更を行うことができます。 Android OSの場合、アプリをインストールした時点で、アプリ専用のディレクトリが作成されます。 このディレクトリおよび、アプリがファイルを作成したときの初期状態でのアクセス許可設定は、 以下の通りです。

  • アプリインストール時に生成されるディレクトリ
    アプリをインストールすると、当該アプリ専用のディレクトリ /data/data/(アプリのパッケージ名)/ が生成されます。 生成されたディレクトリのアクセス許可は、所有ユーザ:rwx、所属グループ:r-x、その他のユーザ:--xとなります。 このアクセス許可の設定の場合、他のアプリはディレクトリ配下への移動のみ許可されることになります。

    アプリ専用ディレクトリのアクセス許可設定

  • アプリが作成するファイル
    アプリが明示的にアクセス権を指定せずにファイルを作成した場合、作成されたファイルのアクセス許可は、所有ユーザ:rw、所属グループ:rw、その他のユーザ:---となります。 このアクセス許可設定の場合、他のアプリからこのファイルの読み書きはできません。 なお、アプリがファイル作成時に設定を明示的に変更し、他のアプリからの読み書きが可能となるファイルを作成することもできます。

    ファイルのアクセス許可設定

  • ファイルの保存先によってアクセス許可設定が異なる
    端末には、データを保存する領域が2種類あります。端末に内蔵されているデータ保存領域である内部ストレージと、 SDカードなどの端末から取り外すことが可能なデータ保存領域である外部ストレージです。 (最近の端末の中には、基板上に設置され「取り外しできないSDカード」と認識される外部ストレージを持つものもあります)。 内部ストレージは、簡単に取り外すことができないため、重要な情報の保存に適しているといえます。 一方、外部ストレージは、一般的に取り外し可能であるため、公開しても良い情報を保存するのに適しています。 また、アプリがファイルを作成する際に、アクセス許可の設定ができるのは内部ストレージに対してのみです。 外部ストレージにファイルを作成する場合には、アプリからアクセス制限を行うことはできません。 外部ストレージ上のファイルは、悪意のあるアプリを含む全てのアプリが読み書きできてしまう点に注意が必要です。

    SDカード上のファイルのアクセス許可設定

    上の例はSDカード上に作成されたファイルのアクセス許可を表示したものですが、所有ユーザはsystemとなっており、特定のアプリに帰属していないことが分かります。

ContentProvider

Android OSは、アプリが明示的に許可しない限り、他のアプリのデータにアクセスができません。 しかし、これではアプリ間でのデータ共有が困難になります。 セキュリティを維持しつつデータ共有を実現するために、Android OSは「ContentProvider」という仕組みを提供しています。 ContentProviderを実装したアプリは、そのアプリが管理しているデータを他のアプリに公開することができるようになります。

ContentProviderの使用イメージ

上の図では、アプリAはアプリBが管理しているデータに直接アクセスする事はできませんが、 アプリBが提供しているContentProviderを通じてアプリBのデータにアクセスできるようになっています。
ContentProviderのアクセス制限
ContentProviderが全てのアプリからアクセス可能になっていることは、アプリのデータを全て他のアプリに提供しているのと同じ事です。 これはセキュリティの面で大きな問題となります。
データを公開するアプリは、データの公開範囲を限定し、かつアクセスモードも限定し、想定外のアプリがデータを入手したり、 悪意のあるアプリによってデータを改ざんされたりしないようにContentProviderを適切に保護する事が必要です。
ContentProviderに対するアクセス制限は、「AndroidManifest.xml」ファイルに定義します。
アクセス制限を適切に行う事で、例えば、下図のようにアプリBが「データ1」、「データ2」、「データ3」を保存していた場合、 「データ1」と「データ2」のみ他のアプリに公開して、「データ3」は非公開にするといったような制御を行う事ができます。

ContentProviderのアクセス制限イメージ

また、特定のPermissionを持つアプリだけにデータの読み取りを許可する、といった制限も可能です。 ContentProviderを利用することで、アクセス制限をかけた上で他のアプリにデータを公開することができます。

Intent

Android OSは、アプリ間の機能連携を実現するために、アプリから他のアプリの機能(コンポーネント)を呼び出す仕組みを提供しています。 この仕組みを「Intent」と呼びます。
Intentを使用することにより、下の図のようにカメラアプリで撮影した写真を、別アプリのメール送信機能を使って、 友人に宛てて送信するといった事が可能になります。

Intentによる機能の呼び出しイメージ

Intentはアプリ連携を実現する重要なものですが、疎結合のアプリ間でやり取りされるために想定外のアプリにIntentが渡ってしまう、 または悪意のあるアプリからIntentを受け取ってしまう、といった可能性があります。開発者はIntentのこのような問題を正しく理解してアプリを設計しなければいけません。
Intentに対するアクセス制限
Intentが保護されていない場合、想定外のアプリからIntentを受け取ってしまうことにより、アプリの機能を悪用される可能性があります。 このような問題が起きる事を防ぐために、コンポーネントが受信できるIntentを制限することができるようになっています。 設定は、Intentを受け取る側のアプリの「AndroidManifest.xml」ファイルに記述します。 例えば、他のアプリからのIntentを一切受け取らないようにしたり、特定のPermissionを持つアプリからのIntentだけを受け取るように制限したりすることが可能です。

Intentのアクセス制限イメージ

上の図の例は、メールアプリ側で、機能(コンポーネント)が受信するIntentを制限している例です。
カメラアプリからメール送信機能へ向けたIntentはメールアプリに受信されますが、メール受信機能へ向けたIntentは、メールアプリは受け取りません。 これでメールアプリのメール受信機能は保護されていることになります。
Intentの種類
Intentには、受信先を明示的に指定する「明示的Intent」と、受取り先のアプリの条件だけを指定する「暗黙的Intent」の2種類があります。

明示的Intentと暗黙的Intentの制限方法の違い
Intentの種類 制限の設定方法
明示的Intent Intentの受信先をクラス名で明示しているIntentです。 Intentを送信する側のアプリが受信先のアプリを特定しているため、指定したアプリ以外がIntentを受信することはありません。 Intentを受信する側は、想定外のアプリからIntentを受け取る可能性があるので、想定外のアプリからのIntentを受信する事がないように制限を設定します。 制限は、「AndroidManifest.xml」ファイルにコンポーネント毎に記述します。
暗黙的Intent 「Intentの受信先を明示せず、受取り先のアプリの条件だけを指定しているIntentです。 Intentを送信する側のアプリは、受信先アプリを特定していないので、想定外のアプリがIntentを受信する可能性があります。 暗黙的Intentを受信する側は、受け取るIntentの条件を「AndroidManifest.xml」に記載します(この設定を「IntentFilter」と呼びます)。明示的Intentの場合と同様に、 想定外のアプリからIntentを受け取る可能性があるので、想定外のアプリからのIntentを受信する事がないように制限を設定します。 この制限も「AndroidManifest.xml」ファイルにコンポーネント毎に記述します。

明示的Intentを発行した場合は相手のアプリは一意に決まります。 暗黙的Intentを発行した場合は条件に合致するアプリが複数見つかることがあります。 この場合は、Android OSによって起動するアプリを選択する画面が表示され、利用者がIntentを受信するアプリを選択することになります。

これでAndroid OSの仕組みについての説明は終了です。学習コンテンツに取り組む準備ができました。
興味のあるコンテンツを選んで学習してみましょう。