Detailed explanation of Android security mechanism

Publisher:泥匠手Latest update time:2012-04-29 Source: OFweek Keywords:Android Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1 Overview of Android security mechanism

Android is a system with separated permissions. This uses the existing permission management mechanism of Linux to assign different uids and gids to each Appl ic ation, so that the private data and access between different applications (both native and java layers can be isolated through this sandbox mechanism) can be isolated. At the same time, Android also expands on this basis and provides a permission mechanism, which is mainly used to subdivide permissions and control access to certain specific operations that applications can perform. It also provides a per-URI permission mechanism to provide ad-hoc access to certain specific data blocks.

1.1 uid, gid, gids

The basis of Android's privilege separation is built on the existing uid, gid, and gids of Linux.

UID. When Android installs an application, it will assign a uid to it (refer to the implementation of newUserLP in PackageManagerService). The uid of ordinary Android applications starts from 10000 (refer to Process.FIRST_APPLICATION_UID), and the uid below 10000 is the uid of the system process.

GID. For common applications, gid is equal to uid. Since the uid and gid of each application are different, both the native layer and the java layer can protect private data.

GIDS. gids are generated by the framework during the application installation process and are related to the specific permissions applied for by the application. If the corresponding permission applied for by the application is granted and there are corresponding gids, then the gids of the application will include this gid.

Detailed setting process of uid gid gids:

Please refer to startProcessLocked in ActivityManagerService. When starting a process through zygote, uid is directly passed to gid. Then zygote is used to fork a new process (forkAndSpecialize in zygote.java ) , and finally gid, uid and gids are set through Linux system calls in forkAndSpecializeCommon in the native layer (dalvik_system_zygote.c).

1.2 permission

A permission mainly contains three aspects of information: the name of the permission; the permission group it belongs to; and the protection level. A permission group refers to a collection of permissions divided into different groups according to their functions. Each permission group contains several specific permissions. For example, the COST_MONEY group contains android.permission.SEND_SMS, android.permission.CALL_PHONE and other cost-related permissions.

Each permission is identified by the protectionLevel: normal, dangerous, signature, signatureorsystem. Different protection levels represent the authentication method when the program wants to use this permission. Normal permissions can be used as long as they are applied for; dangerous permissions require user confirmation before they can be used during installation; signature and signatureorsystem permissions require the user's app and the system to use the same digital certificate.

The package's permission information is mainly specified in AndroidManifest.xml through some tags, such as tag, tag, tag, etc. If the package needs to apply for a certain permission, it needs to use the tag to specify it.

2 Android permission management mechanism

2.1 Framework permission mechanism

2.1.1 Installation entry

Permission initialization refers to the application of permission to the system, the system checks and authorizes, and establishes the corresponding data structure. In most cases, permissions are scanned from a package, which happens when the package is installed or upgraded. There are generally the following installation entrances:

n packageInstaller, which is triggered when a package is downloaded and installed. packageInstaller checks dangerous permissions through AppSecurityPermissions and prompts the user.

n pm command.

n adb install. Finally, pm install is called to install the apk package.

n Copy and install. PackageManagerService uses AppDirObserver to monitor /data/app/ and triggers installation if there is a copy.

These installation methods will eventually complete the installation of the program by calling the functions in PackageManagerService.

2.1.2 Permission creation

The first step is to extract permission information from AndroidManifest.xml. The following information is mainly extracted:

² shared uid

Specifies to share the same uid with other packages.

² permission

Extract the specified attributes of the permissions tag. It uses permissionInfo to describe the basic information of a permission. It needs to specify the protectedLevel information and the group information. It will be added to the permissions list structure of this package.

² permission-tree

Extract the permissions-tree tag attributes. Permissions-tree is also described by permissionInfo and added to the list structure of package permissions. Permission-tree is just a namespace to which some so-called Dynamic permissions are dynamically added. These permissions can be modified dynamically. These permission names must start with the name of permission-tree. It is not a permission itself, and has no protectedLevel and group. It only saves the package it belongs to and the permission name (with the package prefix).

