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

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

Merge tag 'android-8.1.0_r80' into staging/lineage-15.1_merge-android-8.1.0_r80

Android 8.1.0 release 80

* tag 'android-8.1.0_r80':
  Only autoVerify at install for new hosts
  DO NOT MERGE: Verify INSTALL_PACKAGES permissions when adding installer package
  Revert "Revoke 'always' web handler status when not autoverifying"

Change-Id: I70d6a0efd71713c0ca2fb1aeee3d60afb48e5c42
parents c5446a4a 2b71d2b7
Loading
Loading
Loading
Loading
+154 −76
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.ResourcesManager;
import android.app.admin.IDevicePolicyManager;
@@ -1105,9 +1106,13 @@ public class PackageManagerService extends IPackageManager.Stub
            verificationIntent.setComponent(mIntentFilterVerifierComponent);
            verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            final long whitelistTimeout = getVerificationTimeout();
            final BroadcastOptions options = BroadcastOptions.makeBasic();
            options.setTemporaryAppWhitelistDuration(whitelistTimeout);
            DeviceIdleController.LocalService idleController = getDeviceIdleController();
            idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                    mIntentFilterVerifierComponent.getPackageName(), getVerificationTimeout(),
                    mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
                    UserHandle.USER_SYSTEM, true, "intent filter verifier");
            mContext.sendBroadcastAsUser(verificationIntent, UserHandle.SYSTEM);
@@ -1148,9 +1153,6 @@ public class PackageManagerService extends IPackageManager.Stub
                        + verificationId + " packageName:" + packageName);
                return;
            }
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                    "Updating IntentFilterVerificationInfo for package " + packageName
                            +" verificationId:" + verificationId);
            synchronized (mPackages) {
                if (verified) {
@@ -1168,19 +1170,51 @@ public class PackageManagerService extends IPackageManager.Stub
                    int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
                    boolean needUpdate = false;
                    // We cannot override the STATUS_ALWAYS / STATUS_NEVER states if they have
                    // already been set by the User thru the Disambiguation dialog
                    // In a success case, we promote from undefined or ASK to ALWAYS.  This
                    // supports a flow where the app fails validation but then ships an updated
                    // APK that passes, and therefore deserves to be in ALWAYS.
                    //
                    // If validation failed, the undefined state winds up in the basic ASK behavior,
                    // but apps that previously passed and became ALWAYS are *demoted* out of
                    // that state, since they would not deserve the ALWAYS behavior in case of a
                    // clean install.
                     switch (userStatus) {
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
                             if (!verified) {
                                 // Don't demote if sysconfig says 'always'
                                 SystemConfig systemConfig = SystemConfig.getInstance();
                                 ArraySet<String> packages = systemConfig.getLinkedApps();
                                 if (!packages.contains(packageName)) {
                                     // updatedStatus is already UNDEFINED
                                     needUpdate = true;
                                     if (DEBUG_DOMAIN_VERIFICATION) {
                                         Slog.d(TAG, "Formerly validated but now failing; demoting");
                                     }
                                 } else {
                                     if (DEBUG_DOMAIN_VERIFICATION) {
                                         Slog.d(TAG, "Updating bundled package " + packageName
                                                 + " failed autoVerify, but sysconfig supersedes");
                                     }
                                     // leave needUpdate == false here intentionally
                                 }
                             }
                             break;
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
                             // Stay in 'undefined' on verification failure
                             if (verified) {
                                 updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
                            } else {
                                updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
                             }
                             needUpdate = true;
                             if (DEBUG_DOMAIN_VERIFICATION) {
                                 Slog.d(TAG, "Applying update; old=" + userStatus
                                         + " new=" + updatedStatus);
                             }
                             break;
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
                             // Keep in 'ask' on failure
                             if (verified) {
                                 updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
                                 needUpdate = true;
@@ -1196,6 +1230,8 @@ public class PackageManagerService extends IPackageManager.Stub
                                packageName, updatedStatus, userId);
                        scheduleWritePackageRestrictionsLocked(userId);
                    }
                } else {
                    Slog.i(TAG, "autoVerify ignored when installing for all users");
                }
             }
        }
