am 353835e1: am c88dec32: am 6638c182: Merge "Fix reset permissions on clear data and package uninstall." into mnc-dev

* commit '353835e12d1419a08bd1030db29fe4740cf09598':
  Fix reset permissions on clear data and package uninstall.
This commit is contained in:
Svetoslav
2015-07-09 01:04:00 +00:00
committed by Android Git Automerger
3 changed files with 156 additions and 80 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
// 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;
}
}
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;
}
}
}
// Ensure default permissions are never cleared.
mHandler.post(new Runnable() {
@Override
public void run() {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
}
});
if (needsWrite) {
// 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();
}
}
/**

View File

@@ -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();
PermissionsState permissionsState = sus.getPermissionsState();
PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.packageName);
// 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;
// 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;