Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ff73c56 authored by Yuting Fang's avatar Yuting Fang Committed by Android (Google) Code Review
Browse files

Merge "[DeviceAwareAppOp] Fix the bug that misuses device Id in proxy and...

Merge "[DeviceAwareAppOp] Fix the bug that misuses device Id in proxy and proxied attribution source" into main
parents c1513687 332f702f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -461,6 +461,20 @@ public final class AttributionSource implements Parcelable {
        return null;
    }

    /**
     * @return The next package's device Id from its context.
     * This device ID is used for permissions checking during attribution source validation.
     *
     * @hide
     */
    public int getNextDeviceId() {
        if (mAttributionSourceState.next != null
                && mAttributionSourceState.next.length > 0) {
            return mAttributionSourceState.next[0].deviceId;
        }
        return Context.DEVICE_ID_DEFAULT;
    }

    /**
     * Checks whether this attribution source can be trusted. That is whether
     * the app it refers to created it and provided to the attribution chain.
+53 −33
Original line number Diff line number Diff line
@@ -2912,10 +2912,12 @@ public class AppOpsService extends IAppOpsService.Stub {
        final int proxyUid = attributionSource.getUid();
        final String proxyPackageName = attributionSource.getPackageName();
        final String proxyAttributionTag = attributionSource.getAttributionTag();
        final int proxiedUid = attributionSource.getNextUid();
        final int proxyVirtualDeviceId = attributionSource.getDeviceId();

        final int proxiedUid = attributionSource.getNextUid();
        final String proxiedPackageName = attributionSource.getNextPackageName();
        final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
        final int proxiedVirtualDeviceId = attributionSource.getNextDeviceId();

        verifyIncomingProxyUid(attributionSource);
        verifyIncomingOp(code);
@@ -2952,7 +2954,8 @@ public class AppOpsService extends IAppOpsService.Stub {

            final SyncNotedAppOp proxyReturn = noteOperationUnchecked(code, proxyUid,
                    resolveProxyPackageName, proxyAttributionTag, proxyVirtualDeviceId,
                    Process.INVALID_UID, null, null, proxyFlags, !isProxyTrusted,
                    Process.INVALID_UID, null, null,
                    Context.DEVICE_ID_DEFAULT, proxyFlags, !isProxyTrusted,
                    "proxy " + message, shouldCollectMessage);
            if (proxyReturn.getOpMode() != AppOpsManager.MODE_ALLOWED) {
                return new SyncNotedAppOp(proxyReturn.getOpMode(), code, proxiedAttributionTag,
@@ -2970,9 +2973,9 @@ public class AppOpsService extends IAppOpsService.Stub {
        final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
                : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
        return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
                proxiedAttributionTag, proxyVirtualDeviceId, proxyUid, resolveProxyPackageName,
                proxyAttributionTag, proxiedFlags, shouldCollectAsyncNotedOp, message,
                shouldCollectMessage);
                proxiedAttributionTag, proxiedVirtualDeviceId, proxyUid, resolveProxyPackageName,
                proxyAttributionTag, proxyVirtualDeviceId, proxiedFlags, shouldCollectAsyncNotedOp,
                message, shouldCollectMessage);
    }

    @Override
@@ -3023,14 +3026,14 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
        return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
                virtualDeviceId, Process.INVALID_UID, null, null,
                AppOpsManager.OP_FLAG_SELF, shouldCollectAsyncNotedOp, message,
                shouldCollectMessage);
                Context.DEVICE_ID_DEFAULT, AppOpsManager.OP_FLAG_SELF, shouldCollectAsyncNotedOp,
                message, shouldCollectMessage);
    }

    private SyncNotedAppOp noteOperationUnchecked(int code, int uid, @NonNull String packageName,
            @Nullable String attributionTag, int virtualDeviceId, int proxyUid,
            String proxyPackageName, @Nullable String proxyAttributionTag, @OpFlags int flags,
            boolean shouldCollectAsyncNotedOp, @Nullable String message,
            String proxyPackageName, @Nullable String proxyAttributionTag, int proxyVirtualDeviceId,
            @OpFlags int flags, boolean shouldCollectAsyncNotedOp, @Nullable String message,
            boolean shouldCollectMessage) {
        PackageVerificationResult pvr;
        try {
@@ -3161,8 +3164,9 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
            scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag,
                    virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED);

            attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag,
                    uidState.getState(), flags);
                    getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags);

            if (shouldCollectAsyncNotedOp) {
                collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
@@ -3528,9 +3532,9 @@ public class AppOpsService extends IAppOpsService.Stub {
        }

        return startOperationUnchecked(clientId, code, uid, packageName, attributionTag,
                virtualDeviceId, Process.INVALID_UID, null, null, OP_FLAG_SELF,
                startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
                attributionFlags, attributionChainId);
                virtualDeviceId, Process.INVALID_UID, null, null, Context.DEVICE_ID_DEFAULT,
                OP_FLAG_SELF, startIfModeDefault, shouldCollectAsyncNotedOp, message,
                shouldCollectMessage, attributionFlags, attributionChainId);
    }

    /** @deprecated Use {@link #startProxyOperationWithState} instead. */
