summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-11-02 21:06:28 +0000
committerandroid-build-merger <android-build-merger@google.com>2015-11-02 21:06:28 +0000
commit733539776541fa51bddf2d38fb57e556d563d9af (patch)
tree40fa57edfeb0e6e5b0496b9b48ca61dc4aa270fb
parentbc22f8d63e2ca24ee4ee9d61258d6704bc78724b (diff)
parentddab0bb51320af9f277d98a4e36e77ea527503e5 (diff)
downloadandroid_system_security-733539776541fa51bddf2d38fb57e556d563d9af.tar.gz
android_system_security-733539776541fa51bddf2d38fb57e556d563d9af.tar.bz2
android_system_security-733539776541fa51bddf2d38fb57e556d563d9af.zip
Limit maximum number of concurrent keystore operations.
am: ddab0bb513 * commit 'ddab0bb51320af9f277d98a4e36e77ea527503e5': Limit maximum number of concurrent keystore operations.
-rw-r--r--keystore/keystore.cpp46
-rw-r--r--keystore/operation.h1
2 files changed, 35 insertions, 12 deletions
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index bb5a411..e466466 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;
@@ -2689,23 +2690,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);
@@ -2909,6 +2913,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);