Androidの許可制度

Androidのシステムは安全なオペレーティング環境で各アプリケーションを提供し、異なるプログラム、データ、アプリケーション、および他の民間リソース間の相互の分離、外の世界にアクセスすることはできません。提供するために、Androidの許可制度によるこの安全な動作環境(サンドボックスシステムと呼ばれることもあります)。この紙簡単にAndroidの許可制度と実装のキーコードメカニズムの基本的なビルディングブロックを記録します。

メインモジュール

Androidの許可制度は、4つのモジュールに分けられます。

  1. パーミッション・システムのユーザーIDに基づいて、
  2. 能力権限システム
  3. Androidの許可制度
  4. SELinuxの権限システム

パーミッション・システムのユーザーIDに基づいて、

許可制度は、ファイルや他のリソースへのプロセスへのアクセスを制御するために、UIDのプロセスに基づいています。手短に言えば、すべてのプロセスは、UIDとGID 1つ以上の属性を有し、各ファイルは、UIDとGID性を有する、及び許可のそれぞれのビットと、そのUID同じプロセスを3組、同じプロセスGIDがありますだけでなく、ファイルの読み込み、書き込みに他の無関係なプロセス、およびアクセスを実行します。粒度権管理の基本単位としてのUIDへのカーネル。特定のアクセスルールファイルのプロセスでは、あなたは、UNIX / Linuxのマニュアルまたはいくつかの本にアクセスすることができます。( "UNIX高度なプログラミング環境" セクション4.5)。

