Loading services/core/java/com/android/server/pm/PackageManagerService.java +20 −4 Original line number Diff line number Diff line Loading @@ -336,6 +336,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.os.Zygote; import com.android.internal.telephony.CarrierAppUtils; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; Loading Loading @@ -12687,11 +12688,16 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.addAllPermissionGroups(pkg, chatty); } // If a permission has had its defining app changed, or it has had its protection // upgraded, we need to revoke apps that hold it final List<String> permissionsWithChangedDefinition; // Don't allow ephemeral applications to define new permissions. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { permissionsWithChangedDefinition = null; Slog.w(TAG, "Permissions from package " + pkg.getPackageName() + " ignored: instant apps cannot define new permissions."); } else { permissionsWithChangedDefinition = mPermissionManager.addAllPermissions(pkg, chatty); } Loading Loading @@ -12721,7 +12727,10 @@ public class PackageManagerService extends IPackageManager.Stub } } if (oldPkg != null) { boolean hasOldPkg = oldPkg != null; boolean hasPermissionDefinitionChanges = !CollectionUtils.isEmpty(permissionsWithChangedDefinition); if (hasOldPkg || hasPermissionDefinitionChanges) { // 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. Loading @@ -12732,9 +12741,16 @@ public class PackageManagerService extends IPackageManager.Stub // won't be granted yet, hence new packages are no problem. final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet()); AsyncTask.execute(() -> AsyncTask.execute(() -> { if (hasOldPkg) { mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames)); allPackageNames); } if (hasPermissionDefinitionChanges) { mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged( permissionsWithChangedDefinition, allPackageNames); } }); } } services/core/java/com/android/server/pm/permission/BasePermission.java +18 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ public final class BasePermission { private static final String ATTR_PACKAGE = "package"; private static final String TAG_ITEM = "item"; private boolean mPermissionDefinitionChanged; @NonNull private PermissionInfo mPermissionInfo; Loading Loading @@ -122,6 +124,10 @@ public final class BasePermission { return mPermissionInfo.packageName; } public boolean isPermissionDefinitionChanged() { return mPermissionDefinitionChanged; } public int getType() { return mType; } Loading @@ -148,6 +154,10 @@ public final class BasePermission { mReconciled = permissionInfo != null; } public void setPermissionDefinitionChanged(boolean shouldOverride) { mPermissionDefinitionChanged = shouldOverride; } public boolean hasGids() { return mGids.length != 0; } Loading Loading @@ -364,6 +374,7 @@ public final class BasePermission { @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees, boolean chatty) { // Allow system apps to redefine non-system permissions boolean ownerChanged = false; if (bp != null && !Objects.equals(bp.mPermissionInfo.packageName, p.packageName)) { final boolean currentOwnerIsSystem; if (!bp.mReconciled) { Loading @@ -389,6 +400,7 @@ public final class BasePermission { String msg = "New decl " + pkg + " of permission " + p.name + " is system; overriding " + bp.mPermissionInfo.packageName; PackageManagerService.reportSettingsProblem(Log.WARN, msg); ownerChanged = true; bp = null; } } Loading @@ -396,6 +408,7 @@ public final class BasePermission { if (bp == null) { bp = new BasePermission(p.name, p.packageName, TYPE_MANIFEST); } boolean wasNormal = bp.isNormal(); StringBuilder r = null; if (!bp.mReconciled) { if (bp.mPermissionInfo.packageName == null Loading Loading @@ -435,6 +448,11 @@ public final class BasePermission { r.append("DUP:"); r.append(p.name); } if (bp.isRuntime() && (ownerChanged || wasNormal)) { // If this is a runtime permission and the owner has changed, or this was a normal // permission, then permission state should be cleaned up bp.mPermissionDefinitionChanged = true; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); } Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +82 −3 Original line number Diff line number Diff line Loading @@ -2327,8 +2327,74 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } private void addAllPermissions(AndroidPackage pkg, boolean chatty) { /** * If permissions are upgraded to runtime, or their owner changes to the system, then any * granted permissions must be revoked. * * @param permissionsToRevoke A list of permission names to revoke * @param allPackageNames All package names * @param permissionCallback Callback for permission changed */ private void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { final int[] userIds = mUserManagerInt.getUserIds(); final int numPermissions = permissionsToRevoke.size(); final int numUserIds = userIds.length; final int numPackages = allPackageNames.size(); final int callingUid = Binder.getCallingUid(); for (int permNum = 0; permNum < numPermissions; permNum++) { String permName = permissionsToRevoke.get(permNum); BasePermission bp = mSettings.getPermission(permName); if (bp == null || !bp.isRuntime()) { continue; } for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { final int userId = userIds[userIdNum]; for (int packageNum = 0; packageNum < numPackages; packageNum++) { final String packageName = allPackageNames.get(packageNum); final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId); if (uid < Process.FIRST_APPLICATION_UID) { // do not revoke from system apps continue; } final int permissionState = checkPermissionImpl(permName, packageName, userId); final int flags = getPermissionFlags(permName, packageName, userId); final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT | FLAG_PERMISSION_GRANTED_BY_ROLE; if (permissionState == PackageManager.PERMISSION_GRANTED && (flags & flagMask) == 0) { EventLog.writeEvent(0x534e4554, "154505240", uid, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); EventLog.writeEvent(0x534e4554, "168319670", uid, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); Slog.e(TAG, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); try { revokeRuntimePermissionInternal(permName, packageName, false, callingUid, userId, null, permissionCallback); } catch (Exception e) { Slog.e(TAG, "Could not revoke " + permName + " from " + packageName, e); } } } } bp.setPermissionDefinitionChanged(false); } } private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) { final int N = ArrayUtils.size(pkg.getPermissions()); ArrayList<String> definitionChangedPermissions = new ArrayList<>(); for (int i=0; i<N; i++) { ParsedPermission p = pkg.getPermissions().get(i); Loading Loading @@ -2369,8 +2435,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (bp.isInstalled()) { p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED); } if (bp.isPermissionDefinitionChanged()) { definitionChangedPermissions.add(p.getName()); } } } return definitionChangedPermissions; } private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { Loading Loading @@ -4750,9 +4820,18 @@ public class PermissionManagerService extends IPermissionManager.Stub { PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage, oldPackage, allPackageNames, mDefaultPermissionCallback); } @Override public void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames) { PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged( permissionsToRevoke, allPackageNames, mDefaultPermissionCallback); } @Override public void addAllPermissions(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.addAllPermissions(pkg, chatty); public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) { return PermissionManagerService.this.addAllPermissions(pkg, chatty); } @Override public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { Loading services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +15 −1 Original line number Diff line number Diff line Loading @@ -255,13 +255,27 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager @NonNull AndroidPackage oldPackage, @NonNull ArrayList<String> allPackageNames); /** * Some permissions might have been owned by a non-system package, and the system then defined * said permission. Some other permissions may one have been install permissions, but are now * runtime or higher. These permissions should be revoked. * * @param permissionsToRevoke A list of permission names to revoke * @param allPackageNames All packages */ public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames); /** * Add all permissions in the given package. * <p> * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to * the permission settings. * * @return A list of BasePermissions that were updated, and need to be revoked from packages */ public abstract void addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty); public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +20 −4 Original line number Diff line number Diff line Loading @@ -336,6 +336,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.os.Zygote; import com.android.internal.telephony.CarrierAppUtils; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; Loading Loading @@ -12687,11 +12688,16 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.addAllPermissionGroups(pkg, chatty); } // If a permission has had its defining app changed, or it has had its protection // upgraded, we need to revoke apps that hold it final List<String> permissionsWithChangedDefinition; // Don't allow ephemeral applications to define new permissions. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { permissionsWithChangedDefinition = null; Slog.w(TAG, "Permissions from package " + pkg.getPackageName() + " ignored: instant apps cannot define new permissions."); } else { permissionsWithChangedDefinition = mPermissionManager.addAllPermissions(pkg, chatty); } Loading Loading @@ -12721,7 +12727,10 @@ public class PackageManagerService extends IPackageManager.Stub } } if (oldPkg != null) { boolean hasOldPkg = oldPkg != null; boolean hasPermissionDefinitionChanges = !CollectionUtils.isEmpty(permissionsWithChangedDefinition); if (hasOldPkg || hasPermissionDefinitionChanges) { // 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. Loading @@ -12732,9 +12741,16 @@ public class PackageManagerService extends IPackageManager.Stub // won't be granted yet, hence new packages are no problem. final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet()); AsyncTask.execute(() -> AsyncTask.execute(() -> { if (hasOldPkg) { mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames)); allPackageNames); } if (hasPermissionDefinitionChanges) { mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged( permissionsWithChangedDefinition, allPackageNames); } }); } }
services/core/java/com/android/server/pm/permission/BasePermission.java +18 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ public final class BasePermission { private static final String ATTR_PACKAGE = "package"; private static final String TAG_ITEM = "item"; private boolean mPermissionDefinitionChanged; @NonNull private PermissionInfo mPermissionInfo; Loading Loading @@ -122,6 +124,10 @@ public final class BasePermission { return mPermissionInfo.packageName; } public boolean isPermissionDefinitionChanged() { return mPermissionDefinitionChanged; } public int getType() { return mType; } Loading @@ -148,6 +154,10 @@ public final class BasePermission { mReconciled = permissionInfo != null; } public void setPermissionDefinitionChanged(boolean shouldOverride) { mPermissionDefinitionChanged = shouldOverride; } public boolean hasGids() { return mGids.length != 0; } Loading Loading @@ -364,6 +374,7 @@ public final class BasePermission { @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees, boolean chatty) { // Allow system apps to redefine non-system permissions boolean ownerChanged = false; if (bp != null && !Objects.equals(bp.mPermissionInfo.packageName, p.packageName)) { final boolean currentOwnerIsSystem; if (!bp.mReconciled) { Loading @@ -389,6 +400,7 @@ public final class BasePermission { String msg = "New decl " + pkg + " of permission " + p.name + " is system; overriding " + bp.mPermissionInfo.packageName; PackageManagerService.reportSettingsProblem(Log.WARN, msg); ownerChanged = true; bp = null; } } Loading @@ -396,6 +408,7 @@ public final class BasePermission { if (bp == null) { bp = new BasePermission(p.name, p.packageName, TYPE_MANIFEST); } boolean wasNormal = bp.isNormal(); StringBuilder r = null; if (!bp.mReconciled) { if (bp.mPermissionInfo.packageName == null Loading Loading @@ -435,6 +448,11 @@ public final class BasePermission { r.append("DUP:"); r.append(p.name); } if (bp.isRuntime() && (ownerChanged || wasNormal)) { // If this is a runtime permission and the owner has changed, or this was a normal // permission, then permission state should be cleaned up bp.mPermissionDefinitionChanged = true; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); } Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +82 −3 Original line number Diff line number Diff line Loading @@ -2327,8 +2327,74 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } private void addAllPermissions(AndroidPackage pkg, boolean chatty) { /** * If permissions are upgraded to runtime, or their owner changes to the system, then any * granted permissions must be revoked. * * @param permissionsToRevoke A list of permission names to revoke * @param allPackageNames All package names * @param permissionCallback Callback for permission changed */ private void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { final int[] userIds = mUserManagerInt.getUserIds(); final int numPermissions = permissionsToRevoke.size(); final int numUserIds = userIds.length; final int numPackages = allPackageNames.size(); final int callingUid = Binder.getCallingUid(); for (int permNum = 0; permNum < numPermissions; permNum++) { String permName = permissionsToRevoke.get(permNum); BasePermission bp = mSettings.getPermission(permName); if (bp == null || !bp.isRuntime()) { continue; } for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { final int userId = userIds[userIdNum]; for (int packageNum = 0; packageNum < numPackages; packageNum++) { final String packageName = allPackageNames.get(packageNum); final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId); if (uid < Process.FIRST_APPLICATION_UID) { // do not revoke from system apps continue; } final int permissionState = checkPermissionImpl(permName, packageName, userId); final int flags = getPermissionFlags(permName, packageName, userId); final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT | FLAG_PERMISSION_GRANTED_BY_ROLE; if (permissionState == PackageManager.PERMISSION_GRANTED && (flags & flagMask) == 0) { EventLog.writeEvent(0x534e4554, "154505240", uid, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); EventLog.writeEvent(0x534e4554, "168319670", uid, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); Slog.e(TAG, "Revoking permission " + permName + " from package " + packageName + " due to definition change"); try { revokeRuntimePermissionInternal(permName, packageName, false, callingUid, userId, null, permissionCallback); } catch (Exception e) { Slog.e(TAG, "Could not revoke " + permName + " from " + packageName, e); } } } } bp.setPermissionDefinitionChanged(false); } } private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) { final int N = ArrayUtils.size(pkg.getPermissions()); ArrayList<String> definitionChangedPermissions = new ArrayList<>(); for (int i=0; i<N; i++) { ParsedPermission p = pkg.getPermissions().get(i); Loading Loading @@ -2369,8 +2435,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (bp.isInstalled()) { p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED); } if (bp.isPermissionDefinitionChanged()) { definitionChangedPermissions.add(p.getName()); } } } return definitionChangedPermissions; } private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { Loading Loading @@ -4750,9 +4820,18 @@ public class PermissionManagerService extends IPermissionManager.Stub { PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage, oldPackage, allPackageNames, mDefaultPermissionCallback); } @Override public void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames) { PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged( permissionsToRevoke, allPackageNames, mDefaultPermissionCallback); } @Override public void addAllPermissions(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.addAllPermissions(pkg, chatty); public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) { return PermissionManagerService.this.addAllPermissions(pkg, chatty); } @Override public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { Loading
services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +15 −1 Original line number Diff line number Diff line Loading @@ -255,13 +255,27 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager @NonNull AndroidPackage oldPackage, @NonNull ArrayList<String> allPackageNames); /** * Some permissions might have been owned by a non-system package, and the system then defined * said permission. Some other permissions may one have been install permissions, but are now * runtime or higher. These permissions should be revoked. * * @param permissionsToRevoke A list of permission names to revoke * @param allPackageNames All packages */ public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged( @NonNull List<String> permissionsToRevoke, @NonNull ArrayList<String> allPackageNames); /** * Add all permissions in the given package. * <p> * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to * the permission settings. * * @return A list of BasePermissions that were updated, and need to be revoked from packages */ public abstract void addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty); public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); Loading