@@ -3568,18 +3572,32 @@ public class AppOpsService extends IAppOpsService.Stub {
        final int proxyUid = attributionSource.getUid();
        final String proxyPackageName = attributionSource.getPackageName();
        final String proxyAttributionTag = attributionSource.getAttributionTag();
        final int proxiedUid = attributionSource.getNextUid();
        final int proxyVirtualDeviceId = attributionSource.getDeviceId();

        final int proxiedUid = attributionSource.getNextUid();
        final String proxiedPackageName = attributionSource.getNextPackageName();
        final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
        final int proxiedVirtualDeviceId = attributionSource.getNextDeviceId();

        verifyIncomingProxyUid(attributionSource);
        verifyIncomingOp(code);
        if (!isValidVirtualDeviceId(proxyVirtualDeviceId)) {
            Slog.w(TAG, "startProxyOperationImpl returned MODE_IGNORED as virtualDeviceId "
                    + proxyVirtualDeviceId + " is invalid");
            return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag,
                    proxiedPackageName);
            Slog.w(
                    TAG,
                    "startProxyOperationImpl returned MODE_IGNORED as proxyVirtualDeviceId "
                            + proxyVirtualDeviceId
                            + " is invalid");
            return new SyncNotedAppOp(
                    AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, proxiedPackageName);
        }
        if (!isValidVirtualDeviceId(proxiedVirtualDeviceId)) {
            Slog.w(
                    TAG,
                    "startProxyOperationImpl returned MODE_IGNORED as proxiedVirtualDeviceId "
                            + proxiedVirtualDeviceId
                            + " is invalid");
            return new SyncNotedAppOp(
                    AppOpsManager.MODE_IGNORED, code, proxiedAttributionTag, proxiedPackageName);
        }
        if (!isIncomingPackageValid(proxyPackageName, UserHandle.getUserId(proxyUid))
                || !isIncomingPackageValid(proxiedPackageName, UserHandle.getUserId(proxiedUid))) {
@@ -3621,7 +3639,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            // Test if the proxied operation will succeed before starting the proxy operation
            final SyncNotedAppOp testProxiedOp = startOperationDryRun(code,
                    proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag,
                    proxyVirtualDeviceId, resolvedProxyPackageName, proxiedFlags,
                    proxiedVirtualDeviceId, resolvedProxyPackageName, proxiedFlags,
                    startIfModeDefault);

            if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) {
@@ -3633,7 +3651,7 @@ public class AppOpsService extends IAppOpsService.Stub {

            final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid,
                    resolvedProxyPackageName, proxyAttributionTag, proxyVirtualDeviceId,
                    Process.INVALID_UID, null, null, proxyFlags,
                    Process.INVALID_UID, null, null, Context.DEVICE_ID_DEFAULT, proxyFlags,
                    startIfModeDefault, !isProxyTrusted, "proxy " + message,
                    shouldCollectMessage, proxyAttributionFlags, attributionChainId);
            if (!shouldStartForMode(proxyAppOp.getOpMode(), startIfModeDefault)) {
@@ -3642,9 +3660,10 @@ public class AppOpsService extends IAppOpsService.Stub {
        }

        return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
                proxiedAttributionTag, proxyVirtualDeviceId, proxyUid, resolvedProxyPackageName,
                proxyAttributionTag, proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp,
                message, shouldCollectMessage, proxiedAttributionFlags, attributionChainId);
                proxiedAttributionTag, proxiedVirtualDeviceId, proxyUid, resolvedProxyPackageName,
                proxyAttributionTag, proxyVirtualDeviceId, proxiedFlags, startIfModeDefault,
                shouldCollectAsyncNotedOp, message, shouldCollectMessage, proxiedAttributionFlags,
                attributionChainId);
    }

    private boolean shouldStartForMode(int mode, boolean startIfModeDefault) {
@@ -3654,9 +3673,10 @@ public class AppOpsService extends IAppOpsService.Stub {
    private SyncNotedAppOp startOperationUnchecked(IBinder clientId, int code, int uid,
            @NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId,
            int proxyUid, String proxyPackageName, @Nullable String proxyAttributionTag,
            @OpFlags int flags, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
            @Nullable String message, boolean shouldCollectMessage,
            @AttributionFlags int attributionFlags, int attributionChainId) {
            int proxyVirtualDeviceId, @OpFlags int flags, boolean startIfModeDefault,
            boolean shouldCollectAsyncNotedOp, @Nullable String message,
            boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
            int attributionChainId) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
@@ -3751,13 +3771,13 @@ public class AppOpsService extends IAppOpsService.Stub {
                    + " flags: " + AppOpsManager.flagsToString(flags));
            try {
                if (isRestricted) {
                    attributedOp.createPaused(clientId, proxyUid, proxyPackageName,
                            proxyAttributionTag, virtualDeviceId, uidState.getState(), flags,
                            attributionFlags, attributionChainId);
                    attributedOp.createPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName,
                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
                            uidState.getState(), flags, attributionFlags, attributionChainId);
                } else {
                    attributedOp.started(clientId, proxyUid, proxyPackageName,
                            proxyAttributionTag, virtualDeviceId, uidState.getState(), flags,
                            attributionFlags, attributionChainId);
                    attributedOp.started(clientId, virtualDeviceId, proxyUid, proxyPackageName,
                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
                            uidState.getState(), flags, attributionFlags, attributionChainId);
                    startType = START_TYPE_STARTED;
                }
            } catch (RemoteException e) {
@@ -4946,7 +4966,7 @@ public class AppOpsService extends IAppOpsService.Stub {

        if (accessTime > 0) {
            attributedOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg,
                    proxyAttributionTag, uidState, opFlags);
                    proxyAttributionTag, PERSISTENT_DEVICE_ID_DEFAULT, uidState, opFlags);
        }
        if (rejectTime > 0) {
            attributedOp.rejected(rejectTime, uidState, opFlags);
+49 −45
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.companion.virtual.VirtualDeviceManager;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -95,16 +94,17 @@ final class AttributedOp {
     *
     * @param proxyUid            The uid of the proxy
     * @param proxyPackageName    The package name of the proxy
     * @param proxyAttributionTag the attributionTag in the proxies package
     * @param proxyAttributionTag The attributionTag in the proxies package
     * @param proxyDeviceId       The device Id of the proxy
     * @param uidState            UID state of the app noteOp/startOp was called for
     * @param flags               OpFlags of the call
     */
    public void accessed(int proxyUid, @Nullable String proxyPackageName,
            @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags) {
            @Nullable String proxyAttributionTag, @Nullable String proxyDeviceId,
            @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags) {
        long accessTime = System.currentTimeMillis();
        accessed(accessTime, -1, proxyUid, proxyPackageName,
                proxyAttributionTag, uidState, flags);
        accessed(accessTime, -1, proxyUid, proxyPackageName, proxyAttributionTag, proxyDeviceId,
                uidState, flags);

        mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                parent.packageName, tag, uidState, flags, accessTime,
@@ -118,14 +118,16 @@ final class AttributedOp {
     * @param duration            The duration of the event
     * @param proxyUid            The uid of the proxy
     * @param proxyPackageName    The package name of the proxy
     * @param proxyAttributionTag the attributionTag in the proxies package
     * @param proxyAttributionTag The attributionTag in the proxies package
     * @param proxyDeviceId       The device Id of the proxy
     * @param uidState            UID state of the app noteOp/startOp was called for
     * @param flags               OpFlags of the call
     */
    @SuppressWarnings("GuardedBy") // Lock is held on mAppOpsService
    public void accessed(long noteTime, long duration, int proxyUid,
            @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
            @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags) {
            @Nullable String proxyDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags) {
        long key = makeKey(uidState, flags);

        if (mAccessEvents == null) {
@@ -135,7 +137,7 @@ final class AttributedOp {
        AppOpsManager.OpEventProxyInfo proxyInfo = null;
        if (proxyUid != Process.INVALID_UID) {
            proxyInfo = mAppOpsService.mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
                            proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
                    proxyAttributionTag, proxyDeviceId);
        }

        AppOpsManager.NoteOpEvent existingEvent = mAccessEvents.get(key);
@@ -189,35 +191,36 @@ final class AttributedOp {
     * Update state when start was called
     *
     * @param clientId            Id of the startOp caller
     * @param virtualDeviceId     The virtual device id of the startOp caller
     * @param proxyUid            The UID of the proxy app
     * @param proxyPackageName    The package name of the proxy app
     * @param proxyAttributionTag The attribution tag of the proxy app
     * @param proxyDeviceId       The device id of the proxy app
     * @param uidState            UID state of the app startOp is called for
     * @param flags               The proxy flags
     * @param attributionFlags    The attribution flags associated with this operation.
     * @param attributionChainId  The if of the attribution chain this operations is a part of.
     * @param attributionChainId  The if of the attribution chain this operations is a part of
     */
    public void started(@NonNull IBinder clientId, int proxyUid,
    public void started(@NonNull IBinder clientId, int virtualDeviceId, int proxyUid,
            @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
            int proxyVirtualDeviceId, @AppOpsManager.UidState int uidState,
            @Nullable String proxyDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags, @AppOpsManager.AttributionFlags int attributionFlags,
            int attributionChainId) throws RemoteException {
        startedOrPaused(clientId, proxyUid, proxyPackageName,
                proxyAttributionTag, proxyVirtualDeviceId, uidState, flags,
                /* triggeredByUidStateChange */ false, /* isStarted */ true, attributionFlags,
                attributionChainId);
        startedOrPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName, proxyAttributionTag,
                proxyDeviceId, uidState, flags, attributionFlags, attributionChainId, false,
                true);
    }

    @SuppressWarnings("GuardedBy") // Lock is held on mAppOpsService
    private void startedOrPaused(@NonNull IBinder clientId, int proxyUid,
    private void startedOrPaused(@NonNull IBinder clientId, int virtualDeviceId, int proxyUid,
            @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
            int proxyVirtualDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags, boolean triggeredByUidStateChange,
            boolean isStarted, @AppOpsManager.AttributionFlags int attributionFlags,
            int attributionChainId) throws RemoteException {
            @Nullable String proxyDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags, @AppOpsManager.AttributionFlags int attributionFlags,
            int attributionChainId, boolean triggeredByUidStateChange, boolean isStarted)
            throws RemoteException {
        if (!triggeredByUidStateChange && !parent.isRunning() && isStarted) {
            mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
                    parent.packageName, tag, proxyVirtualDeviceId, true, attributionFlags,
                    parent.packageName, tag, virtualDeviceId, true, attributionFlags,
                    attributionChainId);
        }

@@ -233,9 +236,9 @@ final class AttributedOp {
        InProgressStartOpEvent event = events.get(clientId);
        if (event == null) {
            event = mAppOpsService.mInProgressStartOpEventPool.acquire(startTime,
                    SystemClock.elapsedRealtime(), clientId, tag, proxyVirtualDeviceId,
                    SystemClock.elapsedRealtime(), clientId, tag, virtualDeviceId,
                    PooledLambda.obtainRunnable(AppOpsService::onClientDeath, this, clientId),
                    proxyUid, proxyPackageName, proxyAttributionTag, uidState, flags,
                    proxyUid, proxyPackageName, proxyAttributionTag, proxyDeviceId, uidState, flags,
                    attributionFlags, attributionChainId);
            events.put(clientId, event);
        } else {
@@ -366,15 +369,14 @@ final class AttributedOp {
    /**
     * Create an event that will be started, if the op is unpaused.
     */
    public void createPaused(@NonNull IBinder clientId, int proxyUid,
            @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
            int proxyVirtualDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags,
            @AppOpsManager.AttributionFlags int attributionFlags,
    public void createPaused(@NonNull IBinder clientId, int virtualDeviceId,
            int proxyUid, @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
            @Nullable String proxyDeviceId, @AppOpsManager.UidState int uidState,
            @AppOpsManager.OpFlags int flags, @AppOpsManager.AttributionFlags int attributionFlags,
            int attributionChainId) throws RemoteException {
        startedOrPaused(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
                proxyVirtualDeviceId, uidState, flags, false, false,
                attributionFlags, attributionChainId);
        startedOrPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName, proxyAttributionTag,
                proxyDeviceId, uidState, flags, attributionFlags, attributionChainId, false,
                false);
    }

    /**
@@ -496,16 +498,16 @@ final class AttributedOp {
                    // Call started() to add a new start event object and then add the
                    // previously removed unfinished start counts back
                    if (proxy != null) {
                        startedOrPaused(event.getClientId(), proxy.getUid(),
                                proxy.getPackageName(), proxy.getAttributionTag(),
                                event.getVirtualDeviceId(), newState, event.getFlags(),
                                true, isRunning,
                                event.getAttributionFlags(), event.getAttributionChainId());
                        startedOrPaused(event.getClientId(), event.getVirtualDeviceId(),
                                proxy.getUid(), proxy.getPackageName(), proxy.getAttributionTag(),
                                proxy.getDeviceId(), newState, event.getFlags(),
                                event.getAttributionFlags(), event.getAttributionChainId(), true,
                                isRunning);
                    } else {
                        startedOrPaused(event.getClientId(), Process.INVALID_UID, null, null,
                                event.getVirtualDeviceId(), newState, event.getFlags(), true,
                                isRunning, event.getAttributionFlags(),
                                event.getAttributionChainId());
                        startedOrPaused(event.getClientId(), event.getVirtualDeviceId(),
                                Process.INVALID_UID, null, null, null,
                                newState, event.getFlags(), event.getAttributionFlags(),
                                event.getAttributionChainId(), true, isRunning);
                    }

                    events = isRunning ? mInProgressEvents : mPausedInProgressEvents;
@@ -847,7 +849,8 @@ final class AttributedOp {
        InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId,
                @Nullable String attributionTag, int virtualDeviceId,  @NonNull Runnable onDeath,
                int proxyUid, @Nullable String proxyPackageName,
                @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState,
                @Nullable String proxyAttributionTag, @Nullable String proxyDeviceId,
                @AppOpsManager.UidState int uidState,
                @AppOpsManager.OpFlags int flags, @AppOpsManager.AttributionFlags
                int attributionFlags, int attributionChainId) throws RemoteException {

@@ -856,7 +859,7 @@ final class AttributedOp {
            AppOpsManager.OpEventProxyInfo proxyInfo = null;
            if (proxyUid != Process.INVALID_UID) {
                proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
                        proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
                        proxyAttributionTag, proxyDeviceId);
            }

            if (recycled != null) {
@@ -880,7 +883,8 @@ final class AttributedOp {
            super(maxUnusedPooledObjects);
        }

        AppOpsManager.OpEventProxyInfo acquire(@IntRange(from = 0) int uid,
        AppOpsManager.OpEventProxyInfo acquire(
                @IntRange(from = 0) int uid,
                @Nullable String packageName,
                @Nullable String attributionTag,
                @Nullable String deviceId) {
@@ -890,7 +894,7 @@ final class AttributedOp {
                return recycled;
            }

            return new AppOpsManager.OpEventProxyInfo(uid, packageName, attributionTag);
            return new AppOpsManager.OpEventProxyInfo(uid, packageName, attributionTag, deviceId);
        }
    }
}
+149 −0

File added.

Preview size limit exceeded, changes collapsed.