Merge "Don't drop restricted permissions on upgrade"

This commit is contained in:
Svetoslav Ganov
2019-07-29 16:11:11 +00:00
committed by Android (Google) Code Review
6 changed files with 135 additions and 38 deletions

View File

@@ -313,6 +313,8 @@ import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.permission.PermissionsState;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -20273,6 +20275,16 @@ public class PackageManagerService extends IPackageManager.Stub
// try optimizing this.
synchronized (mLock) {
mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);
final PermissionPolicyInternal permissionPolicyInternal =
LocalServices.getService(PermissionPolicyInternal.class);
permissionPolicyInternal.setOnInitializedCallback(userId -> {
// The SDK updated case is already handled when we run during the ctor.
synchronized (mPackages) {
mPermissionManager.updateAllPermissions(
StorageManager.UUID_PRIVATE_INTERNAL, false);
}
});
}
// Watch for external volumes that come and go over time

View File

@@ -1170,6 +1170,11 @@ public final class DefaultPermissionGrantPolicy {
final int flags = mContext.getPackageManager().getPermissionFlags(
permission, pkg.packageName, user);
// If we are trying to grant as system fixed and already system fixed
// then the system can change the system fixed grant state.
final boolean changingGrantForSystemFixed = systemFixed
&& (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0;
// Certain flags imply that the permission's current state by the system or
// device/profile owner or the user. In these cases we do not want to clobber the
// current state.
@@ -1177,7 +1182,8 @@ public final class DefaultPermissionGrantPolicy {
// Unless the caller wants to override user choices. The override is
// to make sure we can grant the needed permission to the default
// sms and phone apps after the user chooses this in the UI.
if (!isFixedOrUserSet(flags) || ignoreSystemPackage) {
if (!isFixedOrUserSet(flags) || ignoreSystemPackage
|| changingGrantForSystemFixed) {
// Never clobber policy fixed permissions.
// We must allow the grant of a system-fixed permission because
// system-fixed is sticky, but the permission itself may be revoked.
@@ -1196,6 +1202,14 @@ public final class DefaultPermissionGrantPolicy {
PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
}
// If the system tries to change a system fixed permission from one fixed
// state to another we need to drop the fixed flag to allow the grant.
if (changingGrantForSystemFixed) {
mContext.getPackageManager().updatePermissionFlags(permission,
pkg.packageName, flags,
flags & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, user);
}
if (pm.checkPermission(permission, pkg.packageName)
!= PackageManager.PERMISSION_GRANTED) {
mContext.getPackageManager()

View File

@@ -125,6 +125,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal.Default
import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState.PermissionState;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.SoftRestrictedPermissionPolicy;
import libcore.util.EmptyArray;
@@ -227,6 +228,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@GuardedBy("mLock")
private boolean mSystemReady;
@GuardedBy("mLock")
private PermissionPolicyInternal mPermissionPolicyInternal;
/**
* For each foreground/background permission the mapping:
* Background permission -> foreground permissions
@@ -2443,6 +2447,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean softRestricted = bp.isSoftRestricted();
for (int userId : currentUserIds) {
// If permission policy is not ready we don't deal with restricted
// permissions as the policy may whitelist some permissions. Once
// the policy is initialized we would re-evaluate permissions.
final boolean permissionPolicyInitialized =
mPermissionPolicyInternal != null
&& mPermissionPolicyInternal.isInitialized(userId);
PermissionState permState = origPermissions
.getRuntimePermissionState(perm, userId);
int flags = permState != null ? permState.getFlags() : 0;
@@ -2457,7 +2468,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (appSupportsRuntimePermissions) {
// If hard restricted we don't allow holding it
if (hardRestricted) {
if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
if (permState != null && permState.isGranted()
&& permissionsState.revokeRuntimePermission(
@@ -2470,7 +2481,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
// If soft restricted we allow holding in a restricted form
} else if (softRestricted) {
} else if (permissionPolicyInitialized && softRestricted) {
// Regardless if granted set the restriction flag as it
// may affect app treatment based on this permission.
if (!restrictionExempt && !restrictionApplied) {
@@ -2489,7 +2500,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
wasChanged = true;
// Hard restricted permissions cannot be held.
} else if (!hardRestricted || restrictionExempt) {
} else if (!permissionPolicyInitialized
|| (!hardRestricted || restrictionExempt)) {
if (permState != null && permState.isGranted()) {
if (permissionsState.grantRuntimePermission(bp, userId)
== PERMISSION_OPERATION_FAILURE) {
@@ -2518,33 +2530,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If legacy app always grant the permission but if restricted
// and not exempt take a note a restriction should be applied.
if ((hardRestricted || softRestricted)
&& !restrictionExempt && !restrictionApplied) {
if (permissionPolicyInitialized
&& (hardRestricted || softRestricted)
&& !restrictionExempt && !restrictionApplied) {
flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
wasChanged = true;
}
}
// If unrestricted or restriction exempt, don't apply restriction.
if (!(hardRestricted || softRestricted) || restrictionExempt) {
if (restrictionApplied) {
flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
// Dropping restriction on a legacy app requires a review.
if (!appSupportsRuntimePermissions) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
if (permissionPolicyInitialized) {
if (!(hardRestricted || softRestricted) || restrictionExempt) {
if (restrictionApplied) {
flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
// Dropping restriction on a legacy app implies a review
if (!appSupportsRuntimePermissions) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
}
wasChanged = true;
}
wasChanged = true;
}
}
if (hardRestricted && !restrictionExempt
&& (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
// Applying a hard restriction implies revoking it. This might
// lead to a system-fixed, revoked permission.
flags &= ~FLAG_PERMISSION_SYSTEM_FIXED;
wasChanged = true;
}
if (wasChanged) {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
@@ -2579,6 +2586,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean softRestricted = bp.isSoftRestricted();
for (int userId : currentUserIds) {
// If permission policy is not ready we don't deal with restricted
// permissions as the policy may whitelist some permissions. Once
// the policy is initialized we would re-evaluate permissions.
final boolean permissionPolicyInitialized =
mPermissionPolicyInternal != null
&& mPermissionPolicyInternal.isInitialized(userId);
boolean wasChanged = false;
boolean restrictionExempt =
@@ -2589,7 +2603,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (appSupportsRuntimePermissions) {
// If hard restricted we don't allow holding it
if (hardRestricted) {
if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
if (permState != null && permState.isGranted()
&& permissionsState.revokeRuntimePermission(
@@ -2602,7 +2616,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
// If soft restricted we allow holding in a restricted form
} else if (softRestricted) {
} else if (permissionPolicyInitialized && softRestricted) {
// Regardless if granted set the restriction flag as it
// may affect app treatment based on this permission.
if (!restrictionExempt && !restrictionApplied) {
@@ -2621,7 +2635,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
wasChanged = true;
// Hard restricted permissions cannot be held.
} else if (!hardRestricted || restrictionExempt) {
} else if (!permissionPolicyInitialized ||
(!hardRestricted || restrictionExempt)) {
if (permissionsState.grantRuntimePermission(bp, userId) !=
PERMISSION_OPERATION_FAILURE) {
wasChanged = true;
@@ -2637,22 +2652,25 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If legacy app always grant the permission but if restricted
// and not exempt take a note a restriction should be applied.
if ((hardRestricted || softRestricted)
&& !restrictionExempt && !restrictionApplied) {
if (permissionPolicyInitialized
&& (hardRestricted || softRestricted)
&& !restrictionExempt && !restrictionApplied) {
flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
wasChanged = true;
}
}
// If unrestricted or restriction exempt, don't apply restriction.
if (!(hardRestricted || softRestricted) || restrictionExempt) {
if (restrictionApplied) {
flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
// Dropping restriction on a legacy app requires a review.
if (!appSupportsRuntimePermissions) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
if (permissionPolicyInitialized) {
if (!(hardRestricted || softRestricted) || restrictionExempt) {
if (restrictionApplied) {
flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
// Dropping restriction on a legacy app implies a review
if (!appSupportsRuntimePermissions) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
}
wasChanged = true;
}
wasChanged = true;
}
}
@@ -3959,6 +3977,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
for (int userId : UserManagerService.getInstance().getUserIds()) {

View File

@@ -18,6 +18,7 @@ package com.android.server.policy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Intent;
/**
@@ -25,6 +26,19 @@ import android.content.Intent;
*/
public abstract class PermissionPolicyInternal {
/**
* Callback for initializing the permission policy service.
*/
public interface OnInitializedCallback {
/**
* Called when initialized for the given user.
*
* @param userId The initialized user.
*/
void onInitialized(@UserIdInt int userId);
}
/**
* Check whether an activity should be started.
*
@@ -36,4 +50,17 @@ public abstract class PermissionPolicyInternal {
*/
public abstract boolean checkStartActivity(@NonNull Intent intent, int callingUid,
@Nullable String callingPackage);
/**
* @return Whether the policy is initialized for a user.
*/
public abstract boolean isInitialized(@UserIdInt int userId);
/**
* Set a callback for users being initialized. If the user is already
* initialized the callback will not be invoked.
*
* @param callback The callback to register.
*/
public abstract void setOnInitializedCallback(@NonNull OnInitializedCallback callback);
}

View File

@@ -66,6 +66,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
@@ -86,6 +87,10 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock")
private final SparseBooleanArray mIsStarted = new SparseBooleanArray();
/** Callbacks for when a user is initialized */
@GuardedBy("mLock")
private OnInitializedCallback mOnInitializedCallback;
/**
* Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
* scheduled for a package/user.
@@ -240,12 +245,20 @@ public final class PermissionPolicyService extends SystemService {
grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);
final OnInitializedCallback callback;
synchronized (mLock) {
mIsStarted.put(userId, true);
callback = mOnInitializedCallback;
}
// Force synchronization as permissions might have changed
synchronizePermissionsAndAppOpsForUser(userId);
// Tell observers we are initialized for this user.
if (callback != null) {
callback.onInitialized(userId);
}
}
@Override
@@ -809,6 +822,18 @@ public final class PermissionPolicyService extends SystemService {
return true;
}
@Override
public boolean isInitialized(int userId) {
return isStarted(userId);
}
@Override
public void setOnInitializedCallback(@NonNull OnInitializedCallback callback) {
synchronized (mLock) {
mOnInitializedCallback = callback;
}
}
/**
* Check if the intent action is removed for the calling package (often based on target SDK
* version). If the action is removed, we'll silently cancel the activity launch.

View File

@@ -1980,6 +1980,11 @@ public final class SystemServer {
}
t.traceEnd();
// Permission policy service
t.traceBegin("StartPermissionPolicyService");
mSystemServiceManager.startService(PermissionPolicyService.class);
t.traceEnd();
t.traceBegin("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
t.traceEnd();
@@ -2014,11 +2019,6 @@ public final class SystemServer {
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
t.traceEnd();
// Permission policy service
t.traceBegin("StartPermissionPolicyService");
mSystemServiceManager.startService(PermissionPolicyService.class);
t.traceEnd();
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkStatsService networkStatsF = networkStats;