² permission-group

Defines permission group information, represented by PermissionGroup. It does not represent a permission itself, but is added to the permissionGroups list of the package.

² uses-permission

Defines the permission name that the package needs to apply for. Add the permission name to the requestedPermissions list of the package.

² adopt-permissions

Store the name specified by this tag into the mAdoptPermissions list of the package. Name specifies that this package needs to adopt permissions from the package specified by name. Used when the system package is upgraded.

Step 2. Get the certificate in the Package, verify it, and save the signature information in the Package structure.

1. If the package comes from system img (system app), then you only need to obtain the signature information from the AndroidManifest.xml of the Package without verifying its integrity. However, if the package shares a uid with other packages, the signature stored in the sharedUser corresponding to the shared uid is inconsistent with it, and the signature verification fails.

2. If it is a normal package, you need to extract the certificate and signature information and verify the completeness of the file.

Step 3. If it is a normal package, clear the mAdoptPermissions field information of the package (only used for system package upgrades).

Step 4. If a shared user is specified in AndroidManifest.xml, first check the global list (mSharedUsers) to see if there is a SharedUserSetting data structure corresponding to the uid. If not, assign a new uid, create a SharedUserSetting and save it to the global list (mSharedUsers).

mUserIds stores the SharedUserSetting structure corresponding to the uids that have been allocated in the system. Each time when allocating, it always polls from the first one, finds the first free position i, and then adds FIRST_APPLICATION_UID.

Step 5. Create a PackageSettings data structure and bind PackageSettings to SharedUserSetting. PackageSettings saves the SharedUserSetting structure; SharedUserSetting uses the signature information in PackageSettings to fill its own internal signature information, and adds PackageSettings to a queue, indicating that PackageSettings is one of the sharers.

When creating, the packageName will first be used to query the global data structure mPackages to see if there is a corresponding PackageSettings data structure. If the PackageSettings data structure already exists (for example, the package has been uninstalled, but the data has not been deleted, and the package structure has been released), then compare the signature information in the package (scanned from AndroidManifest) with the signature information in PackageSettings to see if they match. If they do not match but it is a system package, then trust this package and update the signature information in the package to the existing PackageSettings. At the same time, if this package shares a uid with other packages, and the signature information saved in the shared uid does not match the current package, then the signature verification also fails.

Step 6. If the mAdoptPermissions field is not empty, process the adoption of the permission (change the owner of the permission to the current package from the PackageSettings corresponding to the specified package. This usually happens when the system app is upgraded. Before this, it is necessary to verify that the adopted package has been uninstalled, that is, check whether the package data structure exists).

Step 7. Add custom permissions. Add the permissionGroup defined in the package to the global list mPermissionGroups; add the permissions defined in the package to the global list (if it is a permission-tree type, add it to mSettings.mPermissionTrees, if it is a general permission, add it to mSettings.mPermissions).

Step 8. Clear inconsistent permission information.

1. Clear inconsistent permission-tree information. If the packageSettings field of the permission-tree is empty, it means that the package has not been parsed yet (if the code is executed to this point, packageSettings must have been created), remove it. If packageSettings is not empty, but the corresponding package data structure is empty (indicates that the package has been uninstalled, but the data is still retained), or the package data structure does not contain this permission-tree at all, then clear this permission-tree.

2. Clear inconsistent permission information. If the packageSettings or package structure is empty (the package is not parsed or uninstalled, but the data is retained), or the permission is not defined in the package at all, then clear the permission.

Step 9. Poll each package and grant permission.

1. Check the requested permissions and update the grantedPermissions list

2. If it has no shared user id set, then initialize its gids to mGlobalGids, which is read from permission.xml.

3. Traverse all the permissions applied for and perform the following checks

1) If the permission is normal or dangerous, pass the check.

2) If the permission requires signature verification. If the signature verification passes, the following checks are also required:

