summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2015-07-07 18:18:15 -0700
committerSvet Ganov <svetoslavganov@google.com>2015-07-08 16:52:42 -0700
commit4a5f4a2bc7a379a5b4174f78fefeefe745e6cd37 (patch)
tree177a7e7a9b43499fe5f6bb78eb9da729aaee4459
parent3aa1b1e5ec3a4e2074ea054b931cd68df45b43cf (diff)
downloadframeworks_base-4a5f4a2bc7a379a5b4174f78fefeefe745e6cd37.zip
frameworks_base-4a5f4a2bc7a379a5b4174f78fefeefe745e6cd37.tar.gz
frameworks_base-4a5f4a2bc7a379a5b4174f78fefeefe745e6cd37.tar.bz2
Fix reset permissions on clear data and package uninstall.
If the user clears data for an app we reset the permission but only the changes made by the user. We do not modify syste or policy flags and also ensure the permission that were granted by default are granted after the data wipe. This is the same as starting with a clean slate. If the package whose data is cleared is a part of a shared user we resent to initial state only the permissions that the cleared package contributed. Hence, if another package also declared the permission as used we do not clear the permission state as it is still in use. When a package is deleted for a user but still present for another user we reset its permissions to their inital state follwoing above described strategy. Lastly when a preinstalled package wtih an upgrade is diabled (triggers upgrade uninstall) and this package is a part of a shared user, we do not drop permission state (grants and flags) for permissions used by the shadowed system package. This ensures that we do not drop runtime permission state (such state is default grants and user changes).i bug:22248525 Change-Id: I3a3007476d2cb9f4ff824e1e137a6e1a4d04408b
-rw-r--r--core/java/android/content/pm/PackageManager.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java167
-rw-r--r--services/core/java/com/android/server/pm/Settings.java55
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;