Loading services/core/java/com/android/server/pm/PackageManagerService.java +30 −6 Original line number Diff line number Diff line Loading @@ -202,6 +202,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; Loading Loading @@ -8696,7 +8697,7 @@ public class PackageManagerService extends IPackageManager.Stub } } // we're updating the disabled package, so, scan it as the package setting final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null, disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, null /* originalPkgSetting */, null, parseFlags, scanFlags, (pkg == mPlatformPackage), user); Loading Loading @@ -9874,6 +9875,8 @@ public class PackageManagerService extends IPackageManager.Stub private static class ScanRequest { /** The parsed package */ @NonNull public final PackageParser.Package pkg; /** The package this package replaces */ @Nullable public final PackageParser.Package oldPkg; /** Shared user settings, if the package has a shared user */ @Nullable public final SharedUserSetting sharedUserSetting; /** Loading @@ -9899,6 +9902,7 @@ public class PackageManagerService extends IPackageManager.Stub public ScanRequest( @NonNull PackageParser.Package pkg, @Nullable SharedUserSetting sharedUserSetting, @Nullable PackageParser.Package oldPkg, @Nullable PackageSetting pkgSetting, @Nullable PackageSetting disabledPkgSetting, @Nullable PackageSetting originalPkgSetting, Loading @@ -9908,6 +9912,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean isPlatformPackage, @Nullable UserHandle user) { this.pkg = pkg; this.oldPkg = oldPkg; this.pkgSetting = pkgSetting; this.sharedUserSetting = sharedUserSetting; this.oldPkgSetting = pkgSetting == null ? null : new PackageSetting(pkgSetting); Loading Loading @@ -10037,8 +10042,9 @@ public class PackageManagerService extends IPackageManager.Stub boolean scanSucceeded = false; try { final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, (pkg == mPlatformPackage), user); final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime); if (result.success) { Loading Loading @@ -10068,6 +10074,7 @@ public class PackageManagerService extends IPackageManager.Stub private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; final PackageParser.Package oldPkg = request.oldPkg; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final PackageSetting oldPkgSetting = request.oldPkgSetting; Loading Loading @@ -10237,7 +10244,7 @@ public class PackageManagerService extends IPackageManager.Stub } else { final int userId = user == null ? 0 : user.getIdentifier(); // Modify state for the given package setting commitPackageSettings(pkg, pkgSetting, user, scanFlags, commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags, (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); if (pkgSetting.getInstantApp(userId)) { mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); Loading Loading @@ -11163,8 +11170,9 @@ public class PackageManagerService extends IPackageManager.Stub * Adds a scanned package to the system. When this method is finished, the package will * be available for query, resolution, etc... */ private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { private void commitPackageSettings(PackageParser.Package pkg, @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { final String pkgName = pkg.packageName; if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { Loading Loading @@ -11504,6 +11512,22 @@ public class PackageManagerService extends IPackageManager.Stub } } } if (oldPkg != null) { // We need to call revokeRuntimePermissionsIfGroupChanged async as permission // revoke callbacks 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(() -> mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames, mPermissionCallback)); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.pm.PackageParser.Permission; import com.android.server.pm.SharedUserSetting; import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; Loading Loading @@ -90,6 +91,22 @@ public abstract class PermissionManagerInternal { public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated, @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback); /** * 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 packages * @param permissionCallback Callback for permission changed */ public abstract void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback); /** * Add all permissions in the given package. * <p> Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +86 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.os.storage.StorageManagerInternal; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -391,6 +392,82 @@ public class PermissionManagerService { return protectionLevel; } /** * 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 * @param permissionCallback Callback for permission changed */ private void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { 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.getProtection(); 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 int[] userIds = mUserManagerInt.getUserIds(); final int numUserIds = userIds.length; for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { final int userId = userIds[userIdNum]; final int numPackages = allPackageNames.size(); for (int packageNum = 0; packageNum < numPackages; packageNum++) { final String packageName = allPackageNames.get(packageNum); if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM, 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(permissionName, packageName, false, Process.SYSTEM_UID, userId, permissionCallback); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); } } } } } } } } private void addAllPermissions(PackageParser.Package pkg, boolean chatty) { final int N = pkg.permissions.size(); for (int i=0; i<N; i++) { Loading Loading @@ -1968,6 +2045,15 @@ public class PermissionManagerService { return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId); } @Override public void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage, oldPackage, allPackageNames, permissionCallback); } @Override public void addAllPermissions(Package pkg, boolean chatty) { PermissionManagerService.this.addAllPermissions(pkg, chatty); } Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +30 −6 Original line number Diff line number Diff line Loading @@ -202,6 +202,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; Loading Loading @@ -8696,7 +8697,7 @@ public class PackageManagerService extends IPackageManager.Stub } } // we're updating the disabled package, so, scan it as the package setting final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null, disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, null /* originalPkgSetting */, null, parseFlags, scanFlags, (pkg == mPlatformPackage), user); Loading Loading @@ -9874,6 +9875,8 @@ public class PackageManagerService extends IPackageManager.Stub private static class ScanRequest { /** The parsed package */ @NonNull public final PackageParser.Package pkg; /** The package this package replaces */ @Nullable public final PackageParser.Package oldPkg; /** Shared user settings, if the package has a shared user */ @Nullable public final SharedUserSetting sharedUserSetting; /** Loading @@ -9899,6 +9902,7 @@ public class PackageManagerService extends IPackageManager.Stub public ScanRequest( @NonNull PackageParser.Package pkg, @Nullable SharedUserSetting sharedUserSetting, @Nullable PackageParser.Package oldPkg, @Nullable PackageSetting pkgSetting, @Nullable PackageSetting disabledPkgSetting, @Nullable PackageSetting originalPkgSetting, Loading @@ -9908,6 +9912,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean isPlatformPackage, @Nullable UserHandle user) { this.pkg = pkg; this.oldPkg = oldPkg; this.pkgSetting = pkgSetting; this.sharedUserSetting = sharedUserSetting; this.oldPkgSetting = pkgSetting == null ? null : new PackageSetting(pkgSetting); Loading Loading @@ -10037,8 +10042,9 @@ public class PackageManagerService extends IPackageManager.Stub boolean scanSucceeded = false; try { final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, (pkg == mPlatformPackage), user); final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime); if (result.success) { Loading Loading @@ -10068,6 +10074,7 @@ public class PackageManagerService extends IPackageManager.Stub private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; final PackageParser.Package oldPkg = request.oldPkg; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final PackageSetting oldPkgSetting = request.oldPkgSetting; Loading Loading @@ -10237,7 +10244,7 @@ public class PackageManagerService extends IPackageManager.Stub } else { final int userId = user == null ? 0 : user.getIdentifier(); // Modify state for the given package setting commitPackageSettings(pkg, pkgSetting, user, scanFlags, commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags, (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); if (pkgSetting.getInstantApp(userId)) { mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); Loading Loading @@ -11163,8 +11170,9 @@ public class PackageManagerService extends IPackageManager.Stub * Adds a scanned package to the system. When this method is finished, the package will * be available for query, resolution, etc... */ private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { private void commitPackageSettings(PackageParser.Package pkg, @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { final String pkgName = pkg.packageName; if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { Loading Loading @@ -11504,6 +11512,22 @@ public class PackageManagerService extends IPackageManager.Stub } } } if (oldPkg != null) { // We need to call revokeRuntimePermissionsIfGroupChanged async as permission // revoke callbacks 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(() -> mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames, mPermissionCallback)); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.pm.PackageParser.Permission; import com.android.server.pm.SharedUserSetting; import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; Loading Loading @@ -90,6 +91,22 @@ public abstract class PermissionManagerInternal { public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated, @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback); /** * 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 packages * @param permissionCallback Callback for permission changed */ public abstract void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback); /** * Add all permissions in the given package. * <p> Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +86 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.os.storage.StorageManagerInternal; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -391,6 +392,82 @@ public class PermissionManagerService { return protectionLevel; } /** * 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 * @param permissionCallback Callback for permission changed */ private void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { 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.getProtection(); 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 int[] userIds = mUserManagerInt.getUserIds(); final int numUserIds = userIds.length; for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { final int userId = userIds[userIdNum]; final int numPackages = allPackageNames.size(); for (int packageNum = 0; packageNum < numPackages; packageNum++) { final String packageName = allPackageNames.get(packageNum); if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM, 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(permissionName, packageName, false, Process.SYSTEM_UID, userId, permissionCallback); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); } } } } } } } } private void addAllPermissions(PackageParser.Package pkg, boolean chatty) { final int N = pkg.permissions.size(); for (int i=0; i<N; i++) { Loading Loading @@ -1968,6 +2045,15 @@ public class PermissionManagerService { return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId); } @Override public void revokeRuntimePermissionsIfGroupChanged( @NonNull PackageParser.Package newPackage, @NonNull PackageParser.Package oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage, oldPackage, allPackageNames, permissionCallback); } @Override public void addAllPermissions(Package pkg, boolean chatty) { PermissionManagerService.this.addAllPermissions(pkg, chatty); } Loading