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

Commit d79fdf1c authored by dcashman's avatar dcashman
Browse files

Remove KeySetManagerService lock.

The KeySetManagerService is a part of the PackageManagerService, which is
responsible for maintaining the association between packages, keysets and
public keys.  This information is a critical component of the
PackageManagerService data, and should require the holding of the
PackageManagerService's lock.  Remove the existing KeySetManagerService lock
and require the mPackages lock to be held instead.

Bug: 6967056
Change-Id: I803f8388e42469d30562b40212cf497320851268
parent 5aa5f494
Loading
Loading
Loading
Loading
+203 −243
Original line number Diff line number Diff line
@@ -52,13 +52,11 @@ public class KeySetManagerService {
    /** Sentinel value returned when public key is not found. */
    protected static final long PUBLIC_KEY_NOT_FOUND = -1;

    private final Object mLockObject = new Object();

    private final LongSparseArray<KeySet> mKeySets;

    private final LongSparseArray<PublicKey> mPublicKeys;

    protected final LongSparseArray<Set<Long>> mKeySetMapping;
    protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;

    private final Map<String, PackageSetting> mPackages;

@@ -69,7 +67,7 @@ public class KeySetManagerService {
    public KeySetManagerService(Map<String, PackageSetting> packages) {
        mKeySets = new LongSparseArray<KeySet>();
        mPublicKeys = new LongSparseArray<PublicKey>();
        mKeySetMapping = new LongSparseArray<Set<Long>>();
        mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
        mPackages = packages;
    }

@@ -84,8 +82,7 @@ public class KeySetManagerService {
     *
     * Note that this can return true for multiple KeySets.
     */
    public boolean packageIsSignedBy(String packageName, KeySet ks) {
        synchronized (mLockObject) {
    public boolean packageIsSignedByLPr(String packageName, KeySet ks) {
        PackageSetting pkg = mPackages.get(packageName);
        if (pkg == null) {
            throw new NullPointerException("Invalid package name");
@@ -93,67 +90,61 @@ public class KeySetManagerService {
        if (pkg.keySetData == null) {
            throw new NullPointerException("Package has no KeySet data");
        }
            long id = getIdByKeySetLocked(ks);
        long id = getIdByKeySetLPr(ks);
        return pkg.keySetData.packageIsSignedBy(id);
    }
    }

    /**
     * This informs the system that the given package has defined a KeySet
     * in its manifest that a) contains the given keys and b) is named
     * alias by that package.
     */
    public void addDefinedKeySetToPackage(String packageName,
    public void addDefinedKeySetToPackageLPw(String packageName,
            Set<PublicKey> keys, String alias) {
        if ((packageName == null) || (keys == null) || (alias == null)) {
            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
            return;
        }
        synchronized (mLockObject) {
        PackageSetting pkg = mPackages.get(packageName);
        if (pkg == null) {
            throw new NullPointerException("Unknown package");
        }
        // Add to KeySets, then to package
            KeySet ks = addKeySetLocked(keys);
            long id = getIdByKeySetLocked(ks);
        KeySet ks = addKeySetLPw(keys);
        long id = getIdByKeySetLPr(ks);
        pkg.keySetData.addDefinedKeySet(id, alias);
    }
    }

    /**
     * This informs the system that the given package has defined a KeySet
     * alias in its manifest to be an upgradeKeySet.  This must be called
     * after all of the defined KeySets have been added.
     */
    public void addUpgradeKeySetToPackage(String packageName, String alias) {
    public void addUpgradeKeySetToPackageLPw(String packageName, String alias) {
        if ((packageName == null) || (alias == null)) {
            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
            return;
        }
        synchronized (mLockObject) {
        PackageSetting pkg = mPackages.get(packageName);
        if (pkg == null) {
            throw new NullPointerException("Unknown package");
        }
        pkg.keySetData.addUpgradeKeySet(alias);
    }
    }

    /**
     * Similar to the above, this informs the system that the given package
     * was signed by the provided KeySet.
     */
    public void addSigningKeySetToPackage(String packageName,
    public void addSigningKeySetToPackageLPw(String packageName,
            Set<PublicKey> signingKeys) {
        if ((packageName == null) || (signingKeys == null)) {
            Slog.w(TAG, "Got null argument for a signing keyset, ignoring!");
            return;
        }
        synchronized (mLockObject) {
        // add the signing KeySet
            KeySet ks = addKeySetLocked(signingKeys);
            long id = getIdByKeySetLocked(ks);
        KeySet ks = addKeySetLPw(signingKeys);
        long id = getIdByKeySetLPr(ks);
        Set<Long> publicKeyIds = mKeySetMapping.get(id);
        if (publicKeyIds == null) {
            throw new NullPointerException("Got invalid KeySet id");
@@ -175,19 +166,12 @@ public class KeySetManagerService {
            }
        }
    }
    }

    /**
     * Fetches the stable identifier associated with the given KeySet. Returns
     * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
     */
    public long getIdByKeySet(KeySet ks) {
        synchronized (mLockObject) {
            return getIdByKeySetLocked(ks);
        }
    }

    private long getIdByKeySetLocked(KeySet ks) {
    private long getIdByKeySetLPr(KeySet ks) {
        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
            KeySet value = mKeySets.valueAt(keySetIndex);
            if (ks.equals(value)) {
@@ -203,11 +187,9 @@ public class KeySetManagerService {
     * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
     * identify a {@link KeySet}.
     */
    public KeySet getKeySetById(long id) {
        synchronized (mLockObject) {
    public KeySet getKeySetByIdLPr(long id) {
        return mKeySets.get(id);
    }
    }

    /**
     * Fetches the {@link KeySet} that a given package refers to by the provided alias.
@@ -215,8 +197,7 @@ public class KeySetManagerService {
     * @throws IllegalArgumentException if the package has no keyset data.
     * @throws NullPointerException if the package is unknown.
     */
    public KeySet getKeySetByAliasAndPackageName(String packageName, String alias) {
        synchronized (mLockObject) {
    public KeySet getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
        PackageSetting p = mPackages.get(packageName);
        if (p == null) {
            throw new NullPointerException("Unknown package");
@@ -227,7 +208,6 @@ public class KeySetManagerService {
        long keySetId = p.keySetData.getAliases().get(alias);
        return mKeySets.get(keySetId);
    }
    }

    /**
     * Fetches the {@link PublicKey public keys} which belong to the specified
@@ -236,8 +216,7 @@ public class KeySetManagerService {
     * Returns {@code null} if the identifier doesn't
     * identify a {@link KeySet}.
     */
    public ArraySet<PublicKey> getPublicKeysFromKeySet(long id) {
        synchronized (mLockObject) {
    public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) {
        if(mKeySetMapping.get(id) == null) {
            return null;
        }
@@ -247,7 +226,6 @@ public class KeySetManagerService {
        }
        return mPubKeys;
    }
    }

    /**
     * Fetches all the known {@link KeySet KeySets} that signed the given
@@ -256,8 +234,7 @@ public class KeySetManagerService {
     * @throws IllegalArgumentException if the package has no keyset data.
     * @throws NullPointerException if the package is unknown.
     */
    public Set<KeySet> getSigningKeySetsByPackageName(String packageName) {
        synchronized (mLockObject) {
    public Set<KeySet> getSigningKeySetsByPackageNameLPr(String packageName) {
        Set<KeySet> signingKeySets = new ArraySet<KeySet>();
        PackageSetting p = mPackages.get(packageName);
        if (p == null) {
@@ -271,7 +248,6 @@ public class KeySetManagerService {
        }
        return signingKeySets;
    }
    }

    /**
     * Fetches all the known {@link KeySet KeySets} that may upgrade the given
@@ -280,8 +256,7 @@ public class KeySetManagerService {
     * @throws IllegalArgumentException if the package has no keyset data.
     * @throws NullPointerException if the package is unknown.
     */
    public ArraySet<KeySet> getUpgradeKeySetsByPackageName(String packageName) {
        synchronized (mLockObject) {
    public ArraySet<KeySet> getUpgradeKeySetsByPackageNameLPr(String packageName) {
        ArraySet<KeySet> upgradeKeySets = new ArraySet<KeySet>();
        PackageSetting p = mPackages.get(packageName);
        if (p == null) {
@@ -297,7 +272,6 @@ public class KeySetManagerService {
        }
        return upgradeKeySets;
    }
    }

    /**
     * Creates a new KeySet corresponding to the given keys.
@@ -313,19 +287,19 @@ public class KeySetManagerService {
     *
     * Throws if the provided set is {@code null}.
     */
    private KeySet addKeySetLocked(Set<PublicKey> keys) {
    private KeySet addKeySetLPw(Set<PublicKey> keys) {
        if (keys == null) {
            throw new NullPointerException("Provided keys cannot be null");
        }
        // add each of the keys in the provided set
        Set<Long> addedKeyIds = new ArraySet<Long>(keys.size());
        ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
        for (PublicKey k : keys) {
            long id = addPublicKeyLocked(k);
            long id = addPublicKeyLPw(k);
            addedKeyIds.add(id);
        }

        // check to see if the resulting keyset is new
        long existingKeySetId = getIdFromKeyIdsLocked(addedKeyIds);
        long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
        if (existingKeySetId != KEYSET_NOT_FOUND) {
            return mKeySets.get(existingKeySetId);
        }
@@ -333,7 +307,7 @@ public class KeySetManagerService {
        // create the KeySet object
        KeySet ks = new KeySet(new Binder());
        // get the first unoccupied slot in mKeySets
        long id = getFreeKeySetIDLocked();
        long id = getFreeKeySetIDLPw();
        // add the KeySet object to it
        mKeySets.put(id, ks);
        // add the stable key ids to the mapping
@@ -358,14 +332,14 @@ public class KeySetManagerService {
    /**
     * Adds the given PublicKey to the system, deduping as it goes.
     */
    private long addPublicKeyLocked(PublicKey key) {
    private long addPublicKeyLPw(PublicKey key) {
        // check if the public key is new
        long existingKeyId = getIdForPublicKeyLocked(key);
        long existingKeyId = getIdForPublicKeyLPr(key);
        if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
            return existingKeyId;
        }
        // if it's new find the first unoccupied slot in the public keys
        long id = getFreePublicKeyIdLocked();
        long id = getFreePublicKeyIdLPw();
        // add the public key to it
        mPublicKeys.put(id, key);
        // return the stable identifier
@@ -377,7 +351,7 @@ public class KeySetManagerService {
     *
     * Returns KEYSET_NOT_FOUND if there isn't one.
     */
    private long getIdFromKeyIdsLocked(Set<Long> publicKeyIds) {
    private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) {
        for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
            Set<Long> value = mKeySetMapping.valueAt(keyMapIndex);
            if (value.equals(publicKeyIds)) {
@@ -390,16 +364,7 @@ public class KeySetManagerService {
    /**
     * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
     */
    protected long getIdForPublicKey(PublicKey k) {
        synchronized (mLockObject) {
            return getIdForPublicKeyLocked(k);
        }
    }

    /**
     * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
     */
    private long getIdForPublicKeyLocked(PublicKey k) {
    private long getIdForPublicKeyLPr(PublicKey k) {
        String encodedPublicKey = new String(k.getEncoded());
        for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
            PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
@@ -414,7 +379,7 @@ public class KeySetManagerService {
    /**
     * Gets an unused stable identifier for a KeySet.
     */
    private long getFreeKeySetIDLocked() {
    private long getFreeKeySetIDLPw() {
        lastIssuedKeySetId += 1;
        return lastIssuedKeySetId;
    }
@@ -422,17 +387,16 @@ public class KeySetManagerService {
    /**
     * Same as above, but for public keys.
     */
    private long getFreePublicKeyIdLocked() {
    private long getFreePublicKeyIdLPw() {
        lastIssuedKeyId += 1;
        return lastIssuedKeyId;
    }

    public void removeAppKeySetData(String packageName) {
        synchronized (mLockObject) {
    public void removeAppKeySetDataLPw(String packageName) {
        // Get the package's known keys and KeySets
            Set<Long> deletableKeySets = getOriginalKeySetsByPackageNameLocked(packageName);
            Set<Long> deletableKeys = new ArraySet<Long>();
            Set<Long> knownKeys = null;
        ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName);
        ArraySet<Long> deletableKeys = new ArraySet<Long>();
        ArraySet<Long> knownKeys = null;
        for (Long ks : deletableKeySets) {
            knownKeys = mKeySetMapping.get(ks);
            if (knownKeys != null) {
@@ -445,7 +409,7 @@ public class KeySetManagerService {
            if (pkgName.equals(packageName)) {
                continue;
            }
                Set<Long> knownKeySets = getOriginalKeySetsByPackageNameLocked(pkgName);
            ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName);
            deletableKeySets.removeAll(knownKeySets);
            knownKeys = new ArraySet<Long>();
            for (Long ks : knownKeySets) {
@@ -473,21 +437,19 @@ public class KeySetManagerService {
                p.keySetData.removeSigningKeySet(ks);
            }
        }

        // Finally, remove all KeySets from the original package
        PackageSetting p = mPackages.get(packageName);
            clearPackageKeySetDataLocked(p);
        }
        clearPackageKeySetDataLPw(p);
    }

    private void clearPackageKeySetDataLocked(PackageSetting p) {
    private void clearPackageKeySetDataLPw(PackageSetting p) {
        p.keySetData.removeAllSigningKeySets();
        p.keySetData.removeAllUpgradeKeySets();
        p.keySetData.removeAllDefinedKeySets();
        return;
    }

    private Set<Long> getOriginalKeySetsByPackageNameLocked(String packageName) {
    private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) {
        PackageSetting p = mPackages.get(packageName);
        if (p == null) {
            throw new NullPointerException("Unknown package");
@@ -495,7 +457,7 @@ public class KeySetManagerService {
        if (p.keySetData == null) {
            throw new IllegalArgumentException("Package has no keySet data");
        }
        Set<Long> knownKeySets = new ArraySet<Long>();
        ArraySet<Long> knownKeySets = new ArraySet<Long>();
        knownKeySets.add(p.keySetData.getProperSigningKeySet());
        if (p.keySetData.isUsingDefinedKeySets()) {
            for (long ks : p.keySetData.getDefinedKeySets()) {
@@ -509,9 +471,8 @@ public class KeySetManagerService {
        return new String(Base64.encode(k.getEncoded(), 0));
    }

    public void dump(PrintWriter pw, String packageName,
    public void dumpLPr(PrintWriter pw, String packageName,
                        PackageManagerService.DumpState dumpState) {
        synchronized (mLockObject) {
        boolean printedHeader = false;
        for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
            String keySetPackage = e.getKey();
@@ -588,7 +549,6 @@ public class KeySetManagerService {
            }
        }
    }
    }

    void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException {
        serializer.startTag(null, "keyset-settings");
@@ -651,7 +611,7 @@ public class KeySetManagerService {
            // The KeySet information read previously from packages.xml is invalid.
            // Destroy it all.
            for (PackageSetting p : mPackages.values()) {
                clearPackageKeySetDataLocked(p);
                clearPackageKeySetDataLPw(p);
            }
            return;
        }
+14 −15
Original line number Diff line number Diff line
@@ -2815,7 +2815,9 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Migrate the old signatures to the new scheme.
            existingSigs.assignSignatures(scannedPkg.mSignatures);
            // The new KeySets will be re-added later in the scanning process.
            mSettings.mKeySetManagerService.removeAppKeySetData(scannedPkg.packageName);
            synchronized (mPackages) {
                mSettings.mKeySetManagerService.removeAppKeySetDataLPw(scannedPkg.packageName);
            }
            return PackageManager.SIGNATURE_MATCH;
        }
        return PackageManager.SIGNATURE_NO_MATCH;
@@ -4145,7 +4147,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                // if the package appears to be unchanged.
                pkg.mSignatures = ps.signatures.mSignatures;
                KeySetManagerService ksms = mSettings.mKeySetManagerService;
                pkg.mSigningKeys = ksms.getPublicKeysFromKeySet(mSigningKeySetId);
                synchronized (mPackages) {
                    pkg.mSigningKeys = ksms.getPublicKeysFromKeySetLPr(mSigningKeySetId);
                }
                return true;
            }
@@ -5704,19 +5708,19 @@ public class PackageManagerService extends IPackageManager.Stub {
            KeySetManagerService ksms = mSettings.mKeySetManagerService;
            try {
                // Old KeySetData no longer valid.
                ksms.removeAppKeySetData(pkg.packageName);
                ksms.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys);
                ksms.removeAppKeySetDataLPw(pkg.packageName);
                ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
                if (pkg.mKeySetMapping != null) {
                    for (Map.Entry<String, ArraySet<PublicKey>> entry :
                            pkg.mKeySetMapping.entrySet()) {
                        if (entry.getValue() != null) {
                            ksms.addDefinedKeySetToPackage(pkg.packageName,
                            ksms.addDefinedKeySetToPackageLPw(pkg.packageName,
                                                          entry.getValue(), entry.getKey());
                        }
                    }
                    if (pkg.mUpgradeKeySets != null) {
                        for (String upgradeAlias : pkg.mUpgradeKeySets) {
                            ksms.addUpgradeKeySetToPackage(pkg.packageName, upgradeAlias);
                            ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
                        }
                    }
                }
@@ -9906,14 +9910,9 @@ public class PackageManagerService extends IPackageManager.Stub {
        // required keys.
        long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets();
        KeySetManagerService ksms = mSettings.mKeySetManagerService;
        Set<Long> newSigningKeyIds = new ArraySet<Long>();
        for (PublicKey pk : newPkg.mSigningKeys) {
            newSigningKeyIds.add(ksms.getIdForPublicKey(pk));
        }
        //remove PUBLIC_KEY_NOT_FOUND, although not necessary
        newSigningKeyIds.remove(ksms.PUBLIC_KEY_NOT_FOUND);
        for (int i = 0; i < upgradeKeySets.length; i++) {
            if (newSigningKeyIds.containsAll(ksms.mKeySetMapping.get(upgradeKeySets[i]))) {
            Set<PublicKey> upgradeSet = ksms.getPublicKeysFromKeySetLPr(upgradeKeySets[i]);
            if (newPkg.mSigningKeys.containsAll(upgradeSet)) {
                return true;
            }
        }
@@ -10707,7 +10706,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (deletedPs != null) {
                if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
                    if (outInfo != null) {
                        mSettings.mKeySetManagerService.removeAppKeySetData(packageName);
                        mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
                        outInfo.removedAppId = mSettings.removePackageLPw(packageName);
                    }
                    if (deletedPs != null) {
@@ -12383,7 +12382,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
                mSettings.mKeySetManagerService.dump(pw, packageName, dumpState);
                mSettings.mKeySetManagerService.dumpLPr(pw, packageName, dumpState);
            }
            if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {