Merge "Track active AttributionSources, and finish chains on death" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-07-20 19:36:21 +00:00
committed by Android (Google) Code Review

View File

@@ -172,6 +172,7 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@@ -180,6 +181,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@@ -219,6 +221,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
/** If the permission of the value is granted, so is the key */ /** If the permission of the value is granted, so is the key */
private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>(); private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
/** Map of IBinder -> Running AttributionSource */
private static final ConcurrentHashMap<IBinder, RegisteredAttribution>
sRunningAttributionSources = new ConcurrentHashMap<>();
static { static {
FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION);
@@ -5555,8 +5561,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override @Override
public void finishDataDelivery(int op, public void finishDataDelivery(int op,
@NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) {
finishDataDelivery(mContext, op, attributionSourceState,
fromDataSource);
}
private static void finishDataDelivery(Context context, int op,
@NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
Objects.requireNonNull(attributionSourceState); Objects.requireNonNull(attributionSourceState);
AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
if (op == AppOpsManager.OP_NONE) { if (op == AppOpsManager.OP_NONE) {
return; return;
@@ -5573,7 +5586,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If the call is from a datasource we need to vet only the chain before it. This // If the call is from a datasource we need to vet only the chain before it. This
// way we can avoid the datasource creating an attribution context for every call. // way we can avoid the datasource creating an attribution context for every call.
if (!(fromDatasource && current.asState() == attributionSourceState) if (!(fromDatasource && current.asState() == attributionSourceState)
&& next != null && !current.isTrusted(mContext)) { && next != null && !current.isTrusted(context)) {
return; return;
} }
@@ -5589,20 +5602,20 @@ public class PermissionManagerService extends IPermissionManager.Stub {
? current : next; ? current : next;
if (selfAccess) { if (selfAccess) {
final String resolvedPackageName = resolvePackageName(mContext, accessorSource); final String resolvedPackageName = resolvePackageName(context, accessorSource);
if (resolvedPackageName == null) { if (resolvedPackageName == null) {
return; return;
} }
mAppOpsManager.finishOp(accessorSource.getToken(), op, appOpsManager.finishOp(accessorSource.getToken(), op,
accessorSource.getUid(), resolvedPackageName, accessorSource.getUid(), resolvedPackageName,
accessorSource.getAttributionTag()); accessorSource.getAttributionTag());
} else { } else {
final AttributionSource resolvedAttributionSource = final AttributionSource resolvedAttributionSource =
resolveAttributionSource(mContext, accessorSource); resolveAttributionSource(context, accessorSource);
if (resolvedAttributionSource.getPackageName() == null) { if (resolvedAttributionSource.getPackageName() == null) {
return; return;
} }
mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
resolvedAttributionSource, skipCurrentFinish); resolvedAttributionSource, skipCurrentFinish);
} }
@@ -5610,6 +5623,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return; return;
} }
RegisteredAttribution registered =
sRunningAttributionSources.remove(current.getToken());
if (registered != null) {
registered.unregister();
}
current = next; current = next;
} }
} }
@@ -5827,6 +5845,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
} }
} }
if (startDataDelivery) {
RegisteredAttribution registered = new RegisteredAttribution(context, op,
current, fromDatasource);
sRunningAttributionSources.put(current.getToken(), registered);
}
if (next == null || next.getNext() == null) { if (next == null || next.getNext() == null) {
return PermissionChecker.PERMISSION_GRANTED; return PermissionChecker.PERMISSION_GRANTED;
} }
@@ -6153,4 +6177,43 @@ public class PermissionManagerService extends IPermissionManager.Stub {
attributionSource)); attributionSource));
} }
} }
private static final class RegisteredAttribution {
private final DeathRecipient mDeathRecipient;
private final IBinder mToken;
private final AtomicBoolean mFinished;
RegisteredAttribution(Context context, int op, AttributionSource source,
boolean fromDatasource) {
mFinished = new AtomicBoolean(false);
mDeathRecipient = () -> {
if (unregister()) {
PermissionCheckerService
.finishDataDelivery(context, op, source.asState(), fromDatasource);
}
};
mToken = source.getToken();
if (mToken != null) {
try {
mToken.linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
mDeathRecipient.binderDied();
}
}
}
public boolean unregister() {
if (mFinished.compareAndSet(false, true)) {
try {
if (mToken != null) {
mToken.unlinkToDeath(mDeathRecipient, 0);
}
} catch (NoSuchElementException e) {
// do nothing
}
return true;
}
return false;
}
}
} }