Android permission mechanism (i) permission to apply and save

Source: Internet
Author: User
Tags tagname least privilege

Android uses sandboxes security, and each app has a corresponding pid,uid, resources, data, and basic APIs. You need to declare permissions when the app needs additional APIs that are not available in the sandbox.

In this article, we will explore how the permissions information for the APK application is saved to the system.

I. Declaration of authority 1. Declaring permissions in Androidmanifest.xml

Androidmanifest.xml located in the project root directory

Declaring permissions before <activity> tags

    • Declares the permissions that the app needs to use
    • Android requires permissions to be explicitly declared in the manifest file and not allowed to be declared dynamically at run time
2. "Least Privilege Principle"
    • Do not apply if you do not need it
    • Less permissions, more security for system and apps
      • Some APIs may be attacked by malicious
    • GooglePlay will select the corresponding device according to
      • Fewer permissions, more device-oriented types

Reference: Androiddeveloper->securitytips->using Permissions

Second, the construction process of Packagemanagerservice

    • Systemserver calls the Main method of Packagemanagerservice (pkms) to construct the object
    • PKMS will scan/system/app,/system/priv-app,/data/app, ... Wait for the APK in the directory
    • The androidmanifest information of the APK is dynamically stored in the pkms attribute member

Third, the APK installation process

    • ADBD is the deamon process, listening to the ADB command on the host side
    • adbd Send Shell command start script pm (EXEC)
    • The main method of Pm.jar is executed

    • Copy the APK to/data/app/and start parsing the androidmanifest tag information
    • Similarly to the PKMs constructor, calls to Parsepackage () and Scanpackageli () processing

Four, two data structures: Packageparser.package and SETTINGS.MUSERIDS1. Packageparser.package

The corresponding types of mpackages in pkms are:

Keys is String (package name), values is package.  This also serves//as the lock for the global state.  Methods that must is called with//this lock held has the prefix "LP". Final hashmap<string, packageparser.package> Mpackages =        new hashmap<string, packageparser.package> ();

Some attribute members and methods are as follows:

From the above two processes, we can see that pkms will call Packageparser when Packagemanagerservice (pkms) starts (i.e. Systemserver boot) and installs APK::p arsepackage () and Scanpackageli () method.

So let's analyze the effect of these two methods:

/frameworks/base/core/java/android/content/pm/packageparser.java

PackageParser.Package.parsePackage ():

