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

Commit a40ae770 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Do not allow non-system apps to provide unverified attributions" into...

Merge "Do not allow non-system apps to provide unverified attributions" into tm-dev am: db187c34 am: 1ada6a28

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/31450478



Change-Id: I6b54fd1cf2e490ce53df275879935151c4a3a0f3
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 546143b7 1ada6a28
Loading
Loading
Loading
Loading
+63 −25
Original line number Diff line number Diff line
@@ -701,7 +701,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
    /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */
    private static final class PackageVerificationResult {

        final RestrictionBypass bypass;
@@ -3338,7 +3338,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            verifyAndGetBypass(uid, packageName, null);
            // When the caller is the system, it's possible that the packageName is the special
            // one (e.g., "root") which isn't actually existed.
            if (resolveUid(packageName) == uid
            if (resolveNonAppUid(packageName) == uid
                    || (isPackageExisted(packageName) && !filterAppAccessUnlocked(packageName))) {
                return AppOpsManager.MODE_ALLOWED;
            }
@@ -3462,7 +3462,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            boolean shouldCollectMessage) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
            boolean wasNull = attributionTag == null;
            if (!pvr.isAttributionTagValid) {
                attributionTag = null;
@@ -3981,7 +3981,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            int attributionChainId, boolean dryRun) {
        PackageVerificationResult pvr;
        try {
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
            if (!pvr.isAttributionTagValid) {
                attributionTag = null;
            }
@@ -4444,8 +4444,12 @@ public class AppOpsService extends IAppOpsService.Stub {
    private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) {
        if (attributionSource.getUid() != Binder.getCallingUid()
                && attributionSource.isTrusted(mContext)) {
            // if there is a next attribution source, it must be trusted, as well.
            if (attributionSource.getNext() == null
                    || attributionSource.getNext().isTrusted(mContext)) {
                return true;
            }
        }
        return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), null)
                == PackageManager.PERMISSION_GRANTED;
@@ -4582,11 +4586,20 @@ public class AppOpsService extends IAppOpsService.Stub {
    }

    /**
     * @see #verifyAndGetBypass(int, String, String, String)
     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag) {
        return verifyAndGetBypass(uid, packageName, attributionTag, null);
        return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
    }

    /**
     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
        return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
                false);
    }

    /**
@@ -4597,13 +4610,16 @@ public class AppOpsService extends IAppOpsService.Stub {
     * @param uid The uid the package belongs to
     * @param packageName The package the might belong to the uid
     * @param attributionTag attribution tag or {@code null} if no need to verify
     * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
     * @param proxyUid The proxy uid, from which the attribution tag is to be pulled
     * @param proxyPackageName The proxy package, from which the attribution tag may be pulled
     * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
     *
     * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
     *         attribution tag is valid
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag, @Nullable String proxyPackageName) {
            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
            boolean suppressErrorLogs) {
        if (uid == Process.ROOT_UID) {
            // For backwards compatibility, don't check package name for root UID.
            return new PackageVerificationResult(null,
@@ -4646,31 +4662,47 @@ public class AppOpsService extends IAppOpsService.Stub {

        int callingUid = Binder.getCallingUid();

        // Allow any attribution tag for resolvable uids
        int pkgUid;
        // Allow any attribution tag for resolvable, non-app uids
        int nonAppUid;
        if (Objects.equals(packageName, "com.android.shell")) {
            // Special case for the shell which is a package but should be able
            // to bypass app attribution tag restrictions.
            pkgUid = Process.SHELL_UID;
            nonAppUid = Process.SHELL_UID;
        } else {
            pkgUid = resolveUid(packageName);
            nonAppUid = resolveNonAppUid(packageName);
        }
        if (pkgUid != Process.INVALID_UID) {
            if (pkgUid != UserHandle.getAppId(uid)) {
        if (nonAppUid != Process.INVALID_UID) {
            if (nonAppUid != UserHandle.getAppId(uid)) {
                if (!suppressErrorLogs) {
                    Slog.e(TAG, "Bad call made by uid " + callingUid + ". "
                        + "Package \"" + packageName + "\" does not belong to uid " + uid + ".");
                String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
                throw new SecurityException("Specified package \"" + packageName + "\" under uid "
                        +  UserHandle.getAppId(uid) + otherUidMessage);
                                + "Package \"" + packageName + "\" does not belong to uid " + uid
                                + ".");
                }
                String otherUidMessage =
                            DEBUG ? " but it is really " + nonAppUid : " but it is not";
                throw new SecurityException("Specified package \"" + packageName
                            + "\" under uid " +  UserHandle.getAppId(uid) + otherUidMessage);
            }
            // We only allow bypassing the attribution tag verification if the proxy is a
            // system app (or is null), in order to prevent abusive apps clogging the appops
            // system with unlimited attribution tags via proxy calls.
            boolean proxyIsSystemAppOrNull = true;
            if (proxyPackageName != null) {
                int proxyAppId = UserHandle.getAppId(proxyUid);
                if (proxyAppId >= Process.FIRST_APPLICATION_UID) {
                    proxyIsSystemAppOrNull =
                            mPackageManagerInternal.isSystemPackage(proxyPackageName);
                }
            }
            return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
                    /* isAttributionTagValid */ true);
                    /* isAttributionTagValid */ proxyIsSystemAppOrNull);
        }

        int userId = UserHandle.getUserId(uid);
        RestrictionBypass bypass = null;
        boolean isAttributionTagValid = false;

        int pkgUid = nonAppUid;
        final long ident = Binder.clearCallingIdentity();
        try {
            PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
@@ -5537,7 +5569,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            if (nonpackageUid != -1) {
                packageName = null;
            } else {
                packageUid = resolveUid(packageName);
                packageUid = resolveNonAppUid(packageName);
                if (packageUid < 0) {
                    packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
                            PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -6721,11 +6753,17 @@ public class AppOpsService extends IAppOpsService.Stub {
                if (restricted && attrOp.isRunning()) {
                    attrOp.pause();
                } else if (attrOp.isPaused()) {
                    RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag)
                            .bypass;
                    if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag,
                            bypass, false)) {
                        // Only resume if there are no other restrictions remaining on this op
                        attrOp.resume();
                    }
                }
            }
        }
    }

    private void notifyWatchersOfChange(int code, int uid) {
        final ArraySet<ModeCallback> clonedCallbacks;
@@ -7166,7 +7204,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    private static int resolveUid(String packageName)  {
    private static int resolveNonAppUid(String packageName)  {
        if (packageName == null) {
            return -1;
        }