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

Unverified Commit 1d8f2ed2 authored by Kevin F. Haggerty's avatar Kevin F. Haggerty
Browse files

Merge tag 'android-security-8.1.0_r84' into staging/lineage-15.1_merge_android-security-8.1.0_r84

Android security 8.1.0 release 84

* tag 'android-security-8.1.0_r84':
  Protect GrantCredentialsPermissionActivity against overlay.
  [DO NOT MERGE] Make GlobalScreenshot PendingIntents immutable
  Ignore GrantCredentials call with unexpected calling uid.
  Check that Account Parcel has name and type.
  Revoke permission on non-runtime -> runtime upgrade
  Ensure permissions are revoked on state changes
  RESTRICT AUTOMERGE Fix CDM package check
  DO NOT MERGE Check fingerprint client against top activity in auth callback

Change-Id: I0491f0e1ab635dacbd4188c3aa601f5ad5742f8d
parents c9cb9098 9d57d470
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -88,6 +88,12 @@ public class Account implements Parcelable {
    public Account(Parcel in) {
        this.name = in.readString();
        this.type = in.readString();
        if (TextUtils.isEmpty(name)) {
            throw new android.os.BadParcelableException("the name must not be empty: " + name);
        }
        if (TextUtils.isEmpty(type)) {
            throw new android.os.BadParcelableException("the type must not be empty: " + type);
        }
        this.accessId = in.readString();
        if (accessId != null) {
            synchronized (sAccessedAccounts) {
+31 −6
Original line number Diff line number Diff line
@@ -16,16 +16,23 @@
package android.accounts;

import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.view.View;
import android.view.LayoutInflater;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.internal.R;

import java.io.IOException;
@@ -42,11 +49,15 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
    private Account mAccount;
    private String mAuthTokenType;
    private int mUid;
    private int mCallingUid;
    private Bundle mResultBundle = null;
    protected LayoutInflater mInflater;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addPrivateFlags(
                android.view.WindowManager.LayoutParams
                        .PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        setContentView(R.layout.grant_credentials_permission);
        setTitle(R.string.grant_permissions_header_text);

@@ -74,6 +85,20 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
            return;
        }

        try {
            IBinder activityToken = getActivityToken();
            mCallingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
        } catch (RemoteException re) {
            // Couldn't figure out caller details
            Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
        }

        if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) {
            setResult(Activity.RESULT_CANCELED);
            finish();
            return;
        }

        String accountTypeLabel;
        try {
            accountTypeLabel = getAccountLabel(mAccount);
+41 −30
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ class SaveImageInBackgroundData {
        imageUri = null;
        iconSize = 0;
    }

    void clearContext() {
        context = null;
    }
@@ -390,7 +391,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            mPublicNotificationBuilder
                    .setContentTitle(r.getString(R.string.screenshot_saved_title))
                    .setContentText(r.getString(R.string.screenshot_saved_text))
                    .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                    .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent,
                            PendingIntent.FLAG_IMMUTABLE))
                    .setWhen(now)
                    .setAutoCancel(true)
                    .setColor(context.getColor(
@@ -398,7 +400,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
            mNotificationBuilder
                    .setContentTitle(r.getString(R.string.screenshot_saved_title))
                    .setContentText(r.getString(R.string.screenshot_saved_text))
                .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                    .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent,
                            PendingIntent.FLAG_IMMUTABLE))
                    .setWhen(now)
                    .setAutoCancel(true)
                    .setColor(context.getColor(
@@ -507,7 +510,8 @@ class GlobalScreenshot {
        mDisplayMatrix = new Matrix();
        mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
        mScreenshotSelectorLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
        mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
        mBackgroundView = (ImageView) mScreenshotLayout.findViewById(
                R.id.global_screenshot_background);
        mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
        mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
        mScreenshotSelectorView = (ScreenshotSelectorView) mScreenshotSelectorLayout.findViewById(
@@ -536,6 +540,7 @@ class GlobalScreenshot {
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mNotificationManager =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        mDisplay = mWindowManager.getDefaultDisplay();
        mDisplayMetrics = new DisplayMetrics();
        mDisplay.getRealMetrics(mDisplayMetrics);
@@ -781,6 +786,7 @@ class GlobalScreenshot {
            }
        });
    }

    private ValueAnimator createScreenshotDropInAnimation() {
        final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
                / SCREENSHOT_DROP_IN_DURATION);
@@ -821,6 +827,7 @@ class GlobalScreenshot {
                mScreenshotFlash.setAlpha(0f);
                mScreenshotFlash.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationEnd(android.animation.Animator animation) {
                mScreenshotFlash.setVisibility(View.GONE);
@@ -842,6 +849,7 @@ class GlobalScreenshot {
        });
        return anim;
    }

    private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
            boolean navBarVisible) {
        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
@@ -863,7 +871,8 @@ class GlobalScreenshot {
                public void onAnimationUpdate(ValueAnimator animation) {
                    float t = (Float) animation.getAnimatedValue();
                    float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
                            - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
                            - t * (SCREENSHOT_DROP_IN_MIN_SCALE
                            - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
                    mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
                    mScreenshotView.setAlpha(1f - t);
                    mScreenshotView.setScaleX(scaleT);
@@ -890,8 +899,10 @@ class GlobalScreenshot {
            float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
            final float offsetPct = SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET;
            final PointF finalPos = new PointF(
                -halfScreenWidth + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
                -halfScreenHeight + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);
                    -halfScreenWidth
                            + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
                    -halfScreenHeight
                            + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);

            // Animate the screenshot to the status bar
            anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
@@ -936,7 +947,7 @@ class GlobalScreenshot {
                DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
        if (intent != null) {
            final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
                    context, 0, intent, 0, null, UserHandle.CURRENT);
                    context, 0, intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
            b.setContentIntent(pendingIntent);
        }

+5 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.internal.util.Preconditions.checkState;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
@@ -275,7 +276,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind

            checkArgument(getCallingUserId() == userId,
                    "Must be called by either same user or system");
            mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
            int callingUid = Binder.getCallingUid();
            if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
                throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
            }
        }

        @Override
+91 −3
Original line number Diff line number Diff line
@@ -16,18 +16,29 @@

package com.android.server.fingerprint;

import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import static android.Manifest.permission.USE_FINGERPRINT;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.EventLog;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import java.util.List;

/**
 * A class to keep track of the authentication state for a given client.
 */
@@ -53,6 +64,56 @@ public abstract class AuthenticationClient extends ClientMonitor {
        boolean result = false;
        boolean authenticated = fingerId != 0;

        // Ensure authentication only succeeds if the client activity is on top or is keyguard.
        boolean isBackgroundAuth = false;
        if (authenticated && !isKeyguard(getContext(), getOwnerString())) {
            final ActivityManager activityManager =
                    (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
            final IActivityManager activityManagerService = activityManager != null
                    ? activityManager.getService()
                    : null;
            if (activityManagerService == null) {
                Slog.e(TAG, "Unable to get activity manager service");
                isBackgroundAuth = true;
            } else {
                try {
                    final List<ActivityManager.RunningTaskInfo> tasks =
                            activityManagerService.getTasks(1, 0 /* flags */);
                    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");
        }

        IFingerprintServiceReceiver receiver = getReceiver();
        if (receiver != null) {
            try {
@@ -61,6 +122,14 @@ public abstract class AuthenticationClient extends ClientMonitor {
                if (!authenticated) {
                    receiver.onAuthenticationFailed(getHalDeviceId());
                } else {
                    // 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! Receiver notified");
                    }

                    if (DEBUG) {
                        Slog.v(TAG, "onAuthenticated(owner=" + getOwnerString()
                                + ", id=" + fingerId + ", gp=" + groupId + ")");
@@ -98,6 +167,14 @@ public abstract class AuthenticationClient extends ClientMonitor {
            }
            result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
        } else {
            // 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! Lockout reset");
            }

            if (receiver != null) {
                vibrateSuccess();
            }
@@ -107,6 +184,17 @@ public abstract class AuthenticationClient extends ClientMonitor {
        return result;
    }

    private static boolean isKeyguard(Context context, String clientPackage) {
        final boolean hasPermission = context.checkCallingOrSelfPermission(USE_FINGERPRINT)
                == 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);
    }

    /**
     * Start authentication
     */
Loading