Android permission system

Android system provides each application with a secure operating environment, mutual isolation between different programs, data, applications and other private resources, the outside world can not access. This safe operating environment by Android's permission system (may be called a sandbox system) to provide. This paper briefly record the basic building blocks of Android permission system and key code mechanism of implementation.

The main module

Android permission system can be divided into four modules:

  1. Based on the permissions system user ID
  2. Capability privilege system
  3. Android Permission System
  4. SELinux permissions system

Based on the permissions system user ID

The permission system is based on UID process to control the process access to files and other resources. Briefly, every process has a UID and GID one or more attributes; each file having a UID and a GID property, and there are three sets of permission bits, respectively, and their UID same process, the same process GID as well as other unrelated processes to a file read, write, and execute access. Kernel to UID as the basic unit of granularity rights management. On the process of specific access rules file, you can access UNIX / Linux manual or some books. ( "UNIX Advanced Programming Environment" section 4.5).

In a typical UNIX / Linux multi-user system, the system log for each user is assigned a UID, the granularity of access control to a single user. Android system is not the traditional sense of the concept of user logon, but the UID assigned to each application, so the size of a single rights management applications. Specific operation is as follows.

  1. When the application is installed, a distribution system for the application UID. PackageManagerService default assigned a new UID and GID for each application. If the application is filed for some special runtime permissions, then assign (actually add it) an additional set of GID Group. Two applications developed by the same developer (same signature), can be shared UID and GID, just need to declare the same in AndroidManifest the android:sharedUserIdproperty. Written application together UID / GID and other property packages.listand packages.xmldocuments.

     // 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. When you start the application process, ActivityManagerService UID to PackageManagerService query application / GID and other information, and that information is passed to the Zygote process as a parameter. Zygote fork out the application process for the child process, and so that the application process will run its own identity owned UID UID parameter is set according to the child's / GID up.

     // 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. Setting the application file permissions

    a. Set APK-readable file permissions for all users, so that the system or other application can access the application code.

    b. Data directory system created for the application, set the executable (search) for other users. If you do not set as executable, any user data files can not be shared with other applications.

         // 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. Application data files created by Context.openFileOutput Android and other interfaces by default other users can not read and write. If the user specifies MODE_WORLD_READABLEor MODE_WORLD_WRITEABLEis set other user readable or writable. The new versions of both mode has been abolished.

          // 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);
         }

    Data file d. Applications by File.createNewFile () Java interface to create a default only he can read and write. File permissions created in this way associated with the current process umask setting. init process the Android system in the creation of system services (including zygote), set the umask to 077, application inherited umask zygote, and it is also 077, it indicates that only retains the same UID access, allowing only process the same UID (also It is his) visit.

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

Capability mechanism

Rights management mechanism based on the UID, there is a special UID 0, the so-called root user, have root authority is not bound by rights mechanisms. And some system resources and capabilities, only the root user can use. So the system a lot of core services, such as adbd, zygote run as root, and these system services and frequently interact with the application, these services security vulnerabilities, it is easy to be exploited malicious applications, perform mention the right to operate, breakthrough system access control list. So Android capability mechanism to limit further use UID permission to zero.

Capability mechanism will be only the root user has access privileges is further subdivided into a set of capabilities. Each thread has four sets of bits to represent the authority itself owned by:

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

Which represents CapInh execute permissions execve will retain; CapEff indicates that the thread current privilege; CapPrm represents the maximum limit of CapInh and CapEff; CapBnd representing the maximum authority of threads that can be obtained.

Android system, adbd zygote is created and the process for application services. zygote service creates a child process, the child returns to the former system, CapBnd clear, so that even if the child using the system vulnerability to gain the root uid, still do not have any super powers. adbd then after performing the necessary task privilege, clear CapBnd, will reduce their own rights.

// 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 Permission System

The default application can only access their own files and a very small amount of system resources. Want to get more resources systems and other applications, you need permission mechanism.

Resource / service provider requires explicit permission of the caller by AndroidManifest; application requests permission in the manifest, the system determines which permissions granted during installation or operation.

Permission Definition

