Implement rate limiting on a per app basis for confirmationui
Implements the following strategy per app:
* Every attempted prompt increments a try counter.
* A prompt that was confirmed by the user resets the try counter.
* No penalty is applied after the first two cancelled attempts.
* A penalty of 30s is applied after attempt 3, 4, and 5 when
cancelled by the user
* A penalty of 60s * 2**(N - 6) after the Nth cancelled attempt
for attempts 6...
* A try counter that was not updated in 24h gets garbage collected.
Test: /data/nativetest64/keystore_unit_tests/keystore_unit_tests
Bug: 73892492
Change-Id: I0b50869259bfe920338c0c049cb9a715143ab103
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
index acca304..0dee4aa 100644
--- a/keystore/confirmation_manager.cpp
+++ b/keystore/confirmation_manager.cpp
@@ -23,6 +23,7 @@
#include <android/hardware/confirmationui/1.0/types.h>
#include <android/security/BpConfirmationPromptCallback.h>
#include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include "keystore_aidl_hidl_marshalling_utils.h"
@@ -69,6 +70,12 @@
return Status::ok();
}
+ uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+ if (!mRateLimiting.tryPrompt(callingUid)) {
+ *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::SystemError);
+ return Status::ok();
+ }
+
String8 promptText8(promptText);
String8 locale8(locale);
vector<UIOption> uiOptionsVector;
@@ -137,6 +144,7 @@
// and b) ensure state has been cleared; before doing this...
mMutex.lock();
+ mRateLimiting.processResult(responseCode);
sp<IBinder> listener = mCurrentListener;
if (mCurrentListener != nullptr) {
mCurrentListener->unlinkToDeath(mDeathRecipient);