* If the program is upgraded and it is a system package, whether to grant the permission depends on whether the original package has been granted the permission. If it is granted, the check passes, otherwise it fails.

* If it is a new installation, then the check passes.

4. If the check in step 3 is passed, the permission is added to the grantedPermissions list of the package, indicating that the permission application is successful (granted). When the application is successful, the gids of the permission applied for is added to the gids of the package.

5. Set the permissionsFixed field to true, indicating that the permissions of this package have been modified. It will be prohibited to modify the permissions of non-system apps in the future.

2.1.3 Dynamic permission management

PackageManagerService provides addPermission/removePermission interfaces to dynamically add and remove some permissions. However, these permissions must be so-called dynamic permissions (BasePermission.TYPE_DYNAMIC).

If a package wants to add dynamic permissions, it must first declare the tag in the manifest. It is actually a permission namespace (for example, the permission "com.foo.far" is a member of the permission-tree "com.foo"), not a permission itself. A package can only add or remove permissions for its own permission-tree or for packages with the same uid.

Packages cannot use this interface to modify permissions statically applied for in the manifest, otherwise an exception will be thrown.

First, check whether this permission exists in the global permission list mSettings.mPermissions. If it exists and its type is BasePermission.TYPE_DYNAMIC, modify the permission information in the global table according to the passed permission information and trigger the persistence of permissions.xml.

If the permission is not found in the global permission list mSettings.mPermissions, first find the permissionTree where the permission is located, then add it to the global permission list mSettings.mPermissions, and trigger the persistence of permissions.xml.

2.1.4 Uri permission management

The following two interfaces are mainly used for Uri permission management (actually implemented in ActivityManagerService).

// Add read or write permissions to a content Uri for the specified uid and targetPkg.

public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri, int mode) throws RemoteException;

// Clear all permissions granted to a Uri via grantUriPermission.

public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode) throws RemoteException;

Analysis of the main implementation process of grantUriPermission.

grantUriPermission analysis:

1. Verify that the ProcessRecord and targetPkg of the caller are not empty. Otherwise, the test fails.

2. Verify that the requested mode is Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION, otherwise it will fail.

3. Make sure the parameter Uri is a content Uri. Otherwise, the detection fails.

4. Get the target ContentProvider through Uri. If it does not exist, the detection fails.

5. Get the uid corresponding to targetPkg from PackageManagerService.

6. Check whether the package corresponding to the target uid really needs this permission?

First determine whether you want to apply for read or write permission, and then check whether the corresponding readPermission writePermission field in the corresponding ContentProvider has saved the permission name. If the field is not empty, use the target uid and the permission name to find out whether the uid has been granted the permission in PackageManagerService. If the permission has been obtained, there is no need to apply for the Uri permission for this Activity, and return. Otherwise, continue to perform the following operations.

7. Check the grantUriPermissions switch variable of this ContentProvider to see if it allows granting permissions to other packages. If not, throw an exception.

8. Check if the ContentProvider has set the Uri filter type uriPermissionPatterns. If the filter type is set, match the Uri that needs to apply for permission with it. If the match is different, an exception is thrown.

9. Check if the caller has permission to access this Uri. If not, throw an exception.

10. Get the HashMap "Uri, UriPermission" data structure corresponding to the target uid from mGrantedUriPermissions. Generate UriPermission using target uid and Uri and save it in mGrantedUriPermissions.

revokeUriPermission implementation analysis.

Find the ContentProvider corresponding to the Uri, and then delete all permissions corresponding to the Uri in mGrantedUriPermissions.

2.2 Dynamic check of permission

The dynamic check here refers to the check that is performed when the package performs certain operations or accesses data during program execution. The corresponding check is when the application is installed or upgraded, PackageManagerService scans the static permission information in the package.

The implementation of the system's permission check-related mechanisms is mainly concentrated in PackageManagerService and ActivityManagerService. ActivityManagerService is mainly responsible for the identity check at the bottom uid level; PackageManagerService maintains a table of uids to the permissions it has and is granted. After passing the identity check of ActivityManagerService, PackageManagerService checks this table based on the requester's uid to determine whether it has the corresponding permissions.

