diff options
author | Steve Kondik <steve@cyngn.com> | 2015-12-08 03:26:56 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-12-08 03:26:56 -0800 |
commit | 09f3036fd2eb2f4a8c29cf9a3519991b413a0904 (patch) | |
tree | 6f5cc49958abade0083f95bd067c18b169504ed5 | |
parent | 28e9852ad361927c33a3b76fae95474393be0e96 (diff) | |
parent | 1f76969bd8b6179f256dafb938bb458bc997c23d (diff) | |
download | android_system_security-09f3036fd2eb2f4a8c29cf9a3519991b413a0904.tar.gz android_system_security-09f3036fd2eb2f4a8c29cf9a3519991b413a0904.tar.bz2 android_system_security-09f3036fd2eb2f4a8c29cf9a3519991b413a0904.zip |
Merge tag 'android-6.0.1_r3' of https://android.googlesource.com/platform/system/security into HEADstable/cm-13.0-ZNH0E
Android 6.0.1 release 3
-rw-r--r-- | keystore/keystore.cpp | 98 | ||||
-rw-r--r-- | keystore/operation.h | 1 |
2 files changed, 83 insertions, 16 deletions
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp index 9c1e92c..8f276f5 100644 --- a/keystore/keystore.cpp +++ b/keystore/keystore.cpp @@ -79,6 +79,7 @@ #define KEY_SIZE ((NAME_MAX - 15) / 2) #define VALUE_SIZE 32768 #define PASSWORD_SIZE VALUE_SIZE +const size_t MAX_OPERATIONS = 15; using keymaster::SoftKeymasterDevice; @@ -920,6 +921,38 @@ public: } memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES); setupMasterKeys(); + return copyMasterKeyFile(src); + } + + ResponseCode copyMasterKeyFile(UserState* src) { + /* Copy the master key file to the new user. + * Unfortunately we don't have the src user's password so we cannot + * generate a new file with a new salt. + */ + int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY)); + if (in < 0) { + return ::SYSTEM_ERROR; + } + blob rawBlob; + size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob)); + if (close(in) != 0) { + return ::SYSTEM_ERROR; + } + int out = TEMP_FAILURE_RETRY(open(mMasterKeyFile, + O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)); + if (out < 0) { + return ::SYSTEM_ERROR; + } + size_t outLength = writeFully(out, (uint8_t*) &rawBlob, length); + if (close(out) != 0) { + return ::SYSTEM_ERROR; + } + if (outLength != length) { + ALOGW("blob not fully written %zu != %zu", outLength, length); + unlink(mMasterKeyFile); + return ::SYSTEM_ERROR; + } + return ::NO_ERROR; } @@ -1989,10 +2022,12 @@ public: } // Unconditionally clear the keystore, just to be safe. mKeyStore->resetUser(userId, false); - - // If the user has a parent user then use the parent's - // masterkey/password, otherwise there's nothing to do. if (parentId != -1) { + // This profile must share the same master key password as the parent + // profile. Because the password of the parent profile is not known + // here, the best we can do is copy the parent's master key and master + // key file. This makes this profile use the same master key as the + // parent profile, forever. return mKeyStore->copyMasterKey(parentId, userId); } else { return ::NO_ERROR; @@ -2030,7 +2065,17 @@ public: State state = mKeyStore->getState(userId); if (state != ::STATE_LOCKED) { - ALOGI("calling unlock when not locked, ignoring."); + switch (state) { + case ::STATE_NO_ERROR: + ALOGI("calling unlock when already unlocked, ignoring."); + break; + case ::STATE_UNINITIALIZED: + ALOGE("unlock called on uninitialized keystore."); + break; + default: + ALOGE("unlock called on keystore in unknown state: %d", state); + break; + } return state; } @@ -2654,23 +2699,26 @@ public: } keymaster_key_param_set_t outParams = {NULL, 0}; + + // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as + // pruneable. + while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) { + ALOGD("Reached or exceeded concurrent operations limit"); + if (!pruneOperation()) { + break; + } + } + err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle); + if (err != KM_ERROR_OK) { + ALOGE("Got error %d from begin()", err); + } // If there are too many operations abort the oldest operation that was // started as pruneable and try again. while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) { - sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation(); - ALOGD("Ran out of operation handles, trying to prune %p", oldest.get()); - - // We mostly ignore errors from abort() below because all we care about is whether at - // least one pruneable operation has been removed. - size_t op_count_before = mOperationMap.getPruneableOperationCount(); - int abort_error = abort(oldest); - size_t op_count_after = mOperationMap.getPruneableOperationCount(); - if (op_count_after >= op_count_before) { - // Failed to create space for a new operation. Bail to avoid an infinite loop. - ALOGE("Failed to remove pruneable operation %p, error: %d", - oldest.get(), abort_error); + ALOGE("Ran out of operation handles"); + if (!pruneOperation()) { break; } err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle); @@ -2874,6 +2922,24 @@ private: static const int32_t UID_SELF = -1; /** + * Prune the oldest pruneable operation. + */ + inline bool pruneOperation() { + sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation(); + ALOGD("Trying to prune operation %p", oldest.get()); + size_t op_count_before_abort = mOperationMap.getOperationCount(); + // We mostly ignore errors from abort() because all we care about is whether at least + // one operation has been removed. + int abort_error = abort(oldest); + if (mOperationMap.getOperationCount() >= op_count_before_abort) { + ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), + abort_error); + return false; + } + return true; + } + + /** * Get the effective target uid for a binder operation that takes an * optional uid as the target. */ diff --git a/keystore/operation.h b/keystore/operation.h index 01c4dbe..d8d1b18 100644 --- a/keystore/operation.h +++ b/keystore/operation.h @@ -57,6 +57,7 @@ public: const keymaster_key_characteristics_t** outCharacteristics); bool removeOperation(sp<IBinder> token); bool hasPruneableOperation() const; + size_t getOperationCount() const { return mMap.size(); } size_t getPruneableOperationCount() const; bool getOperationAuthToken(sp<IBinder> token, const hw_auth_token_t** outToken); bool setOperationAuthToken(sp<IBinder> token, const hw_auth_token_t* authToken); |