OSDN Git Service

Merge tag 'android-8.1.0_r76' into oreo-x86
[android-x86/frameworks-base.git] / services / core / java / com / android / server / pm / PackageManagerService.java
index 0d3925c..6fada7e 100644 (file)
@@ -184,6 +184,7 @@ import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -3794,19 +3795,16 @@ public class PackageManagerService extends IPackageManager.Stub
      * <p>
      * Currently, there are three cases in which this can occur:
      * <ol>
-     * <li>The calling application is a "special" process. The special
-     *     processes are {@link Process#SYSTEM_UID}, {@link Process#SHELL_UID}
-     *     and {@code 0}</li>
+     * <li>The calling application is a "special" process. Special processes
+     *     are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li>
      * <li>The calling application has the permission
-     *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
+     *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li>
      * <li>The calling application is the default launcher on the
      *     system partition.</li>
      * </ol>
      */
     private boolean canViewInstantApps(int callingUid, int userId) {
-        if (callingUid == Process.SYSTEM_UID
-                || callingUid == Process.SHELL_UID
-                || callingUid == Process.ROOT_UID) {
+        if (callingUid < Process.FIRST_APPLICATION_UID) {
             return true;
         }
         if (mContext.checkCallingOrSelfPermission(
@@ -5853,6 +5851,83 @@ public class PackageManagerService extends IPackageManager.Stub
     }
 
     /**
+     * We might auto-grant permissions if any permission of the group is already granted. Hence if
+     * the group of a granted permission changes we need to revoke it to avoid having permissions of
+     * the new group auto-granted.
+     *
+     * @param newPackage The new package that was installed
+     * @param oldPackage The old package that was updated
+     * @param allPackageNames All package names
+     */
+    private void revokeRuntimePermissionsIfGroupChanged(
+            PackageParser.Package newPackage,
+            PackageParser.Package oldPackage,
+            ArrayList<String> allPackageNames) {
+        final int numOldPackagePermissions = oldPackage.permissions.size();
+        final ArrayMap<String, String> oldPermissionNameToGroupName
+                = new ArrayMap<>(numOldPackagePermissions);
+
+        for (int i = 0; i < numOldPackagePermissions; i++) {
+            final PackageParser.Permission permission = oldPackage.permissions.get(i);
+
+            if (permission.group != null) {
+                oldPermissionNameToGroupName.put(permission.info.name,
+                        permission.group.info.name);
+            }
+        }
+
+        final int numNewPackagePermissions = newPackage.permissions.size();
+        for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions;
+                newPermissionNum++) {
+            final PackageParser.Permission newPermission =
+                    newPackage.permissions.get(newPermissionNum);
+            final int newProtection = newPermission.info.protectionLevel;
+
+            if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
+                final String permissionName = newPermission.info.name;
+                final String newPermissionGroupName =
+                        newPermission.group == null ? null : newPermission.group.info.name;
+                final String oldPermissionGroupName = oldPermissionNameToGroupName.get(
+                        permissionName);
+
+                if (newPermissionGroupName != null
+                        && !newPermissionGroupName.equals(oldPermissionGroupName)) {
+                    final List<UserInfo> users = mContext.getSystemService(UserManager.class)
+                            .getUsers();
+
+                    final int numUsers = users.size();
+                    for (int userNum = 0; userNum < numUsers; userNum++) {
+                        final int userId = users.get(userNum).id;
+                        final int numPackages = allPackageNames.size();
+
+                        for (int packageNum = 0; packageNum < numPackages; packageNum++) {
+                            final String packageName = allPackageNames.get(packageNum);
+
+                            if (checkPermission(permissionName, packageName, userId)
+                                    == PackageManager.PERMISSION_GRANTED) {
+                                EventLog.writeEvent(0x534e4554, "72710897",
+                                        newPackage.applicationInfo.uid,
+                                        "Revoking permission", permissionName, "from package",
+                                        packageName, "as the group changed from",
+                                        oldPermissionGroupName, "to", newPermissionGroupName);
+
+                                try {
+                                    revokeRuntimePermission(packageName, permissionName, userId,
+                                           false);
+                                } catch (IllegalArgumentException e) {
+                                    Slog.e(TAG, "Could not revoke " + permissionName + " from "
+                                            + packageName, e);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
      * Get the first event id for the permission.
      *
      * <p>There are four events for each permission: <ul>
@@ -10746,6 +10821,8 @@ public class PackageManagerService extends IPackageManager.Stub
         String primaryCpuAbiFromSettings = null;
         String secondaryCpuAbiFromSettings = null;
 
+        final PackageParser.Package oldPkg;
+
         // writer
         synchronized (mPackages) {
             if (pkg.mSharedUserId != null) {
@@ -10846,6 +10923,12 @@ public class PackageManagerService extends IPackageManager.Stub
             final PackageSetting disabledPkgSetting =
                     mSettings.getDisabledSystemPkgLPr(pkg.packageName);
 
+            if (oldPkgSetting == null) {
+                oldPkg = null;
+            } else {
+                oldPkg = oldPkgSetting.pkg;
+            }
+
             String[] usesStaticLibraries = null;
             if (pkg.usesStaticLibraries != null) {
                 usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
@@ -11178,6 +11261,25 @@ public class PackageManagerService extends IPackageManager.Stub
                 mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
             }
         }
+
+        if (oldPkg != null) {
+            // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
+            // revokation from this method might need to kill apps which need the
+            // mPackages lock on a different thread. This would dead lock.
+            //
+            // Hence create a copy of all package names and pass it into
+            // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get
+            // revoked. If a new package is added before the async code runs the permission
+            // won't be granted yet, hence new packages are no problem.
+            final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
+
+            AsyncTask.execute(new Runnable() {
+                public void run() {
+                    revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames);
+                }
+            });
+        }
+
         return pkg;
     }
 
@@ -16894,7 +16996,6 @@ public class PackageManagerService extends IPackageManager.Stub
 
             if (!SELinux.restoreconRecursive(afterCodeFile)) {
                 Slog.w(TAG, "Failed to restorecon");
-                return false;
             }
 
             // Reflect the rename internally
@@ -18928,40 +19029,54 @@ public class PackageManagerService extends IPackageManager.Stub
         int count = 0;
         final String packageName = pkg.packageName;
 
+        boolean handlesWebUris = false;
+        final boolean alreadyVerified;
         synchronized (mPackages) {
             // If this is a new install and we see that we've already run verification for this
             // package, we have nothing to do: it means the state was restored from backup.
-            if (!replacing) {
-                IntentFilterVerificationInfo ivi =
-                        mSettings.getIntentFilterVerificationLPr(packageName);
-                if (ivi != null) {
-                    if (DEBUG_DOMAIN_VERIFICATION) {
-                        Slog.i(TAG, "Package " + packageName+ " already verified: status="
-                                + ivi.getStatusString());
-                    }
-                    return;
+            final IntentFilterVerificationInfo ivi =
+                    mSettings.getIntentFilterVerificationLPr(packageName);
+            alreadyVerified = (ivi != null);
+            if (!replacing && alreadyVerified) {
+                if (DEBUG_DOMAIN_VERIFICATION) {
+                    Slog.i(TAG, "Package " + packageName + " already verified: status="
+                            + ivi.getStatusString());
                 }
+                return;
             }
 
-            // If any filters need to be verified, then all need to be.
+            // If any filters need to be verified, then all need to be.  In addition, we need to
+            // know whether an updating app has any web navigation intent filters, to re-
+            // examine handling policy even if not re-verifying.
             boolean needToVerify = false;
             for (PackageParser.Activity a : pkg.activities) {
                 for (ActivityIntentInfo filter : a.intents) {
+                    if (filter.handlesWebUris(true)) {
+                        handlesWebUris = true;
+                    }
                     if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
                             Slog.d(TAG, "Intent filter needs verification, so processing all filters");
                         }
                         needToVerify = true;
+                        // It's safe to break out here because filter.needsVerification()
+                        // can only be true if filter.handlesWebUris(true) returns true, so
+                        // we've already noted that.
                         break;
                     }
                 }
             }
 
+            // Note whether this app publishes any web navigation handling support at all,
+            // and whether there are any web-nav filters that fit the profile for running
+            // a verification pass now.
             if (needToVerify) {
                 final int verificationId = mIntentFilterVerificationToken++;
                 for (PackageParser.Activity a : pkg.activities) {
                     for (ActivityIntentInfo filter : a.intents) {
-                        if (filter.handlesWebUris(true) && needsNetworkVerificationLPr(filter)) {
+                        // Run verification against hosts mentioned in any web-nav intent filter,
+                        // even if the filter matches non-web schemes as well
+                        if (filter.handlesWebUris(false) && needsNetworkVerificationLPr(filter)) {
                             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                     "Verification needed for IntentFilter:" + filter.toString());
                             mIntentFilterVerifier.addOneIntentFilterVerification(
@@ -18974,13 +19089,23 @@ public class PackageManagerService extends IPackageManager.Stub
         }
 
         if (count > 0) {
+            // count > 0 means that we're running a full verification pass
             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                     + " IntentFilter verification" + (count > 1 ? "s" : "")
                     +  " for userId:" + userId);
             mIntentFilterVerifier.startVerifications(userId);
+        } else if (alreadyVerified && handlesWebUris) {
+            // App used autoVerify in the past, no longer does, but still handles web
+            // navigation starts.
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
+            }
+            synchronized (mPackages) {
+                clearIntentFilterVerificationsLPw(packageName, userId);
+            }
         } else {
             if (DEBUG_DOMAIN_VERIFICATION) {
-                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
+                Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
             }
         }
     }
@@ -19344,6 +19469,12 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public boolean isPackageDeviceAdminOnAnyUser(String packageName) {
         final int callingUid = Binder.getCallingUid();
+        if (checkUidPermission(android.Manifest.permission.MANAGE_USERS, callingUid)
+                != PERMISSION_GRANTED) {
+            EventLog.writeEvent(0x534e4554, "128599183", -1, "");
+            throw new SecurityException(android.Manifest.permission.MANAGE_USERS
+                    + " permission is required to call this API");
+        }
         if (getInstantAppPackageName(callingUid) != null
                 && !isCallerSameApp(packageName, callingUid)) {
             return false;
@@ -19450,7 +19581,7 @@ public class PackageManagerService extends IPackageManager.Stub
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
-                                libEntry.info, 0, currUserId);
+                                libEntry.info, MATCH_KNOWN_PACKAGES, currUserId);
                         if (!ArrayUtils.isEmpty(libClientPackages)) {
                             Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
                                     + " hosting lib " + libEntry.info.getName() + " version "
@@ -19783,7 +19914,8 @@ public class PackageManagerService extends IPackageManager.Stub
      * Tries to delete system package.
      */
     private boolean deleteSystemPackageLIF(PackageParser.Package deletedPkg,
-            PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
+            PackageSetting deletedPs, int[] allUserHandles, int flags,
+            @Nullable PackageRemovedInfo outInfo,
             boolean writeSettings) {
         if (deletedPs.parentPackageName != null) {
             Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName);
@@ -19791,7 +19923,7 @@ public class PackageManagerService extends IPackageManager.Stub
         }
 
         final boolean applyUserRestrictions
-                = (allUserHandles != null) && (outInfo.origUsers != null);
+                = (allUserHandles != null) && outInfo != null && (outInfo.origUsers != null);
         final PackageSetting disabledPs;
         // Confirm if the system package has been updated
         // An updated system app can be deleted. This will also have to restore
@@ -19821,19 +19953,21 @@ public class PackageManagerService extends IPackageManager.Stub
             }
         }
 
-        // Delete the updated package
-        outInfo.isRemovedPackageSystemUpdate = true;
-        if (outInfo.removedChildPackages != null) {
-            final int childCount = (deletedPs.childPackageNames != null)
-                    ? deletedPs.childPackageNames.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                String childPackageName = deletedPs.childPackageNames.get(i);
-                if (disabledPs.childPackageNames != null && disabledPs.childPackageNames
-                        .contains(childPackageName)) {
-                    PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
-                            childPackageName);
-                    if (childInfo != null) {
-                        childInfo.isRemovedPackageSystemUpdate = true;
+        if (outInfo != null) {
+            // Delete the updated package
+            outInfo.isRemovedPackageSystemUpdate = true;
+            if (outInfo.removedChildPackages != null) {
+                final int childCount = (deletedPs.childPackageNames != null)
+                        ? deletedPs.childPackageNames.size() : 0;
+                for (int i = 0; i < childCount; i++) {
+                    String childPackageName = deletedPs.childPackageNames.get(i);
+                    if (disabledPs.childPackageNames != null && disabledPs.childPackageNames
+                            .contains(childPackageName)) {
+                        PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
+                                childPackageName);
+                        if (childInfo != null) {
+                            childInfo.isRemovedPackageSystemUpdate = true;
+                        }
                     }
                 }
             }
@@ -24096,9 +24230,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
             mSettings.writeKernelMappingLPr(ps);
         }
 
-        final UserManager um = mContext.getSystemService(UserManager.class);
+        final UserManagerService um = sUserManager;
         UserManagerInternal umInternal = getUserManagerInternal();
-        for (UserInfo user : um.getUsers()) {
+        for (UserInfo user : um.getUsers(false /* excludeDying */)) {
             final int flags;
             if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
@@ -24738,8 +24872,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                 continue;
             }
             final String packageName = ps.pkg.packageName;
-            // Skip over if system app
-            if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+            // Skip over if system app or static shared library
+            if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0
+                    || !TextUtils.isEmpty(ps.pkg.staticSharedLibName)) {
                 continue;
             }
             if (DEBUG_CLEAN_APKS) {
@@ -25745,11 +25880,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         }
         if (mExternalSourcesPolicy != null) {
             int isTrusted = mExternalSourcesPolicy.getPackageTrustedToInstallApps(packageName, uid);
-            if (isTrusted != PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT) {
-                return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
-            }
+            return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
         }
-        return checkUidPermission(appOpPermission, uid) == PERMISSION_GRANTED;
+        return false;
     }
 
     @Override