@@ -15953,20 +15989,26 @@ public class PackageManagerService extends IPackageManager.Stub
            // Verify: if target already has an installer package, it must
            // be signed with the same cert as the caller.
            if (targetPackageSetting.installerPackageName != null) {
                PackageSetting setting = mSettings.mPackages.get(
                        targetPackageSetting.installerPackageName);
                // If the currently set package isn't valid, then it's always
                // okay to change it.
                if (setting != null) {
            String targetInstallerPackageName =
                    targetPackageSetting.installerPackageName;
            PackageSetting targetInstallerPkgSetting = targetInstallerPackageName == null ? null :
                    mSettings.mPackages.get(targetInstallerPackageName);
            if (targetInstallerPkgSetting != null) {
                if (compareSignatures(callerSignature,
                            setting.signatures.mSignatures)
                        targetInstallerPkgSetting.signatures.mSignatures)
                        != PackageManager.SIGNATURE_MATCH) {
                    throw new SecurityException(
                            "Caller does not have same cert as old installer package "
                                + targetPackageSetting.installerPackageName);
                    }
                                    + targetInstallerPackageName);
                }
            } else if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
                    != PackageManager.PERMISSION_GRANTED) {
                // This is probably an attempt to exploit vulnerability b/150857253 of taking
                // privileged installer permissions when the installer has been uninstalled or
                // was never set.
                EventLog.writeEvent(0x534e4554, "150857253", callingUid, "");
                return;
            }
            // Okay!
