diff options
3 files changed, 155 insertions, 79 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 49386f9..62c2e8c 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4627,12 +4627,12 @@ public abstract class PackageManager { /** {@hide} */ public static String permissionFlagToString(int flag) { switch (flag) { - case FLAG_PERMISSION_GRANTED_BY_DEFAULT: return "FLAG_PERMISSION_GRANTED_BY_DEFAULT"; - case FLAG_PERMISSION_POLICY_FIXED: return "FLAG_PERMISSION_POLICY_FIXED"; - case FLAG_PERMISSION_SYSTEM_FIXED: return "FLAG_PERMISSION_SYSTEM_FIXED"; - case FLAG_PERMISSION_USER_SET: return "FLAG_PERMISSION_USER_SET"; - case FLAG_PERMISSION_REVOKE_ON_UPGRADE: return "FLAG_PERMISSION_REVOKE_ON_UPGRADE"; - case FLAG_PERMISSION_USER_FIXED: return "FLAG_PERMISSION_USER_FIXED"; + case FLAG_PERMISSION_GRANTED_BY_DEFAULT: return "GRANTED_BY_DEFAULT"; + case FLAG_PERMISSION_POLICY_FIXED: return "POLICY_FIXED"; + case FLAG_PERMISSION_SYSTEM_FIXED: return "SYSTEM_FIXED"; + case FLAG_PERMISSION_USER_SET: return "USER_SET"; + case FLAG_PERMISSION_REVOKE_ON_UPGRADE: return "REVOKE_ON_UPGRADE"; + case FLAG_PERMISSION_USER_FIXED: return "USER_FIXED"; default: return Integer.toString(flag); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 124214c..ed20345 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -25,6 +25,12 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; +import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; +import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import static android.content.pm.PackageManager.INSTALL_EXTERNAL; import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER; @@ -72,6 +78,9 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; +import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE; +import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS; +import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; import android.Manifest; import android.app.ActivityManager; @@ -12665,7 +12674,7 @@ public class PackageManagerService extends IPackageManager.Stub { KILL_APP_REASON_GIDS_CHANGED); } }); - break; + break; } } } @@ -12781,8 +12790,14 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); + + // Propagate the permissions state as we do want to drop on the floor + // runtime permissions. The update permissions method below will take + // care of removing obsolete permissions and grant install permissions. + ps.getPermissionsState().copyFrom(disabledPs.getPermissionsState()); updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); + if (applyUserRestrictions) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); @@ -12943,8 +12958,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (clearPackagePreferredActivitiesLPw(packageName, removeUser)) { scheduleWritePackageRestrictionsLocked(removeUser); } - revokeRuntimePermissionsAndClearAllFlagsLocked(ps.getPermissionsState(), - removeUser); + resetUserChangesToRuntimePermissionsAndFlagsLocked(ps, removeUser); } return true; } @@ -13105,8 +13119,7 @@ public class PackageManagerService extends IPackageManager.Stub { } PackageSetting ps = (PackageSetting) pkg.mExtras; - PermissionsState permissionsState = ps.getPermissionsState(); - revokeRuntimePermissionsAndClearUserSetFlagsLocked(permissionsState, userId); + resetUserChangesToRuntimePermissionsAndFlagsLocked(ps, userId); } // Always delete data directories for package, even if we found no other @@ -13137,66 +13150,118 @@ public class PackageManagerService extends IPackageManager.Stub { return true; } - /** - * Revokes granted runtime permissions and clears resettable flags - * which are flags that can be set by a user interaction. + * Reverts user permission state changes (permissions and flags). * - * @param permissionsState The permission state to reset. + * @param ps The package for which to reset. * @param userId The device user for which to do a reset. */ - private void revokeRuntimePermissionsAndClearUserSetFlagsLocked( - PermissionsState permissionsState, int userId) { - final int userSetFlags = PackageManager.FLAG_PERMISSION_USER_SET - | PackageManager.FLAG_PERMISSION_USER_FIXED - | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; + private void resetUserChangesToRuntimePermissionsAndFlagsLocked( + final PackageSetting ps, final int userId) { + if (ps.pkg == null) { + return; + } - revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, userSetFlags); - } + final int userSettableFlags = FLAG_PERMISSION_USER_SET + | FLAG_PERMISSION_USER_FIXED + | FLAG_PERMISSION_REVOKE_ON_UPGRADE; - /** - * Revokes granted runtime permissions and clears all flags. - * - * @param permissionsState The permission state to reset. - * @param userId The device user for which to do a reset. - */ - private void revokeRuntimePermissionsAndClearAllFlagsLocked( - PermissionsState permissionsState, int userId) { - revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, - PackageManager.MASK_PERMISSION_FLAGS); - } + final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED + | FLAG_PERMISSION_POLICY_FIXED; - /** - * Revokes granted runtime permissions and clears certain flags. - * - * @param permissionsState The permission state to reset. - * @param userId The device user for which to do a reset. - * @param flags The flags that is going to be reset. - */ - private void revokeRuntimePermissionsAndClearFlagsLocked( - PermissionsState permissionsState, final int userId, int flags) { - boolean needsWrite = false; + boolean writeInstallPermissions = false; + boolean writeRuntimePermissions = false; - for (PermissionState state : permissionsState.getRuntimePermissionStates(userId)) { - BasePermission bp = mSettings.mPermissions.get(state.getName()); - if (bp != null) { - permissionsState.revokeRuntimePermission(bp, userId); - permissionsState.updatePermissionFlags(bp, userId, flags, 0); - needsWrite = true; + final int permissionCount = ps.pkg.requestedPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + String permission = ps.pkg.requestedPermissions.get(i); + + BasePermission bp = mSettings.mPermissions.get(permission); + if (bp == null) { + continue; } - } - // Ensure default permissions are never cleared. - mHandler.post(new Runnable() { - @Override - public void run() { - mDefaultPermissionPolicy.grantDefaultPermissions(userId); + // If shared user we just reset the state to which only this app contributed. + if (ps.sharedUser != null) { + boolean used = false; + final int packageCount = ps.sharedUser.packages.size(); + for (int j = 0; j < packageCount; j++) { + PackageSetting pkg = ps.sharedUser.packages.valueAt(j); + if (pkg.pkg != null && !pkg.pkg.packageName.equals(ps.pkg.packageName) + && pkg.pkg.requestedPermissions.contains(permission)) { + used = true; + break; + } + } + if (used) { + continue; + } } - }); - if (needsWrite) { + PermissionsState permissionsState = ps.getPermissionsState(); + + final int oldFlags = permissionsState.getPermissionFlags(bp.name, userId); + + // Always clear the user settable flags. + final boolean hasInstallState = permissionsState.getInstallPermissionState( + bp.name) != null; + if (permissionsState.updatePermissionFlags(bp, userId, userSettableFlags, 0)) { + if (hasInstallState) { + writeInstallPermissions = true; + } else { + writeRuntimePermissions = true; + } + } + + // Below is only runtime permission handling. + if (!bp.isRuntime()) { + continue; + } + + // Never clobber system or policy. + if ((oldFlags & policyOrSystemFlags) != 0) { + continue; + } + + // If this permission was granted by default, make sure it is. + if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) { + if (permissionsState.grantRuntimePermission(bp, userId) + != PERMISSION_OPERATION_FAILURE) { + writeRuntimePermissions = true; + } + } else { + // Otherwise, reset the permission. + final int revokeResult = permissionsState.revokeRuntimePermission(bp, userId); + switch (revokeResult) { + case PERMISSION_OPERATION_SUCCESS: { + writeRuntimePermissions = true; + } break; + + case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: { + writeRuntimePermissions = true; + // If gids changed for this user, kill all affected packages. + mHandler.post(new Runnable() { + @Override + public void run() { + // This has to happen with no lock held. + killSettingPackagesForUser(ps, userId, + KILL_APP_REASON_GIDS_CHANGED); + } + }); + } break; + } + } + } + + // Synchronously write as we are taking permissions away. + if (writeRuntimePermissions) { mSettings.writeRuntimePermissionsForUserLPr(userId, true); } + + // Synchronously write as we are taking permissions away. + if (writeInstallPermissions) { + mSettings.writeLPr(); + } } /** diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 4e85e39..bdcd714 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -824,14 +824,8 @@ final class Settings { continue; } - // If no user has the permission, nothing to remove. - if (!sus.getPermissionsState().hasPermission(bp.name, userId)) { - continue; - } - - boolean used = false; - // Check if another package in the shared user needs the permission. + boolean used = false; for (PackageSetting pkg : sus.packages) { if (pkg.pkg != null && !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) @@ -840,26 +834,43 @@ final class Settings { break; } } + if (used) { + continue; + } - if (!used) { - PermissionsState permissionsState = sus.getPermissionsState(); - - // Try to revoke as an install permission which is for all users. - // The package is gone - no need to keep flags for applying policy. - permissionsState.updatePermissionFlags(bp, userId, - PackageManager.MASK_PERMISSION_FLAGS, 0); + PermissionsState permissionsState = sus.getPermissionsState(); + PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.packageName); - if (permissionsState.revokeInstallPermission(bp) == - PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { - return UserHandle.USER_ALL; + // If the package is shadowing is a disabled system package, + // do not drop permissions that the shadowed package requests. + if (disabledPs != null) { + boolean reqByDisabledSysPkg = false; + for (String permission : disabledPs.pkg.requestedPermissions) { + if (permission.equals(eachPerm)) { + reqByDisabledSysPkg = true; + break; + } } - - // Try to revoke as an install permission which is per user. - if (permissionsState.revokeRuntimePermission(bp, userId) == - PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { - return userId; + if (reqByDisabledSysPkg) { + continue; } } + + // Try to revoke as an install permission which is for all users. + // The package is gone - no need to keep flags for applying policy. + permissionsState.updatePermissionFlags(bp, userId, + PackageManager.MASK_PERMISSION_FLAGS, 0); + + if (permissionsState.revokeInstallPermission(bp) == + PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { + return UserHandle.USER_ALL; + } + + // Try to revoke as an install permission which is per user. + if (permissionsState.revokeRuntimePermission(bp, userId) == + PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { + return userId; + } } return UserHandle.USER_NULL; |