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

Commit 8c04facd authored by dcashman's avatar dcashman
Browse files

Refactor KeySet code.

Eliminate dependency in packagesetting keyset metadata on other packages by
introducing reference counts for KeySets and public keys.  This also allows
keysets to retain their id across reboots by eliminating the need to remove
all keyset data after scanning all packages on boot, which also should
drastically reduce the number of calls to ArraySet.removeAll().

Bug: 19617481

Change-Id: I6cc65f30e431b8e4ebe49047a9219a0d983f2774
parent 521c125d
Loading
Loading
Loading
Loading
+43 −2
Original line number Diff line number Diff line
@@ -18,5 +18,46 @@ package com.android.server.pm;

import android.os.Binder;

public class KeySetHandle extends Binder {
class KeySetHandle extends Binder{
    private final long mId;
    private int mRefCount;

    protected KeySetHandle(long id) {
        mId = id;
        mRefCount = 1;
    }

    /*
     * Only used when reading state from packages.xml
     */
    protected KeySetHandle(long id, int refCount) {
        mId = id;
        mRefCount = refCount;
    }

    public long getId() {
        return mId;
    }

    protected int getRefCountLPr() {
        return mRefCount;
    }

    /*
     * Only used when reading state from packages.xml
     */
    protected void setRefCountLPw(int newCount) {
         mRefCount = newCount;
         return;
    }

    protected void incrRefCountLPw() {
        mRefCount++;
        return;
    }

    protected int decrRefCountLPw() {
        mRefCount--;
        return mRefCount;
    }
}
+264 −253

File changed.

Preview size limit exceeded, changes collapsed.

+30 −52
Original line number Diff line number Diff line
@@ -27,12 +27,8 @@ public class PackageKeySetData {
    /* KeySet containing all signing keys - superset of the others */
    private long mProperSigningKeySet;

    private long[] mSigningKeySets;

    private long[] mUpgradeKeySets;

    private long[] mDefinedKeySets;

    private final ArrayMap<String, Long> mKeySetAliases = new ArrayMap<String, Long>();

    PackageKeySetData() {
@@ -41,23 +37,12 @@ public class PackageKeySetData {

    PackageKeySetData(PackageKeySetData original) {
        mProperSigningKeySet = original.mProperSigningKeySet;
        mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets);
        mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets);
        mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets);
        mKeySetAliases.putAll(original.mKeySetAliases);
    }

    protected void setProperSigningKeySet(long ks) {
        if (ks == mProperSigningKeySet) {

            /* nothing to change */
            return;
        }

        /* otherwise, our current signing keysets are likely invalid */
        removeAllSigningKeySets();
        mProperSigningKeySet = ks;
        addSigningKeySet(ks);
        return;
    }

@@ -65,15 +50,10 @@ public class PackageKeySetData {
        return mProperSigningKeySet;
    }

    protected void addSigningKeySet(long ks) {
        mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
    }

    protected void removeSigningKeySet(long ks) {
        mSigningKeySets = ArrayUtils.removeLong(mSigningKeySets, ks);
    }

