diff options
author | Shawn Willden <swillden@google.com> | 2015-11-23 22:55:25 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2015-11-23 22:55:25 +0000 |
commit | 80b09638de3571d2c12aa3d6e3d22682fc431b72 (patch) | |
tree | 09226d46b8f1e19aaf507786048cbc0f5bf26c35 | |
parent | e5f3a444f692f2d61d54783021551bb82c56e507 (diff) | |
parent | 108a5d34b5ce181dff52906a66862ec084841ec4 (diff) | |
download | security-brillo-m8-release.tar.gz |
Merge "Limit maximum number of concurrent keystore operations."brillo-m9-releasebrillo-m9-devbrillo-m8-releasebrillo-m8-dev
am: 108a5d34b5
* commit '108a5d34b5ce181dff52906a66862ec084841ec4':
Limit maximum number of concurrent keystore operations.
-rw-r--r-- | keystore/keystore.cpp | 46 | ||||
-rw-r--r-- | keystore/operation.h | 1 |
2 files changed, 35 insertions, 12 deletions
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp index ffd8b5cb..77b30392 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; @@ -2710,23 +2711,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); @@ -2930,6 +2934,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 01c4dbe5..d8d1b181 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); |