Loading services/core/java/com/android/server/pm/PackageManagerService.java +103 −0 Original line number Original line Diff line number Diff line Loading @@ -165,6 +165,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.net.Uri; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; import android.os.Binder; import android.os.Build; import android.os.Build; import android.os.Bundle; import android.os.Bundle; Loading Loading @@ -4195,6 +4196,81 @@ public class PackageManagerService extends IPackageManager.Stub { killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED); killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED); } } /** * 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); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); } } } } } } } } @Override @Override public void resetRuntimePermissions() { public void resetRuntimePermissions() { mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission( Loading Loading @@ -8088,6 +8164,8 @@ public class PackageManagerService extends IPackageManager.Stub { Log.d(TAG, "Scanning package " + pkg.packageName); Log.d(TAG, "Scanning package " + pkg.packageName); } } final PackageParser.Package oldPkg; synchronized (mPackages) { synchronized (mPackages) { if (mPackages.containsKey(pkg.packageName) if (mPackages.containsKey(pkg.packageName) || mSharedLibraries.containsKey(pkg.packageName)) { || mSharedLibraries.containsKey(pkg.packageName)) { Loading @@ -8096,6 +8174,13 @@ public class PackageManagerService extends IPackageManager.Stub { + " already installed. Skipping duplicate."); + " already installed. Skipping duplicate."); } } final PackageSetting oldPkgSetting = mSettings.peekPackageLPr(pkg.packageName); if (oldPkgSetting == null) { oldPkg = null; } else { oldPkg = oldPkgSetting.pkg; } // If we're only installing presumed-existing packages, require that the // If we're only installing presumed-existing packages, require that the // scanned APK is both already known and at the path previously established // scanned APK is both already known and at the path previously established // for it. Previously unknown packages we pick up normally, but if we have an // for it. Previously unknown packages we pick up normally, but if we have an Loading Loading @@ -8968,6 +9053,24 @@ public class PackageManagerService extends IPackageManager.Stub { // This is a regular package, with one or more known overlay packages. // This is a regular package, with one or more known overlay packages. createIdmapsForPackageLI(pkg); createIdmapsForPackageLI(pkg); } } 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); } }); } } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +103 −0 Original line number Original line Diff line number Diff line Loading @@ -165,6 +165,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.net.Uri; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; import android.os.Binder; import android.os.Build; import android.os.Build; import android.os.Bundle; import android.os.Bundle; Loading Loading @@ -4195,6 +4196,81 @@ public class PackageManagerService extends IPackageManager.Stub { killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED); killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED); } } /** * 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); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); } } } } } } } } @Override @Override public void resetRuntimePermissions() { public void resetRuntimePermissions() { mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission( Loading Loading @@ -8088,6 +8164,8 @@ public class PackageManagerService extends IPackageManager.Stub { Log.d(TAG, "Scanning package " + pkg.packageName); Log.d(TAG, "Scanning package " + pkg.packageName); } } final PackageParser.Package oldPkg; synchronized (mPackages) { synchronized (mPackages) { if (mPackages.containsKey(pkg.packageName) if (mPackages.containsKey(pkg.packageName) || mSharedLibraries.containsKey(pkg.packageName)) { || mSharedLibraries.containsKey(pkg.packageName)) { Loading @@ -8096,6 +8174,13 @@ public class PackageManagerService extends IPackageManager.Stub { + " already installed. Skipping duplicate."); + " already installed. Skipping duplicate."); } } final PackageSetting oldPkgSetting = mSettings.peekPackageLPr(pkg.packageName); if (oldPkgSetting == null) { oldPkg = null; } else { oldPkg = oldPkgSetting.pkg; } // If we're only installing presumed-existing packages, require that the // If we're only installing presumed-existing packages, require that the // scanned APK is both already known and at the path previously established // scanned APK is both already known and at the path previously established // for it. Previously unknown packages we pick up normally, but if we have an // for it. Previously unknown packages we pick up normally, but if we have an Loading Loading @@ -8968,6 +9053,24 @@ public class PackageManagerService extends IPackageManager.Stub { // This is a regular package, with one or more known overlay packages. // This is a regular package, with one or more known overlay packages. createIdmapsForPackageLI(pkg); createIdmapsForPackageLI(pkg); } } 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); } }); } } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); Loading