Android Permission may be divided into three types, each type of permission is defined as follows:

  1. Builtin permission

    System /etc/permissions/*.xmldefinition. Each permission corresponds to a 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>

    Application of a system built for each grant permission, the application will give added a GID corresponding to the application ID groups in the added group

    // 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. Normal

    Normal permission is system (android package), system applications and third-party applications in their own rights AndroidManifest defined. For example READ_CONTACTSother system permissions are defined in the AndroidManifest framework-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. Dynamic

    You can dynamically add permissions defined. Reference android developer

Permission check

  1. Explicit Buildtin permission verification function in the kernel, or verify permissions UID-based mechanisms.

    Kernel check on the INTERNET permission

    //
    // 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-based privilege checking. To sdcard read and write permissions, for example, sdcard directory permissions set to sdcard_rw group can read and write (see permissions for each process is not the same, here in shell user as an example). Only with the WRITE_MEDIA_STORAGEright to obtain a sdcard_rwGID, to access the sdcard directory.

    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. Check Normal and dynamic permissions

    Two cases. For access to the program component Activity, Service, etc., permission checks by the AMS function call to determine whether lawful authority.

    Service or application service system for external services, you can call your own functions in the function permission check function checks whether the caller has permission.

    PackageManager.checkPermission()
    Context.checkPermission()

SELinux

SELinux in 8.0 and later for compatibility treble, made major changes, just to summarize the record about some of the concepts and principles described in official documents before 8.0.

basic concepts

  1. Mandatory Access Control (MAC)

    • SELinux is a mandatory access control system on the Linux system, relative to the already familiar DAC (Discretionary Access Control)
    • Discretionary access control, each owner has the resources that the resource owner, is the main access to resources can be controlled. This is usually coarse-grained privileges and easily lead to error propagation
    • MAC access to centralized management of resources, the problem does not exist DAC
    • SELinux implemented as part of the LSM
  2. Enforcement levels

    • Operating mode
      • Permissive - Only logged
      • Enforcing - Enforced and logged
    • Policy type
      • Unconfined - very lightweight strategy, very few restrictions, applicable to the development stage
      • Confined - custom policy
  3. Label (labels), the rules (rules) and domains (domains)

    • SELinux in any resources, such as files and processes have a decision with labels, labels, and behavior of those tactics are allowed.
    • Shaped like a tab user:rule:type:mls_level, wherein the main part type.
    • Resource object is mapped as a class, access to each class is represented by permission
    • The rule form allow domain types:classes permissions;, where the various moieties meanings:
      • label process - domain
      • type - label resource object
      • Specific categories of resource object - class
      • permission - access operations performed

Background and rationale

  • android 4.3 start, SELinux is used to strengthen the application sandbox
  • SELinux implementation of mandatory access control for all processes, including the root process
  • Under Enforcing mode, any attempt to violate the security policy of SELinux behavior is recorded in the logcat and dmesg
  • Default Deny way to work, that does not show any impermissible behavior are rejected
  • Two operating modes: permissive vs. enforcing
  • Supports per-domain permissive mode
  • Implementation process:
    • android 4.3 permissive
    • android 4.4 partial enforcing
    • android 5.0 full enforcing

Key document

  • SELinux policy files in system/sepolicythe directory.
  • Generally do not need to be modified directly system/sepolicy, but rather to the / device / manufacturer / device-name / sepolicy directory defined device policy files
  • SELinux implementation need to modify or create documents:
    • The new policy source file (* .te) - domain and its label
    • Update BoardConfig.mk - the build system includes sepolicy the newly created directory
    • file_contexts- Tag definition file. You must recompile the file system or execute restorecona command to take effect. The system upgrade will automatically update the system and user partitions. In the file, add init.board.rc restorecon_recursivecan automatically update the other partitions.
    • genfs_contexts- for the proc, vfat, which do not support the extended attributes of a file system settings file tags. This configuration file is loaded as part of the core strategy. But the need to restart or unloaded and reloaded to take effect on nodes that have been created.
    • property_contexts- Set the Android system property label. This file is set by init at system startup and selinux.reload_policy 1 is loaded
    • service_contexts - Settings tab Android binder services, this file is set by servicemanager at system startup and selinux.reload_policy 1 is loaded
    • seapp_contexts- Settings tab app processes and files. Set by the zygote process app and start when initiated by installd the system to read and selinux.reload_policy 1
    • mac_permissions.xml- signature-based package called app and set seinfo, seapp_contextsuse seinfo for the app to set the label. system_serverReads this file on startup
  • Build system using BOARD_SEPOLICY_DIRSvariables such as adding a new policy file

Initial Setup

  1. Init Initialization

    • init first run in the kernel domain. That "u: r: kernel: s0"
    • Setting audit log and callback functions
    • Load / sepolicy policy file
    • Set operating mode: If your system configuration allows Permissive mode is set to the kernel command line parameters specified mode, otherwise Enforcing mode
    • The /file_contextsprovided /initlabel. Root file system does not support extended attributes, when it is set to run
    • init to re-execute their own, this time transfer rule in a policy to take effect, init starts init domain execution.
    • Setting audit log and callback functions
    • Load /file_contextsandproperty_contexts
    • According loaded /file_contexts, settings /dev, /dev/socketand other label file systems and directories.
    • Controlled by initrc file, at all stages of system startup, the need for file systems and directories restorecon command execution, set the file label
    • selinux.reload_policy set to 1, re-loading strategy, including /sepolicy, file_contexts,property_contexts
  2. Binder initialization

    • servicemanagerWhen the service starts, from /service_contextsreading each service corresponding context file
    • Open selinux status query interface for monitoring whether reload policy.
    • Setting audit log and callback functions
    • Each time it receives a request binder, to check whether the policy reload too, if reload too, then reload/service_contexts
  3. zygote initialization

    • Every time App starts, zygote by native function is loaded in the child process /seapp_contexts, the process of computing app context
    • installd each time it receives a new request, check /seapp_contextswhether you need to update, such as the need to reload the /seapp_contextsfile
  4. system_server initialization

    • When PMS from start /etc/mac_permissions.xmlreading seinfo information for each packet (if any).

Guess you like

Origin www.cnblogs.com/ntiger/p/12141932.html