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

Commit f5c776f7 authored by Nate Myren's avatar Nate Myren Committed by Automerger Merge Worker
Browse files

Do not allow non-system apps to provide unverified attributions am: ec8a2057

parents 516724cf ec8a2057
Loading
Loading
Loading
Loading
+54 −29
Original line number Diff line number Diff line
@@ -589,7 +589,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;
@@ -2503,10 +2503,10 @@ public class AppOpsService extends IAppOpsService.Stub {
    public int checkPackage(int uid, String packageName) {
        Objects.requireNonNull(packageName);
        try {
            verifyAndGetBypass(uid, packageName, null, null, true);
            verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
            // 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, UserHandle.getUserId(uid)))) {
                return AppOpsManager.MODE_ALLOWED;
@@ -2636,7 +2636,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;
@@ -3178,7 +3178,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;
            }
@@ -3671,14 +3671,18 @@ public class AppOpsService extends IAppOpsService.Stub {
    private boolean isSpecialPackage(int callingUid, @Nullable String packageName) {
        final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName);
        return callingUid == Process.SYSTEM_UID
                || resolveUid(resolvedPackage) != Process.INVALID_UID;
                || resolveNonAppUid(resolvedPackage) != Process.INVALID_UID;
    }

    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;
@@ -3760,19 +3764,20 @@ public class AppOpsService extends IAppOpsService.Stub {
    }

    /**
     * @see #verifyAndGetBypass(int, String, String, String, boolean)
     * @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, String, boolean)
     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
     */
    private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
            @Nullable String attributionTag, @Nullable String proxyPackageName) {
        return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false);
            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
        return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
                false);
    }

    /**
@@ -3783,14 +3788,15 @@ 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.
@@ -3834,34 +3840,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);
                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);
@@ -4613,7 +4632,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);
@@ -5628,11 +5647,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<OnOpModeChangedListener> modeChangedListenerSet;
@@ -6077,7 +6102,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    private static int resolveUid(String packageName)  {
    private static int resolveNonAppUid(String packageName)  {
        if (packageName == null) {
            return Process.INVALID_UID;
        }