private package Parsepackage (Resources res, xmlresourceparser parser, int flags, String[] outerror) throws Xmlpullparserexception, IOException {String pkgname = parsepackagename (parser, Attrs, FL    AGS, Outerror);    Final Package pkg = new package (pkgname);    ... int outerdepth = parser.getdepth (); while (type = Parser.next ())! = Xmlpullparser.end_document && (type! = Xmlpullparser.end_tag | | parser . getdepth () > Outerdepth)) {if (type = = Xmlpullparser.end_tag | | type = = xmlpullparser.text) {Conti        Nue        } String TagName = Parser.getname ();        if (Tagname.equals ("Application")) {//...} }/* ... */else if (tagname.equals ("Uses-permission")) {if (!parseusespermission (pkg, res, parser, Attrs, out            Error)) {return null; }}}//... return pkg;} 

Use Androidmanifest.xml to get the package name, then parse the XML file's tag and call the appropriate method. Call the Parseusespermission () method as the "uses-permission" label corresponds.

/frameworks/base/core/java/android/content/pm/packageparser.java

Packageparser.parseusespermission ():

Private Boolean parseusespermission (Package pkg, Resources res, Xmlresourceparser parser, AttributeSet attrs, string[] outerror) throws Xmlpullparserexception, IOException {//... if (maxsdkvers Ion = = 0) | | (maxsdkversion >= Build.VERSION.RESOURCES_SDK_INT))            {if (name = null) {int index = PKG.REQUESTEDPERMISSIONS.INDEXOF (name);                if (index = =-1) {Pkg.requestedPermissions.add (Name.intern ()); Pkg.requestedPermissionsRequired.add (required?            Boolean.TRUE:Boolean.FALSE); } else {if (pkg.requestedPermissionsRequired.get (index) = required) {Outerror[0] = "C                    onflicting <uses-permission> Entries ";                    Mparseerror = packagemanager.install_parse_failed_manifest_malformed;                return false;    }}}} xmlutils.skipcurrenttag (parser); return true;}

Parseusespermission () Determines whether the permission has been saved, and if not, add to the pkg requestedpermissions (ArrayList).

Let's continue looking at the Scanpackageli () method:

/frameworks/base/services/java/com/android/server/pm/packagemanagerservice.java

Packagemanagerservice.scanpackageli (Packageparser.package, ...)

Private Packageparser.package Scanpackageli (packageparser.package pkg, int parseflags, int scanmode, long Currentti Me, Userhandle user) {//To determine if the APK has been installed, skip duplicate install//check whether the library of non-system app is mapped to the correct path//check if you need to rename the original package name//for the new    APK Create packagesetting//verify APK signature//Verify that the APK contentprovider is in conflict with the existing APK//unzip the APK library into the corresponding Directory//writer Synchronized (mpackages) {//We don ' t expect installation to fail beyond this point, if ((SCANMODE&AMP;SC        An_monitor)! = 0) {mappdirs.put (Pkg.mpath, pkg);        }//Add the new setting to Msettings MSETTINGS.INSERTPACKAGESETTINGLPW (pkgsetting, pkg);        Add the new setting to Mpackages mpackages.put (pkg.applicationInfo.packageName, pkg);        Make sure we don ' t accidentally delete the its data.        Final iterator<packagecleanitem> iter = MSettings.mPackagesToBeCleaned.iterator ();   while (Iter.hasnext ()) {Packagecleanitem item = Iter.next ();         if (Pkgname.equals (Item.packagename)) {iter.remove (); }}//Just Create the setting, don ' t add it yet.        For already existing packages//The pkgsetting exists already and doesn ' t has to be created. When the new apk is installed, it will eventually be called to NEWUSERIDLPW () pkgsetting = MSETTINGS.GETPACKAGELPW (pkg, origpackage, Realname, suid, Destcodefile , Destresourcefile, Pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.flags, user, F        Alse);    // ...    } // ...}
2. Settings

There are several classes named Settings in Android, and this Settings is com.android.server.pm.Settings.

Where the Muserids attribute holds important information about the UID.

2.1. ADDUSERIDLPW ()

From the sequence diagram of the pkms construct, it can be seen that settings addshareduserlpw () and READLPW () are called successively before the pkms is Scandirli.

Public Packagemanagerservice (context context, Installer Installer, Boolean factorytest, Boolean Onlycore) {//.    ..    Msettings = new Settings (context);    MSETTINGS.ADDSHAREDUSERLPW ("Android.uid.system", Process.system_uid, Applicationinfo.flag_system);    MSETTINGS.ADDSHAREDUSERLPW ("Android.uid.phone", Radio_uid, Applicationinfo.flag_system);    MSETTINGS.ADDSHAREDUSERLPW ("Android.uid.log", Log_uid, Applicationinfo.flag_system);    MSETTINGS.ADDSHAREDUSERLPW ("ANDROID.UID.NFC", Nfc_uid, Applicationinfo.flag_system);    MSETTINGS.ADDSHAREDUSERLPW ("Android.uid.bluetooth", Bluetooth_uid, Applicationinfo.flag_system);    MSETTINGS.ADDSHAREDUSERLPW ("Android.uid.shell", Shell_uid, Applicationinfo.flag_system); Synchronized (Minstalllock) {//writer synchronized (mpackages) {//... susermanager = new Usermanag        Erservice (context, this, minstalllock, mpackages);        Readpermissions (); Mfoundpolicyfile = Selinuxmmac.readinstaLlpolicy (); Mrestoredsettings = MSETTINGS.READLPW (This, susermanager.getusers (false), msdkversion, Monlycore);

The ADDSHAREDUSERLPW () method is useful if the androidmanifest of an app is declared android:shareduserid= "com.android.process", Its UID is the same as the process UID in the attribute value.
Of course, the premise is that both apk signatures (signature) are the same.

In this way, the process can gain access to the UID.

The READLPW () is the creation of a new UID. Whether you call ADDSHAREDUSERLPW () or READLPW (), you will eventually be called to ADDUSERIDLPW ().

private boolean adduseridlpw (int uid, object obj, object name) {if (uid > Proc Ess.    Last_application_uid) {return false;        } if (uid >= process.first_application_uid) {int N = Muserids.size ();        Final int index = UID-PROCESS.FIRST_APPLICATION_UID;            while (index >= N) {muserids.add (null);        n++;                    } if (Muserids.get (index) = null) {Packagemanagerservice.reportsettingsproblem (Log.error,            "Adding Duplicate User id:" + uid + "name=" + name);        return false;    } muserids.set (index, obj);                    } else {if (motheruserids.get (UID) = null) {Packagemanagerservice.reportsettingsproblem (Log.error,            "Adding Duplicate Shared ID:" + uid + "name=" + name);        return false;    } motheruserids.put (uid, obj); }

Muserids is a ArrayList, with the UID minus the value of First_application_uid as the subscript index, and the corresponding obj is the object type, which is actually packagesetting
(Packagesetting inherited from Packagesettingbase,
And Packagesettingbase inherits from Grantedpermissions.
Grantedpermissions has a grantedpermissions of type HashSet, a string holding the permission)

2.2. NEWUSERIDLPW ()

The above ADDUSERIDLPW is called when the pkms is started. When installing the new APK, the call is NEWUSERIDLPW.

Private Packageparser.package Scanpackageli (packageparser.package pkg,        int parseflags, int scanmode, long CurrentTime, Userhandle user) {    //writer    synchronized (mpackages) {        //Just Create the setting, don ' t add it yet. For already existing packages        //The pkgsetting exists already and doesn ' t has to be created.        Create packagesetting        pkgsetting = MSETTINGS.GETPACKAGELPW (pkg, origpackage, Realname, suid, Destcodefile) for the new APK,                Destresourcefile, Pkg.applicationInfo.nativeLibraryDir,                pkg.applicationInfo.flags, user, false);        if (pkgsetting = = null) {            SLOG.W (TAG, "Creating application Package" + Pkg.packagename + "failed");            Mlastscanerror = Packagemanager.install_failed_insufficient_storage;            return null;}}            }

Will eventually be called to NEWUSERIDLPW ():

private int newuseridlpw (Object obj) {    /Let ' s is stupidly inefficient    for now ... Final int N = Muserids.size ();    for (int i = 0; i < N; i++) {        if (muserids.get (i) = = null) {            muserids.set (i, obj);            return process.first_application_uid + i;        }    }    None left?    if (N > (process.last_application_uid-process.first_application_uid)) {        return-1;    }    Muserids.add (obj);    return process.first_application_uid + N;}

If the newly installed apk has Android:shareduserid, Scanpackageli () will call GETSHAREDUSERLPW () and will eventually be called to NEWUSERIDLPW (), which we will not explore in detail.

Through the above analysis, we can draw the following conclusions:

    • Systemserver Scan APK when booting and installing APK
    • The label information obtained after the scan is saved in pkms.mpackages and Settings.muserids, not in the file
    • Tag information is stored in two different data structures and should have different applications

V. Obtaining PackageInfo through Packagemanager

After we have saved the APK information, we can use Packagemanager to indirectly obtain the information in pkms. Packagemanager.getpackageinfo () is the public interface for Android API Level 1:

Public abstract PackageInfo Getpackageinfo (String packagename, int flags)

The Getpackageinfo () through aidl,pkms is called to:

/frameworks/base/services/java/com/android/server/pm/packagemanagerservice.java

Packagemanagerservice.getpackageinfo ()

@Overridepublic packageinfo getpackageinfo (String packagename, int flags, int userId) {    if (!susermanager.exists ( USERID)) return null;    Enforcecrossuserpermission (Binder.getcallinguid (), UserId, False, "get package Info");    Reader    synchronized (mpackages) {        Packageparser.package p = mpackages.get (packagename);        if (debug_package_info)            log.v (TAG, "getpackageinfo" + PackageName + ":" + P);        if (P! = null) {            return Generatepackageinfo (p, flags, userId);        }        if ((Flags & packagemanager.get_uninstalled_packages)! = 0) {            return GENERATEPACKAGEINFOFROMSETTINGSLPW ( PackageName, flags, userId);        }    }    return null;}

In this way, the <uses-permission> information of the APK can be obtained by the third party app.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.