Merge "Set app-op for restricted pre-22 apps" into qt-dev

am: 26a896ecc8

Change-Id: I4d6c596e255ca418abac2092b27eb6d57a4e9781
This commit is contained in:
Philip P. Moltmann
2019-06-12 13:31:59 -07:00
committed by android-build-merger
3 changed files with 143 additions and 102 deletions

View File

@@ -19,6 +19,7 @@ package com.android.server.policy;
import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
@@ -290,7 +291,7 @@ public final class PermissionPolicyService extends SystemService {
* *
* Currently, only used by the restricted permissions logic. * Currently, only used by the restricted permissions logic.
* *
* @see #syncRestrictedOps * @see #syncPackages
*/ */
private final @NonNull ArrayList<OpToRestrict> mOpsToDefault = new ArrayList<>(); private final @NonNull ArrayList<OpToRestrict> mOpsToDefault = new ArrayList<>();
@@ -299,16 +300,14 @@ public final class PermissionPolicyService extends SystemService {
* *
* Currently, only used by the restricted permissions logic. * Currently, only used by the restricted permissions logic.
* *
* @see #syncRestrictedOps * @see #syncPackages
*/ */
private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>(); private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>();
/** /**
* All ops that need to be flipped to allow. * All ops that need to be flipped to allow.
* *
* Currently, only used by the restricted permissions logic. * @see #syncPackages
*
* @see #syncRestrictedOps
*/ */
private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>(); private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
@@ -317,16 +316,25 @@ public final class PermissionPolicyService extends SystemService {
* *
* Currently, only used by the restricted permissions logic. * Currently, only used by the restricted permissions logic.
* *
* @see #syncRestrictedOps * @see #syncPackages
*/ */
private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>(); private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>();
/** /**
* All foreground permissions * All ops that need to be flipped to ignore.
* *
* @see #syncOpsOfFgPermissions() * @see #syncPackages
*/ */
private final @NonNull ArrayList<FgPermission> mFgPermOps = new ArrayList<>(); private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
/**
* All ops that need to be flipped to foreground.
*
* Currently, only used by the foreground/background permissions logic.
*
* @see #syncPackages
*/
private final @NonNull ArrayList<OpToUnrestrict> mOpsToForeground = new ArrayList<>();
PermissionToOpSynchroniser(@NonNull Context context) { PermissionToOpSynchroniser(@NonNull Context context) {
mContext = context; mContext = context;
@@ -335,11 +343,11 @@ public final class PermissionPolicyService extends SystemService {
} }
/** /**
* Set app ops that belong to restricted permissions. * Set app ops that were added in {@link #addPackage}.
* *
* <p>This processes ops previously added by {@link #addOpIfRestricted} * <p>This processes ops previously added by {@link #addOpIfRestricted}
*/ */
private void syncRestrictedOps() { private void syncPackages() {
final int allowCount = mOpsToAllow.size(); final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) { for (int i = 0; i < allowCount; i++) {
final OpToUnrestrict op = mOpsToAllow.get(i); final OpToUnrestrict op = mOpsToAllow.get(i);
@@ -350,6 +358,16 @@ public final class PermissionPolicyService extends SystemService {
final OpToUnrestrict op = mOpsToAllowIfDefault.get(i); final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
setUidModeAllowedIfDefault(op.code, op.uid, op.packageName); setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
} }
final int foregroundCount = mOpsToForeground.size();
for (int i = 0; i < foregroundCount; i++) {
final OpToUnrestrict op = mOpsToForeground.get(i);
setUidModeForeground(op.code, op.uid);
}
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
final OpToUnrestrict op = mOpsToIgnore.get(i);
setUidModeIgnored(op.code, op.uid);
}
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size(); final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
for (int i = 0; i < ignoreIfDefaultCount; i++) { for (int i = 0; i < ignoreIfDefaultCount; i++) {
final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i); final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i);
@@ -362,47 +380,9 @@ public final class PermissionPolicyService extends SystemService {
} }
} }
/**
* Set app ops that belong to restricted permissions.
*
* <p>This processed ops previously added by {@link #addOpIfRestricted}
*/
private void syncOpsOfFgPermissions() {
int numFgPermOps = mFgPermOps.size();
for (int i = 0; i < numFgPermOps; i++) {
FgPermission perm = mFgPermOps.get(i);
if (mPackageManager.checkPermission(perm.fgPermissionName, perm.packageName)
== PackageManager.PERMISSION_GRANTED) {
if (mPackageManager.checkPermission(perm.bgPermissionName, perm.packageName)
== PackageManager.PERMISSION_GRANTED) {
mAppOpsManager.setUidMode(
AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid,
AppOpsManager.MODE_ALLOWED);
} else {
mAppOpsManager.setUidMode(
AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid,
AppOpsManager.MODE_FOREGROUND);
}
} else {
mAppOpsManager.setUidMode(
AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid,
AppOpsManager.MODE_IGNORED);
}
}
}
/**
* Synchronize all previously {@link #addPackage added} packages.
*/
void syncPackages() {
syncRestrictedOps();
syncOpsOfFgPermissions();
}
/** /**
* Add op that belong to a restricted permission for later processing in * Add op that belong to a restricted permission for later processing in
* {@link #syncRestrictedOps}. * {@link #syncPackages()}.
* *
* <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager. * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
* *
@@ -424,19 +404,29 @@ public final class PermissionPolicyService extends SystemService {
mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
if (permissionInfo.isHardRestricted()) { if (permissionInfo.isHardRestricted()) {
if (applyRestriction) { if (opCode != OP_NONE) {
mOpsToDefault.add(new OpToRestrict(uid, opCode)); if (applyRestriction) {
} else { mOpsToDefault.add(new OpToRestrict(uid, opCode));
mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode)); } else {
mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
}
} }
} else if (permissionInfo.isSoftRestricted()) { } else if (permissionInfo.isSoftRestricted()) {
final SoftRestrictedPermissionPolicy policy = final SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo, SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo,
permission); permission);
final int op = policy.getAppOp(); if (opCode != OP_NONE) {
if (policy.canBeGranted()) {
mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
} else {
mOpsToDefault.add(new OpToRestrict(uid, opCode));
}
}
final int op = policy.resolveAppOp();
if (op != OP_NONE) { if (op != OP_NONE) {
switch (policy.getAppOpMode()) { switch (policy.getDesiredOpMode()) {
case MODE_DEFAULT: case MODE_DEFAULT:
mOpsToDefault.add(new OpToRestrict(uid, op)); mOpsToDefault.add(new OpToRestrict(uid, op));
break; break;
@@ -444,16 +434,22 @@ public final class PermissionPolicyService extends SystemService {
if (policy.shouldSetAppOpIfNotDefault()) { if (policy.shouldSetAppOpIfNotDefault()) {
mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, op)); mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, op));
} else { } else {
mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, mOpsToAllowIfDefault.add(
op)); new OpToUnrestrict(uid, pkg.packageName,
op));
} }
break; break;
case MODE_FOREGROUND:
Slog.wtf(LOG_TAG,
"Setting appop to foreground is not implemented");
break;
case MODE_IGNORED: case MODE_IGNORED:
if (policy.shouldSetAppOpIfNotDefault()) { if (policy.shouldSetAppOpIfNotDefault()) {
Slog.wtf(LOG_TAG, "Always ignoring appops is not implemented"); mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName, op));
} else { } else {
mOpsToIgnoreIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, mOpsToIgnoreIfDefault.add(
op)); new OpToUnrestrict(uid, pkg.packageName,
op));
} }
break; break;
case MODE_ERRORED: case MODE_ERRORED:
@@ -463,19 +459,59 @@ public final class PermissionPolicyService extends SystemService {
} }
} }
/**
* Add op that belong to a foreground permission for later processing in
* {@link #syncPackages()}.
*
* <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
*
* @param permissionInfo The permission that is currently looked at
* @param pkg The package looked at
*/
private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo, private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo,
@NonNull PackageInfo pkg) { @NonNull PackageInfo pkg) {
if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { final String bgPermissionName = permissionInfo.backgroundPermission;
// Pre-M apps do not store their fg/bg state in the permissions
if (bgPermissionName == null) {
return; return;
} }
if (permissionInfo.backgroundPermission == null) { final String permission = permissionInfo.name;
return; final int opCode = AppOpsManager.permissionToOpCode(permission);
} final String pkgName = pkg.packageName;
final int uid = pkg.applicationInfo.uid;
mFgPermOps.add(new FgPermission(pkg.applicationInfo.uid, pkg.packageName, if (mPackageManager.checkPermission(permission, pkgName)
permissionInfo.name, permissionInfo.backgroundPermission)); == PackageManager.PERMISSION_GRANTED) {
boolean isBgHardRestricted = false;
try {
final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(
bgPermissionName, 0);
if (bgPermInfo.isSoftRestricted()) {
Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
+ "implemented");
}
isBgHardRestricted =
bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
bgPermissionName, pkgName, UserHandle.getUserHandleForUid(uid))
& FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
} catch (NameNotFoundException e) {
Slog.w(LOG_TAG, "Cannot read permission state of " + bgPermissionName, e);
}
final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
pkgName) == PackageManager.PERMISSION_GRANTED;
if (!isBgHardRestricted && isBgPermGranted) {
mOpsToAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
} else {
mOpsToForeground.add(new OpToUnrestrict(uid, pkgName, opCode));
}
} else {
mOpsToIgnore.add(new OpToUnrestrict(uid, pkgName, opCode));
}
} }
/** /**
@@ -525,14 +561,33 @@ public final class PermissionPolicyService extends SystemService {
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
} }
private void setUidModeForeground(int opCode, int uid) {
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_FOREGROUND);
}
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) { private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName); setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
} }
private void setUidModeIgnored(int opCode, int uid) {
mAppOpsManager.setUidMode(opCode, uid, MODE_IGNORED);
}
private void setUidModeIfDefault(int opCode, int uid, int mode, private void setUidModeIfDefault(int opCode, int uid, int mode,
@NonNull String packageName) { @NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager final int currentMode;
.opToPublicName(opCode), uid, packageName); try {
currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
} catch (SecurityException e) {
// This might happen if the app was uninstalled in between the add and sync step.
// In this case the package name cannot be resolved inside appops service and hence
// the uid does not match.
Slog.w(LOG_TAG, "Cannot set mode of uid=" + uid + " op=" + opCode + " to " + mode,
e);
return;
}
if (currentMode == MODE_DEFAULT) { if (currentMode == MODE_DEFAULT) {
mAppOpsManager.setUidMode(opCode, uid, mode); mAppOpsManager.setUidMode(opCode, uid, mode);
} }
@@ -563,21 +618,6 @@ public final class PermissionPolicyService extends SystemService {
this.code = code; this.code = code;
} }
} }
private class FgPermission {
final int uid;
final @NonNull String packageName;
final @NonNull String fgPermissionName;
final @NonNull String bgPermissionName;
private FgPermission(int uid, @NonNull String packageName,
@NonNull String fgPermissionName, @NonNull String bgPermissionName) {
this.uid = uid;
this.packageName = packageName;
this.fgPermissionName = fgPermissionName;
this.bgPermissionName = bgPermissionName;
}
}
} }
private class Internal extends PermissionPolicyInternal { private class Internal extends PermissionPolicyInternal {

View File

@@ -33,7 +33,6 @@ import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.os.Build; import android.os.Build;
import android.util.Log;
/** /**
* The behavior of soft restricted permissions is different for each permission. This class collects * The behavior of soft restricted permissions is different for each permission. This class collects
@@ -43,8 +42,6 @@ import android.util.Log;
* {@link com.android.packageinstaller.permission.utils.SoftRestrictedPermissionPolicy} * {@link com.android.packageinstaller.permission.utils.SoftRestrictedPermissionPolicy}
*/ */
public abstract class SoftRestrictedPermissionPolicy { public abstract class SoftRestrictedPermissionPolicy {
private static final String LOG_TAG = SoftRestrictedPermissionPolicy.class.getSimpleName();
private static final int FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT = private static final int FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT =
FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
| FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
@@ -53,12 +50,12 @@ public abstract class SoftRestrictedPermissionPolicy {
private static final SoftRestrictedPermissionPolicy DUMMY_POLICY = private static final SoftRestrictedPermissionPolicy DUMMY_POLICY =
new SoftRestrictedPermissionPolicy() { new SoftRestrictedPermissionPolicy() {
@Override @Override
public int getAppOp() { public int resolveAppOp() {
return OP_NONE; return OP_NONE;
} }
@Override @Override
public int getAppOpMode() { public int getDesiredOpMode() {
return MODE_DEFAULT; return MODE_DEFAULT;
} }
@@ -100,12 +97,12 @@ public abstract class SoftRestrictedPermissionPolicy {
return new SoftRestrictedPermissionPolicy() { return new SoftRestrictedPermissionPolicy() {
@Override @Override
public int getAppOp() { public int resolveAppOp() {
return OP_LEGACY_STORAGE; return OP_LEGACY_STORAGE;
} }
@Override @Override
public int getAppOpMode() { public int getDesiredOpMode() {
if (applyRestriction) { if (applyRestriction) {
return MODE_DEFAULT; return MODE_DEFAULT;
} else if (hasRequestedLegacyExternalStorage) { } else if (hasRequestedLegacyExternalStorage) {
@@ -119,7 +116,7 @@ public abstract class SoftRestrictedPermissionPolicy {
public boolean shouldSetAppOpIfNotDefault() { public boolean shouldSetAppOpIfNotDefault() {
// Do not switch from allowed -> ignored as this would mean to retroactively // Do not switch from allowed -> ignored as this would mean to retroactively
// turn on isolated storage. This will make the app loose all its files. // turn on isolated storage. This will make the app loose all its files.
return getAppOpMode() != MODE_IGNORED; return getDesiredOpMode() != MODE_IGNORED;
} }
@Override @Override
@@ -127,10 +124,6 @@ public abstract class SoftRestrictedPermissionPolicy {
if (isWhiteListed || targetSDK >= Build.VERSION_CODES.Q) { if (isWhiteListed || targetSDK >= Build.VERSION_CODES.Q) {
return true; return true;
} else { } else {
Log.w(LOG_TAG, permission + " for " + appInfo.packageName
+ " is not whitelisted and targetSDK " + targetSDK + "<"
+ Build.VERSION_CODES.Q);
return false; return false;
} }
} }
@@ -145,16 +138,16 @@ public abstract class SoftRestrictedPermissionPolicy {
* @return An app op to be changed based on the state of the permission or * @return An app op to be changed based on the state of the permission or
* {@link AppOpsManager#OP_NONE} if not app-op should be set. * {@link AppOpsManager#OP_NONE} if not app-op should be set.
*/ */
public abstract int getAppOp(); public abstract int resolveAppOp();
/** /**
* @return The mode the {@link #getAppOp() app op} should be in. * @return The mode the {@link #resolveAppOp() app op} should be in.
*/ */
public abstract @AppOpsManager.Mode int getAppOpMode(); public abstract @AppOpsManager.Mode int getDesiredOpMode();
/** /**
* @return If the {@link #getAppOp() app op} should be set even if the app-op is currently not * @return If the {@link #resolveAppOp() app op} should be set even if the app-op is currently
* {@link AppOpsManager#MODE_DEFAULT}. * not {@link AppOpsManager#MODE_DEFAULT}.
*/ */
public abstract boolean shouldSetAppOpIfNotDefault(); public abstract boolean shouldSetAppOpIfNotDefault();

View File

@@ -35,6 +35,14 @@
"include-filter": "android.permission2.cts.RestrictedPermissionsTest" "include-filter": "android.permission2.cts.RestrictedPermissionsTest"
} }
] ]
},
{
"name": "CtsPermissionTestCases",
"options": [
{
"include-filter": "android.permission.cts.SplitPermissionTest"
}
]
} }
], ],
"postsubmit": [ "postsubmit": [