summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Atneya Nair <atneya@google.com> 2024-10-31 22:03:01 -0700
committer Atneya Nair <atneya@google.com> 2024-10-31 22:03:01 -0700
commit0f09c2f475d06e6802085755aa3fffe729f3a256 (patch)
treeb05c90cf12eb805b36edcc06dd13bef9c2032afb
parent95cff9b40e17bc21a202be71d0cfa58515996bbd (diff)
appops: Finish started proxy op when chain fails
A more precise version of I92060d44e666fa6725411de5d714ac0d380f42ae This fixes an issue where we finish the op which failed permission checks... which causes refcount mismatches again. Instead, ensure that we finish only the proxy ops which were *successfully* started: acheiving this by pushing the cleanup into the checkPerm loop which iterates through the attr chain. Technically this should also be added for appop permissions, but focus on runtime appops for now, since that is where the security issue is. Test: CtsMediaAudioPermissionTestCases Bug: 293603271 Flag: EXEMPT security Change-Id: Ifced9449e47b09c7a1a9982c73d4871302a742a2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java26
1 files changed, 21 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 5fc3e332b95c..24933cab2a32 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1015,7 +1015,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
permission, attributionSource, message, forDataDelivery, startDataDelivery,
fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
- if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
+ if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
+ && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
if (attributedOp == AppOpsManager.OP_NONE) {
finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
attributionSource.asState(), fromDatasource);
@@ -1244,6 +1245,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
AttributionSource current = attributionSource;
AttributionSource next = null;
+ AttributionSource prev = null;
// We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
// every attributionSource in the chain is registered with the system.
final boolean isChainStartTrusted = !hasChain || checkPermission(context,
@@ -1310,8 +1312,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
selfAccess, singleReceiverFromDatasource, attributedOp,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
- switch (opMode) {
- case AppOpsManager.MODE_ERRORED: {
+ if (opMode != AppOpsManager.MODE_ALLOWED) {
+ // Current failed the perm check, so if we are part-way through an attr chain,
+ // we need to clean up the already started proxy op higher up the chain. Note,
+ // proxy ops are verified two by two, which means we have to clear the 2nd next
+ // from the previous iteration (since it is actually curr.next which failed
+ // to pass the perm check).
+ if (prev != null) {
+ final var cutAttrSourceState = prev.asState();
+ if (cutAttrSourceState.next.length > 0) {
+ cutAttrSourceState.next[0].next = new AttributionSourceState[0];
+ }
+ finishDataDelivery(context, attributedOp,
+ cutAttrSourceState, fromDatasource);
+ }
+ if (opMode == AppOpsManager.MODE_ERRORED) {
if (permission.equals(Manifest.permission.BLUETOOTH_CONNECT)) {
Slog.e(LOG_TAG, "BLUETOOTH_CONNECT permission hard denied as op"
+ " mode is MODE_ERRORED. Permission check was requested for: "
@@ -1319,8 +1334,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ current);
}
return PermissionChecker.PERMISSION_HARD_DENIED;
- }
- case AppOpsManager.MODE_IGNORED: {
+ } else {
return PermissionChecker.PERMISSION_SOFT_DENIED;
}
}
@@ -1335,6 +1349,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return PermissionChecker.PERMISSION_GRANTED;
}
+ // an attribution we have already possibly started an op for
+ prev = current;
current = next;
}
}