In addition, the implementation of the per-URI permission mechanism also requires a table, which is maintained in ActivityManagerService, which establishes a mapping from content URI to components that are authorized to access this URI . However, it also needs the PackageManagerService mechanism to assist in its implementation.

2.2.1 Interfaces provided by the framework

The Android framework provides some interfaces for checking permissions for external access (including itself). These interfaces are mainly provided by ContextWrapper and implemented in ContextImpl. If the package receives an operation request from an external visitor, these interfaces can be called to check permissions. Generally, the check interfaces of these interfaces can be divided into two types: one is to return an error, and the other is to throw an exception.

It mainly includes the following groups:

n permission and uid check API

The following set of interfaces are mainly used to check whether a certain caller (or other packages or itself) has the permission to access a certain permission. The pid and uid can be specified in the parameters. If not specified, the framework will obtain the caller's uid and pid information through Binder and fill it in. The return value is PackageManager.PERMISSION_GRANTED or PackageManager.PERMISSION_DENIED.

public int checkPermission(String permission, int pid, int uid) // Check whether a certain uid and pid has permission

public int checkCallingPermission(String permission) // Check whether the caller has permission. If the caller is yourself, return PackageManager.PERMISSION_DENIED

public int checkCallingOrSelfPermission(String permission) // Check whether you or other callers have permission

The following group is similar to the above. If the check fails, an exception will be thrown and a message will be printed.

public void enforcePermission(String permission, int pid, int uid, String message)

public void enforceCallingPermission(String permission, String message)

public void enforceCallingOrSelfPermission(String permission, String message)

n per-URI inspection API

Add read or write permissions to a package to access the content Uri.

public void grantUriPermission(String toPackage, Uri uri, int modeFlags)

public void revokeUriPermission(Uri uri, int modeFlags)

Checks whether the package with a certain pid and uid has read and write permissions for uri. The return value indicates whether it is granted.

public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags)

public int checkCallingUriPermission(Uri uri, int modeFlags)

public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags)

public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags)

Checks whether the package with a certain pid and uid has read and write permissions for uri. If it fails, throws an exception and prints a message.

public void enforceUriPermission(Uri uri, int pid, int uid, int modeFlags, String message)

public void enforceCallingUriPermission(Uri uri, int modeFlags, String message)

public void enforceCallingOrSelfUriPermission(Uri uri, int modeFlags, String message)

public void enforceUriPermission(Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags, String message)

2.2.2 Implementation Analysis

The APIs provided in ContextImpl.java are actually encapsulated by the following interfaces in ActivityManagerService.

public int checkPermission(String permission, int pid, int uid) throws RemoteException; // Mainly used for general permission checks

public int checkUriPermission(Uri uri, int pid, int uid, int mode) throws RemoteException; // Mainly used for permission check of Content Uri

n Implementation analysis of checkPermission

1. If the passed permission name is null, then return PackageManager.PERMISSION_DENIED.

2. Determine whether the caller's uid meets the requirements.

1) If uid is 0, it means it is a process with root privileges and no control is performed on the privileges.

2) If the uid is the uid of the system server process, it means it is a system server and no control is applied to permissions.

3) If it is the ActivityManager process itself, no control is performed on permissions.

4) If the caller uid is inconsistent with the req uid passed in as a parameter, PackageManager.PERMISSION_DENIED is returned.

3. If the check in step 2 is passed, call PackageManagerService.checkUidPermission to determine whether the uid has the corresponding permission. The analysis is as follows.

1) First, it calls getUserI dLP to find the permission list of uid (that is, package) according to uid in the PackageManagerService.Setting.mUserIds array. Once found, it means that there is corresponding permission.

2) If not found, then look for it in PackageManagerService.mSystemPermissions. This information is read from /system/etc/permissions/platform.xml at startup. Here are some system-level application uid corresponding permissions.

3) Return the result.

