Remove keysets from PackageKeySetData when KeySetManager removes them.
This fixes a bug where the KeySets in PackageKeySetData would get
out of sync with those in KeySetManager when repeatedly installed and
uninstalled.
Change-Id: I16cfe6d11f37d908ee5635ebcb6e784cebc252c0
diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/java/com/android/server/pm/KeySetManager.java
index afb7d4b..f154ab3 100644
--- a/services/java/com/android/server/pm/KeySetManager.java
+++ b/services/java/com/android/server/pm/KeySetManager.java
@@ -328,13 +328,16 @@
}
public void removeAppKeySetData(String packageName) {
- Log.e(TAG, "Removing application " + packageName);
synchronized (mLockObject) {
// Get the package's known keys and KeySets
- Set<Long> deletableKeySets = getKnownKeySetsByPackageName(packageName);
+ Set<Long> deletableKeySets = getKnownKeySetsByPackageNameLocked(packageName);
Set<Long> deletableKeys = new HashSet<Long>();
+ Set<Long> knownKeys = null;
for (Long ks : deletableKeySets) {
- deletableKeys.addAll(mKeySetMapping.get(ks));
+ knownKeys = mKeySetMapping.get(ks);
+ if (knownKeys != null) {
+ deletableKeys.addAll(knownKeys);
+ }
}
// Now remove the keys and KeySets known to any other package
@@ -342,11 +345,14 @@
if (pkgName.equals(packageName)) {
continue;
}
- Set<Long> knownKeySets = getKnownKeySetsByPackageName(pkgName);
+ Set<Long> knownKeySets = getKnownKeySetsByPackageNameLocked(pkgName);
deletableKeySets.removeAll(knownKeySets);
- Set<Long> knownKeys = new HashSet<Long>();
+ knownKeys = new HashSet<Long>();
for (Long ks : knownKeySets) {
- deletableKeys.removeAll(mKeySetMapping.get(ks));
+ knownKeys = mKeySetMapping.get(ks);
+ if (knownKeys != null) {
+ deletableKeys.removeAll(knownKeys);
+ }
}
}
@@ -359,10 +365,19 @@
for (Long keyId : deletableKeys) {
mPublicKeys.delete(keyId);
}
+
+ // Now remove them from the KeySets known to each package
+ for (String pkgName : mPackages.keySet()) {
+ PackageSetting p = mPackages.get(packageName);
+ for (Long ks : deletableKeySets) {
+ p.keySetData.removeSigningKeySet(ks);
+ p.keySetData.removeDefinedKeySet(ks);
+ }
+ }
}
}
- private Set<Long> getKnownKeySetsByPackageName(String packageName) {
+ private Set<Long> getKnownKeySetsByPackageNameLocked(String packageName) {
PackageSetting p = mPackages.get(packageName);
if (p == null) {
throw new NullPointerException("Unknown package");
@@ -371,10 +386,10 @@
throw new IllegalArgumentException("Package has no keySet data");
}
Set<Long> knownKeySets = new HashSet<Long>();
- for (Long ks : p.keySetData.getSigningKeySets()) {
+ for (long ks : p.keySetData.getSigningKeySets()) {
knownKeySets.add(ks);
}
- for (Long ks : p.keySetData.getDefinedKeySets()) {
+ for (long ks : p.keySetData.getDefinedKeySets()) {
knownKeySets.add(ks);
}
return knownKeySets;
diff --git a/services/java/com/android/server/pm/PackageKeySetData.java b/services/java/com/android/server/pm/PackageKeySetData.java
index 01ba5ba..cb60621 100644
--- a/services/java/com/android/server/pm/PackageKeySetData.java
+++ b/services/java/com/android/server/pm/PackageKeySetData.java
@@ -55,6 +55,20 @@
mSigningKeySets[end] = ks;
}
+ public void removeSigningKeySet(long ks) {
+ if (packageIsSignedBy(ks)) {
+ long[] keysets = new long[mSigningKeySets.length - 1];
+ int index = 0;
+ for (long signingKeySet : mSigningKeySets) {
+ if (signingKeySet != ks) {
+ keysets[index] = signingKeySet;
+ index += 1;
+ }
+ }
+ mSigningKeySets = keysets;
+ }
+ }
+
public void addDefinedKeySet(long ks, String alias) {
// deduplicate
for (long knownKeySet : mDefinedKeySets) {
@@ -68,6 +82,26 @@
mKeySetAliases.put(alias, ks);
}
+ public void removeDefinedKeySet(long ks) {
+ if (mKeySetAliases.containsValue(ks)) {
+ long[] keysets = new long[mDefinedKeySets.length - 1];
+ int index = 0;
+ for (long definedKeySet : mDefinedKeySets) {
+ if (definedKeySet != ks) {
+ keysets[index] = definedKeySet;
+ index += 1;
+ }
+ }
+ mDefinedKeySets = keysets;
+ for (String alias : mKeySetAliases.keySet()) {
+ if (mKeySetAliases.get(alias) == ks) {
+ mKeySetAliases.remove(alias);
+ break;
+ }
+ }
+ }
+ }
+
public boolean packageIsSignedBy(long ks) {
for (long signingKeySet : mSigningKeySets) {
if (ks == signingKeySet) {