summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Philip P. Moltmann <moltmann@google.com> 2019-06-14 11:08:16 -0700
committer Philip P. Moltmann <moltmann@google.com> 2019-06-19 09:41:17 -0700
commit4e369a79d018263c02cf7b46b4eb76c3efe67d5f (patch)
treed6bf5ce003733f1877aa2c2586faea825ceb8d6f
parentfad1a8fb2f259cb9e699e9ac50c38f87d1921ba6 (diff)
Avoid overiding bg perm app-op for pre-M apps
For pre-M apps the only information about the permission state is encoded in the app-op. This state cannot be computed from the permission state. Hence be very careful to only override this state when sure that it is fine. E.g. one problem is that during the install the permissions are first not whitelisted and then whitelisted shortly after. At this time the permissions state might be lost. Fixes: 135288572, 135190563 Test: atest RestrictedPermissionsTest Change-Id: I8bf74730a6c632313d68f1558c9b67e273c5d7e1
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java99
1 files changed, 64 insertions, 35 deletions
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 48f3d0b95996..68feb4a8445e 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -23,6 +23,7 @@ import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
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_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import android.annotation.NonNull;
@@ -407,6 +408,16 @@ public final class PermissionPolicyService extends SystemService {
*/
private final @NonNull ArrayList<OpToUnrestrict> mOpsToForeground = new ArrayList<>();
+ /**
+ * All ops that need to be flipped to foreground if allow.
+ *
+ * Currently, only used by the foreground/background permissions logic.
+ *
+ * @see #syncPackages
+ */
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToForegroundIfAllow =
+ new ArrayList<>();
+
PermissionToOpSynchroniser(@NonNull Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
@@ -429,8 +440,13 @@ public final class PermissionPolicyService extends SystemService {
final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
}
- final int foregroundCount = mOpsToForeground.size();
+ final int foregroundCount = mOpsToForegroundIfAllow.size();
for (int i = 0; i < foregroundCount; i++) {
+ final OpToUnrestrict op = mOpsToForegroundIfAllow.get(i);
+ setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ }
+ final int foregroundIfAllowCount = mOpsToForeground.size();
+ for (int i = 0; i < foregroundIfAllowCount; i++) {
final OpToUnrestrict op = mOpsToForeground.get(i);
setUidModeForeground(op.code, op.uid, op.packageName);
}
@@ -530,6 +546,24 @@ public final class PermissionPolicyService extends SystemService {
}
}
+ private boolean isBgPermRestricted(@NonNull String pkg, @NonNull String perm, int uid) {
+ try {
+ final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(perm, 0);
+
+ if (bgPermInfo.isSoftRestricted()) {
+ Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
+ + "implemented");
+ }
+
+ return bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
+ perm, pkg, UserHandle.getUserHandleForUid(uid))
+ & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+ } catch (NameNotFoundException e) {
+ Slog.w(LOG_TAG, "Cannot read permission state of " + perm, e);
+ return false;
+ }
+ }
+
/**
* Add op that belong to a foreground permission for later processing in
* {@link #syncPackages()}.
@@ -552,26 +586,27 @@ public final class PermissionPolicyService extends SystemService {
final String pkgName = pkg.packageName;
final int uid = pkg.applicationInfo.uid;
- if (mPackageManager.checkPermission(permission, pkgName)
- == 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);
+ // App does not support runtime permissions. Hence the state is encoded in the app-op.
+ // To not override unrecoverable state don't change app-op unless bg perm is reviewed.
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ // If the review is required for this permission, the grant state does not
+ // really matter. To have a stable state, don't change the app-op if review is still
+ // pending.
+ int flags = mPackageManager.getPermissionFlags(bgPermissionName,
+ pkg.packageName, UserHandle.getUserHandleForUid(uid));
+
+ if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
+ && isBgPermRestricted(pkgName, bgPermissionName, uid)) {
+ mOpsToForegroundIfAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
}
+ return;
+ }
+
+ if (mPackageManager.checkPermission(permission, pkgName)
+ == PackageManager.PERMISSION_GRANTED) {
+ final boolean isBgHardRestricted = isBgPermRestricted(pkgName, bgPermissionName,
+ uid);
final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
pkgName) == PackageManager.PERMISSION_GRANTED;
@@ -625,19 +660,23 @@ public final class PermissionPolicyService extends SystemService {
}
private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
+ setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
}
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
+ private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
+ setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+ }
+
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
+ setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
}
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
@@ -654,23 +693,13 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeIfDefault(int opCode, int uid, int mode,
+ private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
@NonNull String packageName) {
- final int currentMode;
- try {
- currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
+ final int 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) {
- mAppOpsManager.setUidMode(opCode, uid, mode);
+ if (currentMode == requiredModeBefore) {
+ mAppOpsManager.setUidMode(opCode, uid, newMode);
}
}