Similarly, the implementation of checkUriPermission is mainly in ActivityManagerService, and the analysis is as follows:

1. If uid is 0, it means it is the root user, so the permissions are not controlled.

2. Otherwise, check whether the uid has this permission in the mGrantedUriPermissions table maintained by ActivityManagerService. If so, check whether it is requesting read or write permission.

3 Android Signature Mechanism

Regarding the signature mechanism, it is actually divided into two stages.

The package scanning phase requires integrity and certificate verification. The signature and certificate of a common package must be verified first. The specific method is to perform integrity checks on several files under the manifest. The integrity check includes all files in the jar package. If it is a system package, you only need to use the AndroidMenifest.xml file to extract the signature and verification information.

During the permission creation phase, if the package comes from the system img (system app), then trust it and use the new signature information to replace the old information. The premise is that if this package shares a uid with other packages, then the signature stored in the sharedUser corresponding to the shared uid is inconsistent with it, and the signature verification fails. Sometimes when an app is uninstalled but the data is not deleted, its PackageSettings information will be retained, which will store the signature information. This will cause inconsistencies when installing again.

3.1 Android Package Signature Principle

In Android, both the system and the app need to be signed. You can generate the public key and private key yourself through development/tools/make_key.

The android source code provides a tool. /out/host/linux-x86/framework/signapk.jar for manual signing. The main function of the signature is to limit the modification of the program to the same source. There are two main places in the system that will be checked. If it is a program upgrade installation, it is necessary to check whether the signature certificates of the new and old programs are consistent. If they are inconsistent, the installation will fail; for the protected level of the permission application is signature or signatureorsystem, it will check whether the certificates of the permission applicant and the permission declarant are consistent. Signature-related files can be found in the META-INF directory in the apk package.

The source code of signapk.jar is in build/tools/signapk. The signing process mainly consists of the following steps:

l Generate SHA1 signatures for all files except CERT.RSA, CERT.SF, and MANIFEST.MF

First, use SHA-1 to calculate the summary information of all non-directory files except CERT.RSA, CERT.SF, and MANIFEST.MF, then encode them using base64 and store them in MANIFEST.MF. If MANIFEST.MF does not exist, you need to create it. The storage format is entry name and the corresponding summary

l Generate a series of signatures based on the previously calculated SHA1 summary information and the private key and write them into CERT.SF

Calculate the SHA1 for the entire MANIFEST.MF and store the summary information in CERT.SF. Then use SHA1 to calculate the digital signature again for all the previously calculated summary information and write it to CERT.SF.

l Write the public key and signature information into CERT.RST

Use the private key to calculate the signature of the entire signature output file. At the same time, write the signature result and the previously claimed public key information into CERT.RSA for storage.

3.2 Package signature verification

The main logic of signature verification of a package during installation is implemented in the verifyCertificate function of the JarVerifier.java file. The main idea is to extract the certificate and signature information in cert.rsa, obtain the signature algorithm and other information, and then calculate it according to the previous method of signing the apk, and compare the obtained signature and summary information with the one saved in the apk.

Step 1. Extract the certificate information and verify the integrity of cert.sf.

1. First find out whether there are DSA and RSA files. If found, decode them and then read all the certificate lists in them (these certificates will be saved in the Package information for subsequent use).

2. Read the signature data information block list in this file, and only take the first signature data block. Read the publisher and certificate serial number.

3. According to the certificate serial number, match all the certificates obtained previously and find the matching certificate.

4. Read the signature algorithm and encoding method from the previously obtained signature data block

5. Read the cert.sf file and calculate the entire signature, compare it with the signature (in encoded format) in the data block, if they are the same, the integrity check is successful.

Step 2. Use the summary information in cert.sf to verify the integrity of MANIFEST.MF.

