Loading services/core/java/com/android/server/pm/PackageManagerService.java +84 −35 Original line number Original line Diff line number Diff line Loading @@ -1142,13 +1142,6 @@ public class PackageManagerService extends IPackageManager.Stub int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; boolean needUpdate = false; boolean needUpdate = false; if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "Updating IntentFilterVerificationInfo for package " + packageName + " verificationId:" + verificationId + " verified=" + verified); } // In a success case, we promote from undefined or ASK to ALWAYS. This // 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 // supports a flow where the app fails validation but then ships an updated // APK that passes, and therefore deserves to be in ALWAYS. // APK that passes, and therefore deserves to be in ALWAYS. Loading Loading @@ -18134,72 +18127,126 @@ public class PackageManagerService extends IPackageManager.Stub int count = 0; int count = 0; final String packageName = pkg.packageName; final String packageName = pkg.packageName; boolean handlesWebUris = false; ArraySet<String> domains = new ArraySet<>(); final boolean previouslyVerified; boolean hostSetExpanded = false; boolean needToRunVerify = false; synchronized (mPackages) { synchronized (mPackages) { // If this is a new install and we see that we've already run verification for this // 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. // package, we have nothing to do: it means the state was restored from backup. if (!replacing) { IntentFilterVerificationInfo ivi = IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(packageName); mSettings.getIntentFilterVerificationLPr(packageName); if (ivi != null) { previouslyVerified = (ivi != null); if (!replacing && previouslyVerified) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.i(TAG, "Package " + packageName + " already verified: status=" Slog.i(TAG, "Package " + packageName + " already verified: status=" + ivi.getStatusString()); + ivi.getStatusString()); } } return; 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. // If any filters need to be verified, then all need to be. In addition, we need to boolean needToVerify = false; // know whether an updating app has any web navigation intent filters, to re- // examine handling policy even if not re-verifying. final boolean needsVerification = needsNetworkVerificationLPr(packageName); for (PackageParser.Activity a : pkg.activities) { for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { for (ActivityIntentInfo filter : a.intents) { if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) { if (filter.handlesWebUris(true)) { handlesWebUris = true; } if (needsVerification && filter.needsVerification()) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, Slog.d(TAG, "autoVerify requested, processing all filters"); "Intent filter needs verification, so 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) returned true, so // we've already noted that. break; break; } } } } } } 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++; final int verificationId = mIntentFilterVerificationToken++; for (PackageParser.Activity a : pkg.activities) { for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { for (ActivityIntentInfo filter : a.intents) { // Run verification against hosts mentioned in any web-nav intent filter, // Run verification against hosts mentioned in any web-nav intent filter, // even if the filter matches non-web schemes as well // 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, if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Verification needed for IntentFilter:" + filter.toString()); "Verification needed for IntentFilter:" + filter.toString()); mIntentFilterVerifier.addOneIntentFilterVerification( mIntentFilterVerifier.addOneIntentFilterVerification( verifierUid, userId, verificationId, filter, packageName); verifierUid, userId, verificationId, filter, packageName); domains.addAll(filter.getHostsList()); count++; count++; } } } } } } } } if (DEBUG_DOMAIN_VERIFICATION) { Slog.i(TAG, " Update published hosts: " + domains.toString()); } // 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 (count > 0) { if (needToRunVerify && count > 0) { // app requested autoVerify and has at least one matching intent filter if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count + " IntentFilter verification" + (count > 1 ? "s" : "") + " IntentFilter verification" + (count > 1 ? "s" : "") + " for userId:" + userId); + " for userId:" + userId); mIntentFilterVerifier.startVerifications(userId); mIntentFilterVerifier.startVerifications(userId); } else { } else { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "No filters or not all autoVerify for " + packageName); Slog.d(TAG, "No web filters or no new host policy for " + packageName); } } } } } } @GuardedBy("mPackages") @GuardedBy("mPackages") private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) { private boolean needsNetworkVerificationLPr(String packageName) { final ComponentName cn = filter.activity.getComponentName(); final String packageName = cn.getPackageName(); IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( packageName); packageName); if (ivi == null) { if (ivi == null) { Loading Loading @@ -18945,7 +18992,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { final SparseBooleanArray changedUsers = new SparseBooleanArray(); final SparseBooleanArray changedUsers = new SparseBooleanArray(); synchronized (mPackages) { synchronized (mPackages) { clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true); clearDefaultBrowserIfNeeded(packageName); clearDefaultBrowserIfNeeded(packageName); mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); removedAppId = mSettings.removePackageLPw(packageName); removedAppId = mSettings.removePackageLPw(packageName); Loading Loading @@ -20450,13 +20497,14 @@ public class PackageManagerService extends IPackageManager.Stub final int packageCount = mPackages.size(); final int packageCount = mPackages.size(); for (int i = 0; i < packageCount; i++) { for (int i = 0; i < packageCount; i++) { PackageParser.Package pkg = mPackages.valueAt(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. */ /** This method takes a specific user id as well as UserHandle.USER_ALL. */ @GuardedBy("mPackages") @GuardedBy("mPackages") void clearIntentFilterVerificationsLPw(String packageName, int userId) { void clearIntentFilterVerificationsLPw(String packageName, int userId, boolean alsoResetStatus) { if (userId == UserHandle.USER_ALL) { if (userId == UserHandle.USER_ALL) { if (mSettings.removeIntentFilterVerificationLPw(packageName, if (mSettings.removeIntentFilterVerificationLPw(packageName, sUserManager.getUserIds())) { sUserManager.getUserIds())) { Loading @@ -20465,7 +20513,8 @@ public class PackageManagerService extends IPackageManager.Stub } } } } } else { } else { if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) { if (mSettings.removeIntentFilterVerificationLPw(packageName, userId, alsoResetStatus)) { scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageRestrictionsLocked(userId); } } } } services/core/java/com/android/server/pm/Settings.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -1243,7 +1243,8 @@ public final class Settings { return result; return result; } } boolean removeIntentFilterVerificationLPw(String packageName, int userId) { boolean removeIntentFilterVerificationLPw(String packageName, int userId, boolean alsoResetStatus) { PackageSetting ps = mPackages.get(packageName); PackageSetting ps = mPackages.get(packageName); if (ps == null) { if (ps == null) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Loading @@ -1251,14 +1252,17 @@ public final class Settings { } } return false; return false; } } if (alsoResetStatus) { ps.clearDomainVerificationStatusForUser(userId); ps.clearDomainVerificationStatusForUser(userId); } ps.setIntentFilterVerificationInfo(null); return true; return true; } } boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { boolean result = false; boolean result = false; for (int userId : userIds) { for (int userId : userIds) { result |= removeIntentFilterVerificationLPw(packageName, userId); result |= removeIntentFilterVerificationLPw(packageName, userId, true); } } return result; return result; } } Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +84 −35 Original line number Original line Diff line number Diff line Loading @@ -1142,13 +1142,6 @@ public class PackageManagerService extends IPackageManager.Stub int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; boolean needUpdate = false; boolean needUpdate = false; if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "Updating IntentFilterVerificationInfo for package " + packageName + " verificationId:" + verificationId + " verified=" + verified); } // In a success case, we promote from undefined or ASK to ALWAYS. This // 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 // supports a flow where the app fails validation but then ships an updated // APK that passes, and therefore deserves to be in ALWAYS. // APK that passes, and therefore deserves to be in ALWAYS. Loading Loading @@ -18134,72 +18127,126 @@ public class PackageManagerService extends IPackageManager.Stub int count = 0; int count = 0; final String packageName = pkg.packageName; final String packageName = pkg.packageName; boolean handlesWebUris = false; ArraySet<String> domains = new ArraySet<>(); final boolean previouslyVerified; boolean hostSetExpanded = false; boolean needToRunVerify = false; synchronized (mPackages) { synchronized (mPackages) { // If this is a new install and we see that we've already run verification for this // 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. // package, we have nothing to do: it means the state was restored from backup. if (!replacing) { IntentFilterVerificationInfo ivi = IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(packageName); mSettings.getIntentFilterVerificationLPr(packageName); if (ivi != null) { previouslyVerified = (ivi != null); if (!replacing && previouslyVerified) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.i(TAG, "Package " + packageName + " already verified: status=" Slog.i(TAG, "Package " + packageName + " already verified: status=" + ivi.getStatusString()); + ivi.getStatusString()); } } return; 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. // If any filters need to be verified, then all need to be. In addition, we need to boolean needToVerify = false; // know whether an updating app has any web navigation intent filters, to re- // examine handling policy even if not re-verifying. final boolean needsVerification = needsNetworkVerificationLPr(packageName); for (PackageParser.Activity a : pkg.activities) { for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { for (ActivityIntentInfo filter : a.intents) { if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) { if (filter.handlesWebUris(true)) { handlesWebUris = true; } if (needsVerification && filter.needsVerification()) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, Slog.d(TAG, "autoVerify requested, processing all filters"); "Intent filter needs verification, so 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) returned true, so // we've already noted that. break; break; } } } } } } 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++; final int verificationId = mIntentFilterVerificationToken++; for (PackageParser.Activity a : pkg.activities) { for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { for (ActivityIntentInfo filter : a.intents) { // Run verification against hosts mentioned in any web-nav intent filter, // Run verification against hosts mentioned in any web-nav intent filter, // even if the filter matches non-web schemes as well // 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, if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Verification needed for IntentFilter:" + filter.toString()); "Verification needed for IntentFilter:" + filter.toString()); mIntentFilterVerifier.addOneIntentFilterVerification( mIntentFilterVerifier.addOneIntentFilterVerification( verifierUid, userId, verificationId, filter, packageName); verifierUid, userId, verificationId, filter, packageName); domains.addAll(filter.getHostsList()); count++; count++; } } } } } } } } if (DEBUG_DOMAIN_VERIFICATION) { Slog.i(TAG, " Update published hosts: " + domains.toString()); } // 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 (count > 0) { if (needToRunVerify && count > 0) { // app requested autoVerify and has at least one matching intent filter if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count + " IntentFilter verification" + (count > 1 ? "s" : "") + " IntentFilter verification" + (count > 1 ? "s" : "") + " for userId:" + userId); + " for userId:" + userId); mIntentFilterVerifier.startVerifications(userId); mIntentFilterVerifier.startVerifications(userId); } else { } else { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "No filters or not all autoVerify for " + packageName); Slog.d(TAG, "No web filters or no new host policy for " + packageName); } } } } } } @GuardedBy("mPackages") @GuardedBy("mPackages") private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) { private boolean needsNetworkVerificationLPr(String packageName) { final ComponentName cn = filter.activity.getComponentName(); final String packageName = cn.getPackageName(); IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( packageName); packageName); if (ivi == null) { if (ivi == null) { Loading Loading @@ -18945,7 +18992,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { final SparseBooleanArray changedUsers = new SparseBooleanArray(); final SparseBooleanArray changedUsers = new SparseBooleanArray(); synchronized (mPackages) { synchronized (mPackages) { clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true); clearDefaultBrowserIfNeeded(packageName); clearDefaultBrowserIfNeeded(packageName); mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); removedAppId = mSettings.removePackageLPw(packageName); removedAppId = mSettings.removePackageLPw(packageName); Loading Loading @@ -20450,13 +20497,14 @@ public class PackageManagerService extends IPackageManager.Stub final int packageCount = mPackages.size(); final int packageCount = mPackages.size(); for (int i = 0; i < packageCount; i++) { for (int i = 0; i < packageCount; i++) { PackageParser.Package pkg = mPackages.valueAt(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. */ /** This method takes a specific user id as well as UserHandle.USER_ALL. */ @GuardedBy("mPackages") @GuardedBy("mPackages") void clearIntentFilterVerificationsLPw(String packageName, int userId) { void clearIntentFilterVerificationsLPw(String packageName, int userId, boolean alsoResetStatus) { if (userId == UserHandle.USER_ALL) { if (userId == UserHandle.USER_ALL) { if (mSettings.removeIntentFilterVerificationLPw(packageName, if (mSettings.removeIntentFilterVerificationLPw(packageName, sUserManager.getUserIds())) { sUserManager.getUserIds())) { Loading @@ -20465,7 +20513,8 @@ public class PackageManagerService extends IPackageManager.Stub } } } } } else { } else { if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) { if (mSettings.removeIntentFilterVerificationLPw(packageName, userId, alsoResetStatus)) { scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageRestrictionsLocked(userId); } } } }
services/core/java/com/android/server/pm/Settings.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -1243,7 +1243,8 @@ public final class Settings { return result; return result; } } boolean removeIntentFilterVerificationLPw(String packageName, int userId) { boolean removeIntentFilterVerificationLPw(String packageName, int userId, boolean alsoResetStatus) { PackageSetting ps = mPackages.get(packageName); PackageSetting ps = mPackages.get(packageName); if (ps == null) { if (ps == null) { if (DEBUG_DOMAIN_VERIFICATION) { if (DEBUG_DOMAIN_VERIFICATION) { Loading @@ -1251,14 +1252,17 @@ public final class Settings { } } return false; return false; } } if (alsoResetStatus) { ps.clearDomainVerificationStatusForUser(userId); ps.clearDomainVerificationStatusForUser(userId); } ps.setIntentFilterVerificationInfo(null); return true; return true; } } boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { boolean result = false; boolean result = false; for (int userId : userIds) { for (int userId : userIds) { result |= removeIntentFilterVerificationLPw(packageName, userId); result |= removeIntentFilterVerificationLPw(packageName, userId, true); } } return result; return result; } } Loading