@@ -19105,16 +19147,18 @@ public class PackageManagerService extends IPackageManager.Stub
        int count = 0;
        final String packageName = pkg.packageName;
        boolean handlesWebUris = false;
        final boolean alreadyVerified;
        ArraySet<String> domains = new ArraySet<>();
        final boolean previouslyVerified;
        boolean hostSetExpanded = false;
        boolean needToRunVerify = false;
        synchronized (mPackages) {
            // If this is a new install and we see that we've already run verification for this
            // package, we have nothing to do: it means the state was restored from backup.
            final IntentFilterVerificationInfo ivi =
            IntentFilterVerificationInfo ivi =
                    mSettings.getIntentFilterVerificationLPr(packageName);
            alreadyVerified = (ivi != null);
            if (!replacing && alreadyVerified) {
            previouslyVerified = (ivi != null);
            if (!replacing && previouslyVerified) {
                if (DEBUG_DOMAIN_VERIFICATION) {
                    Slog.i(TAG, "Package " + packageName + " already verified: status="
                            + ivi.getStatusString());
@@ -19122,75 +19166,106 @@ public class PackageManagerService extends IPackageManager.Stub
                return;
            }
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "    Previous verified hosts: "
                        + (ivi == null ? "[none]" : ivi.getDomainsString()));
            }
            // If any filters need to be verified, then all need to be.  In addition, we need to
            // know whether an updating app has any web navigation intent filters, to re-
            // examine handling policy even if not re-verifying.
            boolean needToVerify = false;
            final boolean needsVerification = needsNetworkVerificationLPr(packageName);
            for (PackageParser.Activity a : pkg.activities) {
                for (ActivityIntentInfo filter : a.intents) {
                    if (filter.handlesWebUris(true)) {
                        handlesWebUris = true;
                    }
                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                    if (needsVerification && filter.needsVerification()) {
                        if (DEBUG_DOMAIN_VERIFICATION) {
                            Slog.d(TAG, "Intent filter needs verification, so processing all filters");
                            Slog.d(TAG, "autoVerify requested, processing all filters");
                        }
                        needToVerify = true;
                        needToRunVerify = true;
                        // It's safe to break out here because filter.needsVerification()
                        // can only be true if filter.handlesWebUris(true) returns true, so
                        // can only be true if filter.handlesWebUris(true) returned true, so
                        // we've already noted that.
                        break;
                    }
                }
            }
            // Note whether this app publishes any web navigation handling support at all,
            // and whether there are any web-nav filters that fit the profile for running
            // a verification pass now.
            if (needToVerify) {
            // Compare the new set of recognized hosts if the app is either requesting
            // autoVerify or has previously used autoVerify but no longer does.
            if (needToRunVerify || previouslyVerified) {
                final int verificationId = mIntentFilterVerificationToken++;
                for (PackageParser.Activity a : pkg.activities) {
                    for (ActivityIntentInfo filter : a.intents) {
                        // Run verification against hosts mentioned in any web-nav intent filter,
                        // even if the filter matches non-web schemes as well
                        if (filter.handlesWebUris(false) && needsNetworkVerificationLPr(filter)) {
                        if (filter.handlesWebUris(false /*onlyWebSchemes*/)) {
                            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                    "Verification needed for IntentFilter:" + filter.toString());
                            mIntentFilterVerifier.addOneIntentFilterVerification(
                                    verifierUid, userId, verificationId, filter, packageName);
                            domains.addAll(filter.getHostsList());
                            count++;
                        }
                    }
                }
            }
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "    Update published hosts: " + domains.toString());
            }
        if (count > 0) {
            // count > 0 means that we're running a full verification pass
            // If we've previously verified this same host set (or a subset), we can trust that
            // a current ALWAYS policy is still applicable.  If this is the case, we're done.
            // (If we aren't in ALWAYS, we want to reverify to allow for apps that had failing
            // hosts in their intent filters, then pushed a new apk that removed them and now
            // passes.)
            //
            // Cases:
            //   + still autoVerify (needToRunVerify):
            //      - preserve current state if all of: unexpanded, in always
            //      - otherwise rerun as usual (fall through)
            //   + no longer autoVerify (alreadyVerified && !needToRunVerify)
            //      - wipe verification history always
            //      - preserve current state if all of: unexpanded, in always
            hostSetExpanded = !previouslyVerified
                    || (ivi != null && !ivi.getDomains().containsAll(domains));
            final int currentPolicy =
                    mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
            final boolean keepCurState = !hostSetExpanded
                    && currentPolicy == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
            if (needToRunVerify && keepCurState) {
                if (DEBUG_DOMAIN_VERIFICATION) {
                    Slog.i(TAG, "Host set not expanding + ALWAYS -> no need to reverify");
                }
                ivi.setDomains(domains);
                scheduleWriteSettingsLocked();
                return;
            } else if (previouslyVerified && !needToRunVerify) {
                // Prior autoVerify state but not requesting it now.  Clear autoVerify history,
                // and preserve the always policy iff the host set is not expanding.
                clearIntentFilterVerificationsLPw(packageName, userId, !keepCurState);
                return;
            }
        }
        if (needToRunVerify && count > 0) {
            // app requested autoVerify and has at least one matching intent filter
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                    + " IntentFilter verification" + (count > 1 ? "s" : "")
                    +  " for userId:" + userId);
            mIntentFilterVerifier.startVerifications(userId);
        } else if (alreadyVerified && handlesWebUris) {
            // App used autoVerify in the past, no longer does, but still handles web
            // navigation starts.
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
            }
            synchronized (mPackages) {
                clearIntentFilterVerificationsLPw(packageName, userId);
            }
        } else {
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
                Slog.d(TAG, "No web filters or no new host policy for " + packageName);
            }
        }
     }
    private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) {
        final ComponentName cn  = filter.activity.getComponentName();
        final String packageName = cn.getPackageName();
    private boolean needsNetworkVerificationLPr(String packageName) {
        IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(
                packageName);
        if (ivi == null) {
@@ -19199,6 +19274,7 @@ public class PackageManagerService extends IPackageManager.Stub
        int status = ivi.getStatus();
        switch (status) {
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
                return true;
@@ -19908,7 +19984,7 @@ public class PackageManagerService extends IPackageManager.Stub
            boolean installedStateChanged = false;
            if (deletedPs != null) {
                if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
                    clearDefaultBrowserIfNeeded(packageName);
                    mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
                    removedAppId = mSettings.removePackageLPw(packageName);
@@ -21214,12 +21290,13 @@ public class PackageManagerService extends IPackageManager.Stub
        final int packageCount = mPackages.size();
        for (int i = 0; i < packageCount; i++) {
            PackageParser.Package pkg = mPackages.valueAt(i);
            clearIntentFilterVerificationsLPw(pkg.packageName, userId);
            clearIntentFilterVerificationsLPw(pkg.packageName, userId, true);
        }
    }
    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
    void clearIntentFilterVerificationsLPw(String packageName, int userId) {
    void clearIntentFilterVerificationsLPw(String packageName, int userId,
            boolean alsoResetStatus) {
        if (userId == UserHandle.USER_ALL) {
            if (mSettings.removeIntentFilterVerificationLPw(packageName,
                    sUserManager.getUserIds())) {
@@ -21228,7 +21305,8 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
        } else {
            if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) {
            if (mSettings.removeIntentFilterVerificationLPw(packageName, userId,
                    alsoResetStatus)) {
                scheduleWritePackageRestrictionsLocked(userId);
            }
        }
+6 −3
Original line number Diff line number Diff line
@@ -1371,7 +1371,8 @@ final class Settings {
        return result;
    }

    boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
    boolean removeIntentFilterVerificationLPw(String packageName, int userId,
            boolean alsoResetStatus) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            if (DEBUG_DOMAIN_VERIFICATION) {
@@ -1379,7 +1380,9 @@ final class Settings {
            }
            return false;
        }
        if (alsoResetStatus) {
            ps.clearDomainVerificationStatusForUser(userId);
        }
        ps.setIntentFilterVerificationInfo(null);
        return true;
    }
@@ -1387,7 +1390,7 @@ final class Settings {
    boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
        boolean result = false;
        for (int userId : userIds) {
            result |= removeIntentFilterVerificationLPw(packageName, userId);
            result |= removeIntentFilterVerificationLPw(packageName, userId, true);
        }
        return result;
    }