Extract the signature data blocks starting with SHA1-Digest-Manifest or SHA1-Digest from cert.sf (-Digest-Manifest is the summary information of the entire MANIFEST.MF, and the others are the summary information of other files in the jar package), and verify these data blocks one by one. The verification method is to regard cert.sf as many entries, each of which contains some basic information, such as the digest algorithm used in this entry (SHA1, etc.), which file in the jar package the digest is calculated for, and what the digest result is. When processing, first find the file information in each digest data, then read it from the jar package, and then use the digest algorithm before -Digest to calculate. If the calculation result matches the information saved in the digest data block, then the verification is completed.

Keywords:Android Reference address:Detailed explanation of Android security mechanism

Previous article:A new generation of smart sidewalks with WiFi and Bluetooth
Next article:NVIDIA GPU Big Reveal: 28nm's Contribution to Kepler's Energy Efficiency

Recommended ReadingLatest update time:2024-11-16 19:52

Google Pixel 4 downgraded from Android 11 to Android 10 and found a bug: facial recognition doesn't work
        On June 15th, Android 11 Beta 1 was officially launched last week, and Google Pixel models were the first to try it.   Considering that this is the Beta version of Android 11 and the system is not stable enough, many Pixel users choose to downgrade back to Android 10 after upgrading to Android 11. However, ne
[Mobile phone portable]
Android 12 has been released for a year: the version is fragmented and it’s a mess
What version of Android are you using? Including testing, Android 12 has been released for one year, but statistics from Uptodown show that Android 12 users account for only 2.6%, which is less than one-tenth of Android 11. Specifically, Android 11 is the version with the largest number of users at present, with a sha
[Mobile phone portable]
Android 12 has been released for a year: the version is fragmented and it’s a mess
Xiaomi joins hands with NXP to take the lead in adopting Android Ready SE technology to lead a new era of mobile security
In the context of an increasingly interconnected era, the security chip (SE) in mobile phones is particularly critical. It shoulders the important mission of protecting our digital identity. These specialized hardware components form a robust library of hardware designed to store and process highly sensitive informati
[Mobile phone portable]
The most powerful Android SoC is coming! The Snapdragon 8 Plus manufactured by TSMC is revealed
Today, industry insider @手机陶瓷高人 broke the news that 20,000 wafers of Qualcomm's 4nm Snapdragon 8 Gen1 plus wafers cast at TSMC are expected to be shipped in April in advance for delivery in the second quarter, and more than 50,000 4nm Gen1 plus wafers will be produced every quarter starting from the third quarter. The
[Mobile phone portable]
The most powerful Android SoC is coming! The Snapdragon 8 Plus manufactured by TSMC is revealed
It will take a long time for Huawei HMS to surpass Android and Apple
1. Ren Zhengfei: It is wrong to transfer the industrial chain to the country. Only globalization can bring competitiveness. According to Blue Blood Research, Ren Zhengfei accepted an exclusive interview with Jia Zheng, editor-in-chief of Dragon magazine, at Huawei's headquarters in Shenzhen on April 22. During this pe
[Mobile phone portable]
Google promises Pixel 4a system updates for at least three years: Android 14 worry-free
A few days ago, Google launched the Pixel 4a mobile phone. Although it still uses 4G network, the price starts at US$349 (about RMB 2,431), which is much cheaper than the iPhone SE. In terms of hardware, the Pixel 4a phone is equipped with a Snapdragon 730G processor, a 5.8-inch OLED screen, a perforated screen desi
[Mobile phone portable]
Design of low-power mobile ECG monitoring system based on Android
1 Introduction With the continuous development of information technology and medical level and the continuous improvement of people's living standards, more and more people have put forward higher requirements for personal and family health care, hoping to be able to understand their physical health at any time, and t
[Microcontroller]
Design of low-power mobile ECG monitoring system based on Android
Solar power generation technology application: ZTE's new Android smartphone Solar X500 supports solar charging
Mobile phones that support solar charging are nothing new. It is reported that ZTE is developing a new Android smartphone, the Solar X500, which will support solar charging technology. Unfortunately, no details have been disclosed yet. This model was exposed in the product list of Zagg, the manufacturer of invi
[New Energy]
Latest Power Management Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号