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

Commit 8452486b authored by Curtis Belmonte's avatar Curtis Belmonte Committed by Automerger Merge Worker
Browse files

DO NOT MERGE Check fingerprint client against top activity in auth callback...

DO NOT MERGE Check fingerprint client against top activity in auth callback am: 1ba154b1 am: 80de6140

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

Change-Id: Iede8de2a6ce8fb783301e7446fe36a7370274ea5
parents 2b42f2d9 80de6140
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -16,16 +16,22 @@

package com.android.server.biometrics;

import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.security.KeyStore;
import android.util.EventLog;
import android.util.Slog;

import java.util.ArrayList;
import java.util.List;

/**
 * A class to keep track of the authentication state for a given client.
@@ -148,7 +154,54 @@ public abstract class AuthenticationClient extends ClientMonitor {
                    + ", requireConfirmation: " + mRequireConfirmation
                    + ", user: " + getTargetUserId());

            // Ensure authentication only succeeds if the client activity is on top or is keyguard.
            boolean isBackgroundAuth = false;
            if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())) {
                try {
                    final List<ActivityManager.RunningTaskInfo> tasks =
                            ActivityTaskManager.getService().getTasks(1);
                    if (tasks == null || tasks.isEmpty()) {
                        Slog.e(TAG, "No running tasks reported");
                        isBackgroundAuth = true;
                    } else {
                        final ComponentName topActivity = tasks.get(0).topActivity;
                        if (topActivity == null) {
                            Slog.e(TAG, "Unable to get top activity");
                            isBackgroundAuth = true;
                        } else {
                            final String topPackage = topActivity.getPackageName();
                            if (!topPackage.contentEquals(getOwnerString())) {
                                Slog.e(TAG, "Background authentication detected, top: " + topPackage
                                        + ", client: " + this);
                                isBackgroundAuth = true;
                            }
                        }
                    }
                } catch (RemoteException e) {
                    Slog.e(TAG, "Unable to get running tasks", e);
                    isBackgroundAuth = true;
                }
            }

            // Fail authentication if we can't confirm the client activity is on top.
            if (isBackgroundAuth) {
                Slog.e(TAG, "Failing possible background authentication");
                authenticated = false;

                // SafetyNet logging for exploitation attempts of b/159249069.
                final ApplicationInfo appInfo = getContext().getApplicationInfo();
                EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
                        "Attempted background authentication");
            }

            if (authenticated) {
                // SafetyNet logging for b/159249069 if constraint is violated.
                if (isBackgroundAuth) {
                    final ApplicationInfo appInfo = getContext().getApplicationInfo();
                    EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
                            "Successful background authentication!");
                }

                mAlreadyDone = true;

                if (listener != null) {
+16 −0
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@

package com.android.server.biometrics;

import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricManager.Authenticators;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
@@ -29,6 +32,8 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;

import com.android.internal.R;

public class Utils {
    public static boolean isDebugEnabled(Context context, int targetUserId) {
        if (targetUserId == UserHandle.USER_NULL) {
@@ -256,4 +261,15 @@ public class Utils {
                throw new IllegalArgumentException("Unsupported dismissal reason: " + reason);
        }
    }

    static boolean isKeyguard(Context context, String clientPackage) {
        final boolean hasPermission = context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
                == PackageManager.PERMISSION_GRANTED;

        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                context.getResources().getString(R.string.config_keyguardComponent));
        final String keyguardPackage = keyguardComponent != null
                ? keyguardComponent.getPackageName() : null;
        return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage);
    }
}