    protected void addUpgradeKeySet(String alias) {
        if (alias == null) {
            return;
        }

        /* must have previously been defined */
        Long ks = mKeySetAliases.get(alias);
@@ -89,19 +69,9 @@ public class PackageKeySetData {
     * Used only when restoring keyset data from persistent storage.  Must
     * correspond to a defined-keyset.
     */
    protected void addUpgradeKeySetById(long ks) {
        mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
    }

    protected void addDefinedKeySet(long ks, String alias) {
        mDefinedKeySets = ArrayUtils.appendLong(mDefinedKeySets, ks);
        mKeySetAliases.put(alias, ks);
    }

    protected void removeAllSigningKeySets() {
        mProperSigningKeySet = KEYSET_UNASSIGNED;
        mSigningKeySets = null;
        return;
    protected void addUpgradeKeySetById(long ks) {
        mUpgradeKeySets = ArrayUtils.appendLong(mUpgradeKeySets, ks);
    }

    protected void removeAllUpgradeKeySets() {
@@ -109,36 +79,44 @@ public class PackageKeySetData {
        return;
    }

    protected void removeAllDefinedKeySets() {
        mDefinedKeySets = null;
        mKeySetAliases.clear();
        return;
    protected long[] getUpgradeKeySets() {
        return mUpgradeKeySets;
    }

    protected boolean packageIsSignedBy(long ks) {
        return ArrayUtils.contains(mSigningKeySets, ks);
    protected ArrayMap<String, Long> getAliases() {
        return mKeySetAliases;
    }

    protected long[] getSigningKeySets() {
        return mSigningKeySets;
    }
    /*
     * Replace defined keysets with new ones.
     */
    protected void setAliases(ArrayMap<String, Long> newAliases) {

    protected long[] getUpgradeKeySets() {
        return mUpgradeKeySets;
        /* remove old aliases */
        removeAllDefinedKeySets();

        /* add new ones */
        final int newAliasSize = newAliases.size();
        for (int i = 0; i < newAliasSize; i++) {
            mKeySetAliases.put(newAliases.keyAt(i), newAliases.valueAt(i));;
        }
    }

    protected long[] getDefinedKeySets() {
        return mDefinedKeySets;
    protected void addDefinedKeySet(long ks, String alias) {
        mKeySetAliases.put(alias, ks);
    }

    protected ArrayMap<String, Long> getAliases() {
        return mKeySetAliases;
    protected void removeAllDefinedKeySets() {
        final int aliasSize = mKeySetAliases.size();
        for (int i = 0; i < aliasSize; i++) {
            mKeySetAliases.removeAt(i);
        }
    }

    protected boolean isUsingDefinedKeySets() {

        /* should never be the case that mDefinedKeySets.length == 0 */
        return (mDefinedKeySets != null && mDefinedKeySets.length > 0);
        /* should never be the case that mUpgradeKeySets.length == 0 */
        return (mKeySetAliases.size() > 0);
    }

    protected boolean isUsingUpgradeKeySets() {
+2 −12
Original line number Diff line number Diff line
@@ -5885,21 +5885,11 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Add the package's KeySets to the global KeySetManagerService
            KeySetManagerService ksms = mSettings.mKeySetManagerService;
            try {
                // Old KeySetData no longer valid.
                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.addDefinedKeySetToPackageLPw(pkg.packageName,
                                                          entry.getValue(), entry.getKey());
                        }
                    }
                    ksms.addDefinedKeySetsToPackageLPw(pkg.packageName, pkg.mKeySetMapping);
                    if (pkg.mUpgradeKeySets != null) {
                        for (String upgradeAlias : pkg.mUpgradeKeySets) {
                            ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
                        }
                        ksms.addUpgradeKeySetsToPackageLPw(pkg.packageName, pkg.mUpgradeKeySets);
                    }
                }
            } catch (NullPointerException e) {
+25 −19
Original line number Diff line number Diff line
@@ -223,6 +223,8 @@ final class Settings {
    // For reading/writing settings file.
    private final ArrayList<Signature> mPastSignatures =
            new ArrayList<Signature>();
    private final ArrayMap<Long, Integer> mKeySetRefs =
            new ArrayMap<Long, Integer>();

    // Mapping from permission names to info about them.
    final ArrayMap<String, BasePermission> mPermissions =
@@ -1855,33 +1857,24 @@ final class Settings {
            serializer.endTag(null, "perms");
        }

        writeSigningKeySetsLPr(serializer, pkg.keySetData);
        writeSigningKeySetLPr(serializer, pkg.keySetData);
        writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
        writeKeySetAliasesLPr(serializer, pkg.keySetData);

        serializer.endTag(null, "package");
    }

    void writeSigningKeySetsLPr(XmlSerializer serializer,
    void writeSigningKeySetLPr(XmlSerializer serializer,
            PackageKeySetData data) throws IOException {
        if (data.getSigningKeySets() != null) {
            // Keep track of the original signing-keyset.
            // Must be recorded first, since it will be read first and wipe the
            // current signing-keysets for the package when set.
            long properSigningKeySet = data.getProperSigningKeySet();
        serializer.startTag(null, "proper-signing-keyset");
            serializer.attribute(null, "identifier", Long.toString(properSigningKeySet));
        serializer.attribute(null, "identifier",
                Long.toString(data.getProperSigningKeySet()));
        serializer.endTag(null, "proper-signing-keyset");
            for (long id : data.getSigningKeySets()) {
                serializer.startTag(null, "signing-keyset");
                serializer.attribute(null, "identifier", Long.toString(id));
                serializer.endTag(null, "signing-keyset");
            }
        }
    }

    void writeUpgradeKeySetsLPr(XmlSerializer serializer,
            PackageKeySetData data) throws IOException {
        long properSigning = data.getProperSigningKeySet();
        if (data.isUsingUpgradeKeySets()) {
            for (long id : data.getUpgradeKeySets()) {
                serializer.startTag(null, "upgrade-keyset");
@@ -1973,6 +1966,7 @@ final class Settings {

        mPendingPackages.clear();
        mPastSignatures.clear();
        mKeySetRefs.clear();

        try {
            if (str == null) {
@@ -2099,7 +2093,7 @@ final class Settings {
                    final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
                    mReadExternalStorageEnforced = "1".equals(enforcement);
                } else if (tagName.equals("keyset-settings")) {
                    mKeySetManagerService.readKeySetsLPw(parser);
                    mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
                } else {
                    Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
                            + parser.getName());
@@ -2121,6 +2115,7 @@ final class Settings {
        }

        final int N = mPendingPackages.size();

        for (int i = 0; i < N; i++) {
            final PendingPackage pp = mPendingPackages.get(i);
            Object idObj = getUserIdLPr(pp.sharedId);
@@ -2924,16 +2919,27 @@ final class Settings {
                    packageSetting.permissionsFixed = true;
                } else if (tagName.equals("proper-signing-keyset")) {
                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                    Integer refCt = mKeySetRefs.get(id);
                    if (refCt != null) {
                        mKeySetRefs.put(id, refCt + 1);
                    } else {
                        mKeySetRefs.put(id, 1);
                    }
                    packageSetting.keySetData.setProperSigningKeySet(id);
                } else if (tagName.equals("signing-keyset")) {
                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                    packageSetting.keySetData.addSigningKeySet(id);
                    // from v1 of keysetmanagerservice - no longer used
                } else if (tagName.equals("upgrade-keyset")) {
                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                    packageSetting.keySetData.addUpgradeKeySetById(id);
                } else if (tagName.equals("defined-keyset")) {
                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                    String alias = parser.getAttributeValue(null, "alias");
                    Integer refCt = mKeySetRefs.get(id);
                    if (refCt != null) {
                        mKeySetRefs.put(id, refCt + 1);
                    } else {
                        mKeySetRefs.put(id, 1);
                    }
                    packageSetting.keySetData.addDefinedKeySet(id, alias);
                } else {
                    PackageManagerService.reportSettingsProblem(Log.WARN,