典型的なUNIX / Linuxのマルチユーザーシステムでは、各ユーザのシステムログは、UID、単一のユーザへのアクセス制御の粒度が割り当てられます。Androidシステムは、ユーザログオンの概念の伝統的な意味ではなく、UIDは、各アプリケーションに割り当てられているので、単一権管理アプリケーションのサイズ。次のように具体的な動作です。

  1. アプリケーションがインストールされると、アプリケーションのUIDのための分配システム。PackageManagerServiceのデフォルトは、各アプリケーションのための新しいUIDとGIDを割り当て。アプリケーションはいくつかの特別なランタイムの許可を申請している場合は、(実際にそれを追加)GIDグループの追加セットを割り当てます。同じ現像剤(同じシグネチャ)によって開発された二つのアプリケーションは、UIDとGIDを共有することができ、ちょうどAndroidManifestに同じものを宣言する必要android:sharedUserId性。書かれたアプリケーション一緒にUID / GIDと他のプロパティpackages.listpackages.xmlドキュメント。

     // PMS分配UID代码:
     // PackageManagerService.java
     if (newPkgSettingCreated) {
         if (originalPkgSetting != null) {
             mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name);
         }
         // THROWS: when we can't allocate a user id. add call to check if there's
         // enough space to ensure we won't throw; otherwise, don't modify state
         mSettings.addUserToSettingLPw(pkgSetting);
  2. あなたがアプリケーション・プロセスを開始すると、ActivityManagerService UID PackageManagerServiceへの問合せアプリケーション/ GIDやその他の情報、およびその情報がパラメータとして受精卵プロセスに渡されます。受精卵子プロセスのためのアプリケーションプロセスアウトフォーク、およびので、アプリケーション・プロセスは、独自のアイデンティティを実行することUID UIDパラメータを所有していたが、子供の/ GIDアップに応じて設定されています。

     // AMS 传递参数给Zygote
     // ActivityManagerService.java
     private ProcessStartResult startProcess(String hostingType, String entryPoint,
         ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
         String seInfo, String requiredAbi, String instructionSet, String invokeWith,
         long startTime) {
         try {
             ...
         } else {
             startResult = Process.start(entryPoint,
                     app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                     app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                     app.info.dataDir, invokeWith,
                     new String[] {PROC_START_SEQ_IDENT + app.startSeq});
         }
         ...
     }
    
     // Zygote 根据参数设置进程UID属性
     // com_android_internal_os_Zygote.cpp
     static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint runtime_flags, jobjectArray javaRlimits,
                                      jlong permittedCapabilities, jlong effectiveCapabilities,
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose,
                                      jintArray fdsToIgnore, bool is_child_zygote,
                                      jstring instructionSet, jstring dataDir) {
       ...
       pid_t pid = fork();
    
       if (pid == 0) {
         ...
         if (!SetGids(env, javaGids, &error_msg)) {
           fail_fn(error_msg);
         }
         ...
         int rc = setresgid(gid, gid, gid);
         ...
         rc = setresuid(uid, uid, uid);
         ...
       }
  3. アプリケーションファイルのアクセス権を設定します

    。設定システムや他のアプリケーションは、アプリケーションコードにアクセスできるように、すべてのユーザーのためのAPK読み取り可能なファイルのパーミッション、。

    アプリケーション用に作成し、B。データディレクトリシステムは、他のユーザーのための実行可能(検索)を設定します。あなたが実行可能として設定されていない場合は、すべてのユーザーデータファイルは、他のアプリケーションと共有することはできません。

         // ContextImpl.java
         public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException {
         checkMode(mode);
         final boolean append = (mode&MODE_APPEND) != 0;
         File f = makeFilename(getFilesDir(), name);
         ...
         File parent = f.getParentFile();
         parent.mkdir();
         FileUtils.setPermissions(
             parent.getPath(),
             FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                 -1, -1);

    C。デフォルト他のユーザーによってContext.openFileOutput Androidや他のインタフェースによって作成されたアプリケーションデータファイルを読み込み、書き込みができません。ユーザーが指定した場合MODE_WORLD_READABLEまたはをMODE_WORLD_WRITEABLE読み取り、書き込みの他のユーザーに設定されています。両方のモードの新しいバージョンは廃止されました。

          // ContextImpl.java
         public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException {
             checkMode(mode);
             final boolean append = (mode&MODE_APPEND) != 0;
             File f = makeFilename(getFilesDir(), name);
             ...
             setFilePermissionsFromMode(f.getPath(), mode, 0);
             return fos;
         }
         static void setFilePermissionsFromMode(String name, int mode,
             int extraPermissions) {
             int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
                 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
                 |extraPermissions;
             if ((mode&MODE_WORLD_READABLE) != 0) {
                 perms |= FileUtils.S_IROTH;
             }
             if ((mode&MODE_WORLD_WRITEABLE) != 0) {
                 perms |= FileUtils.S_IWOTH;
             }
             if (DEBUG) {
                 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
                     + ", perms=0x" + Integer.toHexString(perms));
             }
             FileUtils.setPermissions(name, perms, -1, -1);
         }

    データファイルD。File.createNewFile()Javaインタフェースにより、アプリケーションは、デフォルト彼だけが読み書きできるを作成します。現在のプロセスのumask設定に関連付けられている。このようにして作成されたファイルのパーミッション。initは077へのumaskを設定するシステムサービス(を含む接合体)の作成にAndroidのシステム、プロセス、アプリケーションはumaskを接合子継承し、そしてそれはまた、077であり、それだけでも(同じUIDを処理できるように、同一のUIDへのアクセスを保持することだけを示していますそれは彼の)訪問です。

         ``C++
         // system/core/init/service.cpp
         Result<Success> Service::Start() {
         ...
         pid = fork();
         if (pid == 0) {
             umask(077);
             ...
         }

機能メカニズム

UIDに基づいた権利管理機構、特殊なUID 0、いわゆるrootユーザーは、root権限が権利メカニズムによって拘束されていない持って、そこにあります。そして、いくつかのシステムリソースと能力は、rootユーザのみが使用することができます。、悪質なアプリケーションを悪用されることは容易であるシステムなどadbd、rootとして受精卵の実行、およびこれらのシステムサービスなどのコアサービスの多くと頻繁に相互作用アプリケーションと、これらのサービスのセキュリティの脆弱性は、だから、運営する権利を言及行い、画期的なシステムアクセス制御リスト。ゼロにさらに使用のUIDの権限を制限するので、Androidの機能メカニズム。

機能メカニズムは、rootユーザーだけが、さらに機能のセットに細分化されたアクセス権限を持っているだろう。各スレッドは、それ自体がが所有する権限を表現するためのビットの4セットを持っています:

$ adb shell cat /proc/<pid>/status
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000000000000000

これCapInhにはexecveが保持する実行権限を表し; CapEffスレッド現在の権限ことを示し、CapPrmはCapInhとCapEffの最大限界を表し; CapBndを得ることができるスレッドの最大権限を表します。

Androidシステム、adbd受精卵が作成され、アプリケーションサービスのためのプロセス。受精卵サービスがまだどんな超能力を持っていないので、子供がルートのuidを得るために、システムの脆弱性を利用した場合でもことを、かつてのシステム、CapBnd明らかに、子供のリターンを子プロセスを作成します。adbdその後、必要に応じてタスクの権限を実行した後に、明確なCapBndは、自らの権利を削減します。

// Zygote 设置子进程CapBnd
// com_android_internal_os_Zygote.cpp
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint runtime_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jintArray fdsToIgnore, bool is_child_zygote,
                                     jstring instructionSet, jstring dataDir) {
  ...
  pid_t pid = fork();
  if (pid == 0) {
    ...
    if (!DropCapabilitiesBoundingSet(&error_msg)) {
      fail_fn(error_msg);
    }
    ...

Androidの許可制度

デフォルトのアプリケーションは、自分のファイルやシステムリソースの非常に少量のみアクセスすることができます。より多くのリソースシステムや他のアプリケーションを取得したい、あなたは許可メカニズムが必要です。

リソース/サービスプロバイダAndroidManifestによって、発信者の明示的な許可を必要とするアプリケーションは、マニフェストに許可を要求し、アクセス権は、インストールや操作時に付与されたシステムを判断します。

権限の定義

次のようにAndroidの許可は、許可の各タイプが定義され、3つのタイプに分けることができます。

  1. 組み込み許可

    システム/etc/permissions/*.xml定義。各権限はGIDに対応しています。

    // /etc/permissions/platform.xml
    <permission name="android.permission.INTERNET" >
         <group gid="inet" />
     </permission>
    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
         <group gid="media_rw" />
     </permission>

    各グラント許可用に構築されたシステムのアプリケーションは、アプリケーションが追加したグループのアプリケーションIDグループに対応するGIDを追加与えます

    // PermissionsState.java
    private int grantPermission(BasePermission permission, int userId) {
         if (hasPermission(permission.getName(), userId)) {
             return PERMISSION_OPERATION_FAILURE;
         }
    
         final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
         final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
         ...
  2. 正常

    通常の権限は、システム(アンドロイドパッケージ)、システムアプリケーションとAndroidManifestが定義され、独自の権利でサードパーティのアプリケーションです。例えば、READ_CONTACTS他のシステム権限がAndroidManifestフレームワークres.apkに定義されています。

    // frameworks/base/core/res/AndroidManifest.xml
    <permission-group android:name="android.permission-group.CONTACTS"
         android:icon="@drawable/perm_group_contacts"
         android:label="@string/permgrouplab_contacts"
         android:description="@string/permgroupdesc_contacts"
         android:request="@string/permgrouprequest_contacts"
         android:priority="100" />
    
     <!-- Allows an application to read the user's contacts data.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CONTACTS"
         android:permissionGroup="android.permission-group.CONTACTS"
         android:label="@string/permlab_readContacts"
         android:description="@string/permdesc_readContacts"
         android:protectionLevel="dangerous" />
  3. 動的

    あなたは、動的に定義された権限を追加することができます。リファレンスAndroidデベロッパー

パーミッションチェック

  1. カーネル内の明示的なBuildtin許可検証機能、または許可UIDベースのメカニズムを検証します。

    INTERNET権限のカーネルチェック

    //
    // af_inet.c
    #ifdef CONFIG_ANDROID_PARANOID_NETWORK
    #include <linux/android_aid.h>
    
    static inline int current_has_network(void)
    {
      return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
    }
    static int inet_create(struct net *net, struct socket *sock, int protocol,
              int kern)
    {
      ...
      if (!current_has_network())
        return -EACCES;

    UIDベースの権限チェック。SDカード読み取りおよび書き込み権限に、例えば、sdcard_rwグループに設定SDカードディレクトリ権限を読み書きできる(各プロセスのための許可を参照し、ここで例として、シェルユーザに、同じではありません)。のみでWRITE_MEDIA_STORAGE入手する権利sdcard_rwSDカードのディレクトリにアクセスするには、GIDを。

    adb shell ls -l /sdcard/
    total 112
    drwxrwx--x 2 root sdcard_rw 4096 2008-12-31 21:31 Alarms
    drwxrwx--x 3 root sdcard_rw 4096 2008-12-31 21:31 Android
    drwxrwx--x 2 root sdcard_rw 4096 2008-12-31 21:31 DCIM
  2. ノーマルとダイナミックな権限を確認

    二つのケース。プログラムコンポーネントの活動、サービスなどへのアクセスについては、AMSの関数呼び出しによって許可チェックは、合法的な権威かどうかを判断します。

    サービスまたは外部サービスのためのアプリケーション・サービス・システムは、あなたは、発信者が権限を持っているかどうかを機能許可チェック機能をチェックして、独自の関数を呼び出すことができます。

    PackageManager.checkPermission()
    Context.checkPermission()

SELinuxの

互換性の高音用8.0以降ではSELinuxは、ちょうど8.0の前に公式文書で説明した概念と原則のいくつかについての記録を要約するために、主要な変更を行いました。

基本コンセプト

  1. 強制アクセス制御(MAC)

    • SELinuxは既におなじみのDAC(任意アクセス制御)に対して、Linuxシステム上で強制アクセス制御システムであります
    • 任意アクセス制御は、各所有者は、リソースの所有者が、リソースへの主要なアクセスを制御することが可能であるリソースを有します。これは通常、粗粒度の特権であり、容易に誤り伝播につながります
    • 資源の集中管理へのMACアクセス、問題はDACが存在しません。
    • SELinuxはLSMの一部として実装しました
  2. 施行レベル

    • 動作モード
      • 許容 - のみログイン
      • 強制 - 強制され、ログに記録
    • ポリシータイプ
      • 一軸 - 開発段階に適用できる非常に軽量な戦略、非常にいくつかの制限は、
      • 閉じ込められた - カスタムポリシー
  3. ラベル(ラベル)、ルール(規則)とドメイン(ドメイン)

    • そのようなファイルやプロセスなどの任意のリソースでのSELinuxは、ラベル、ラベル、およびそれらの戦術の行動と意思決定が許可されています。
    • タブのような形をuser:rule:type:mls_level、前記本体タイプ。
    • リソースオブジェクトをクラスとしてマッピングされ、各クラスへのアクセスは許可で表されます
    • ルール形式allow domain types:classes permissions;、種々の部分の意味:
      • ラベルプロセス - ドメイン
      • タイプ - ラベルのリソースオブジェクト
      • リソースオブジェクトの特定のカテゴリ - クラス
      • 許可 - アクセス操作が実行します

背景と根拠

  • アンドロイド4.3の開始は、SELinuxはアプリケーションサンドボックスを強化するために使用されています
  • ルートプロセスを含むすべてのプロセスの強制アクセス制御のSELinuxの実装、
  • 施行モードでは、SELinuxの行動のセキュリティポリシーに違反する試みは、logcatとdmesgの中に記録されています
  • 拒否されているすべての許されない行動を示さない仕事への道を、拒否デフォルト
  • 2つの動作モード:許容対施行
  • サポートドメインごとpermissiveモード
  • 実装プロセス:
    • アンドロイド4.3許容
    • アンドロイド4.4部分の施行
    • アンドロイド5.0の完全施行

主なドキュメント

  • SELinuxポリシーは、内のファイルsystem/sepolicyのディレクトリ。
  • 一般的には直接変更する必要はありませんsystem/sepolicyが、むしろ/デバイス/メーカー/デバイス名へ / sepolicyのディレクトリ定義されているデバイスのポリシーファイル
  • 文書を変更または作成するには、SELinuxの実装の必要性:
    • 新しいポリシーのソースファイル(* .TE) - ドメインとそのラベル
    • 更新BoardConfig.mk - ビルドシステムは、新しく作成したディレクトリsepolicy含み
    • file_contexts-タグ定義ファイル。あなたは、ファイルシステムを再コンパイルまたは実行する必要がありますrestorecon有効にするコマンドを。システムのアップグレードは、自動的にシステムとユーザのパーティションを更新します。ファイルには、init.board.rc追加restorecon_recursive自動的に他のパーティションを更新することができます。
    • genfs_contexts - ファイルシステムの設定ファイルタグの拡張属性をサポートしていませんPROC、VFAT、ため。この設定ファイルは、コア戦略の一部としてロードされます。しかし、再起動するか、アンロードされ、作成されたノードに反映させる再ロードする必要があります。
    • property_contexts - Androidのシステムプロパティのラベルを設定します。このファイルは、システムの起動時にinitによって設定され、selinux.reload_policy 1がロードされています
    • service_contexts - [設定]タブのAndroid用バインダーサービスは、このファイルは、システムの起動時にservicemanagerによって設定され、selinux.reload_policy 1がロードされています
    • seapp_contexts - [設定]タブのアプリのプロセスやファイル。受精卵プロセスアプリによって設定され、installdシステムによって開始されたときに読むとselinux.reload_policyを開始1
    • mac_permissions.xml-アプリとセットseinfo、と呼ばれる署名ベースのパッケージseapp_contextsのラベルを設定するためのアプリのためのseinfo使用。system_server起動時にこのファイルを読み込みます
  • 使用したビルドシステムBOARD_SEPOLICY_DIRSなど新しいポリシーファイルを追加するなどの変数を

初期セットアップ

  1. 初期化初期化

    • INIT最初のカーネルドメインで実行されます。":R:カーネル:S0 U" それ
    • 監査ログおよびコールバック関数を設定します
    • ロード/ sepolicyポリシーファイル
    • 設定された動作モードは:お使いのシステム構成が可能な場合はpermissiveモードは、そうでないモードを強制、カーネルコマンドラインパラメータ指定されたモードに設定されています
    • /file_contexts提供/initラベル。それが実行するように設定されている場合、ルートファイルシステムは、拡張属性をサポートしていません。
    • 有効にする方針で再実行し、独自の、今回の転送ルールにINIT、INIT開始は、ドメインの実行を初期化。
    • 監査ログおよびコールバック関数を設定します
    • ロード/file_contextsproperty_contexts
    • ロードよると/file_contexts、設定/dev/dev/socketおよびその他のラベルファイルシステムとディレクトリを。
    • システム起動のすべての段階で、initrcファイルによって制御される、ファイルシステムとディレクトリrestoreconコマンドのコマンド実行の必要性は、ファイルのラベルを設定します
    • selinux.reload_policyセット1に、再装填戦略、を含みます/sepolicyfile_contextsproperty_contexts
  2. バインダーの初期化

    • servicemanagerサービスから開始すると、/service_contexts各サービスに対応するコンテキストファイルを読み込みます
    • リロードポリシーかどうかを監視するためのオープンSELinuxのステータスクエリーインターフェイス。
    • 監査ログおよびコールバック関数を設定します
    • リロードあれば、それはあまりにも、その後、リロード、政策があまりにもリロードするかどうかをチェックするために、要求バインダーを受信するたびに/service_contexts
  3. 受精卵の初期化

    • アプリケーションが起動するたびに、ネイティブ関数によって受精卵が子プロセスにロードされ/seapp_contexts、アプリケーションのコンテキストを計算する過程を
    • チェック、それは新しい要求を受信するたびにinstalld /seapp_contextsあなたは、このようなリロードする必要性と、更新する必要があるかどうか/seapp_contexts、ファイルを
  4. system_server 初期化

    • 開始からPMSは、ときに/etc/mac_permissions.xml各パケット(もしあれば)のための情報seinfo読み。

おすすめ

転載: www.cnblogs.com/ntiger/p/12141932.html