Confirmationui Rate Limiting App Abort Bug Fix
Increment the rate limiting counter when the application sends an abort message. Bug: 138655142 Test: Ran keystore_unit_tests and manually checked behavior of keystore application with confimrationui. Merged-In: I5f3af166391a32748a26f7709d30a5ac718499c0 Change-Id: I5f3af166391a32748a26f7709d30a5ac718499c0
This commit is contained in:
parent
6d98db4829
commit
b3bf30bb1f
3 changed files with 39 additions and 19 deletions
|
@ -116,12 +116,30 @@ Status ConfirmationManager::cancelConfirmationPrompt(const sp<IBinder>& listener
|
||||||
}
|
}
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
|
|
||||||
finalizeTransaction(ConfirmationResponseCode::Aborted, {}, true);
|
cancelPrompt();
|
||||||
|
|
||||||
*aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
|
*aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
|
||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfirmationManager::cancelPrompt() {
|
||||||
|
mMutex.lock();
|
||||||
|
mRateLimiting.cancelPrompt();
|
||||||
|
if (mCurrentListener != nullptr) {
|
||||||
|
mCurrentListener->unlinkToDeath(mDeathRecipient);
|
||||||
|
mCurrentListener = nullptr;
|
||||||
|
}
|
||||||
|
sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
|
||||||
|
if (mCurrentConfirmationUI != nullptr) {
|
||||||
|
mCurrentConfirmationUI->unlinkToDeath(this);
|
||||||
|
mCurrentConfirmationUI = nullptr;
|
||||||
|
}
|
||||||
|
mMutex.unlock();
|
||||||
|
if (confirmationUI != nullptr) {
|
||||||
|
confirmationUI->abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called by keystore main thread.
|
// Called by keystore main thread.
|
||||||
Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
|
Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
|
||||||
sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
|
sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
|
||||||
|
@ -136,13 +154,7 @@ Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
|
void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
|
||||||
hidl_vec<uint8_t> dataThatWasConfirmed,
|
hidl_vec<uint8_t> dataThatWasConfirmed) {
|
||||||
bool callAbortOnHal) {
|
|
||||||
// Note that confirmationUI->abort() may make the remote HAL process do an IPC call back
|
|
||||||
// into our process resulting in confirmationResultCallback() to be called... this in turn
|
|
||||||
// calls finalizeTransaction(). So we have to be careful a) not holding any locks;
|
|
||||||
// and b) ensure state has been cleared; before doing this...
|
|
||||||
|
|
||||||
mMutex.lock();
|
mMutex.lock();
|
||||||
mRateLimiting.processResult(responseCode);
|
mRateLimiting.processResult(responseCode);
|
||||||
sp<IBinder> listener = mCurrentListener;
|
sp<IBinder> listener = mCurrentListener;
|
||||||
|
@ -150,18 +162,12 @@ void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseC
|
||||||
mCurrentListener->unlinkToDeath(mDeathRecipient);
|
mCurrentListener->unlinkToDeath(mDeathRecipient);
|
||||||
mCurrentListener = nullptr;
|
mCurrentListener = nullptr;
|
||||||
}
|
}
|
||||||
sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
|
|
||||||
if (mCurrentConfirmationUI != nullptr) {
|
if (mCurrentConfirmationUI != nullptr) {
|
||||||
mCurrentConfirmationUI->unlinkToDeath(this);
|
mCurrentConfirmationUI->unlinkToDeath(this);
|
||||||
mCurrentConfirmationUI = nullptr;
|
mCurrentConfirmationUI = nullptr;
|
||||||
}
|
}
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
|
|
||||||
// Tell the HAL to shut down the confirmation dialog, if requested.
|
|
||||||
if (confirmationUI != nullptr && callAbortOnHal) {
|
|
||||||
confirmationUI->abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deliver result to the application that started the operation.
|
// Deliver result to the application that started the operation.
|
||||||
if (listener != nullptr) {
|
if (listener != nullptr) {
|
||||||
sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
|
sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
|
||||||
|
@ -178,7 +184,7 @@ void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseC
|
||||||
Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
|
Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
|
||||||
const hidl_vec<uint8_t>& dataThatWasConfirmed,
|
const hidl_vec<uint8_t>& dataThatWasConfirmed,
|
||||||
const hidl_vec<uint8_t>& confirmationToken) {
|
const hidl_vec<uint8_t>& confirmationToken) {
|
||||||
finalizeTransaction(responseCode, dataThatWasConfirmed, false);
|
finalizeTransaction(responseCode, dataThatWasConfirmed);
|
||||||
lock_guard<mutex> lock(mMutex);
|
lock_guard<mutex> lock(mMutex);
|
||||||
mLatestConfirmationToken = confirmationToken;
|
mLatestConfirmationToken = confirmationToken;
|
||||||
return Return<void>();
|
return Return<void>();
|
||||||
|
@ -201,7 +207,7 @@ void ConfirmationManager::binderDied(const wp<IBinder>& who) {
|
||||||
mCurrentListener = nullptr;
|
mCurrentListener = nullptr;
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
ALOGW("The process which requested the confirmation dialog died.\n");
|
ALOGW("The process which requested the confirmation dialog died.\n");
|
||||||
finalizeTransaction(ConfirmationResponseCode::SystemError, {}, true);
|
cancelPrompt();
|
||||||
} else {
|
} else {
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
}
|
}
|
||||||
|
@ -210,7 +216,7 @@ void ConfirmationManager::binderDied(const wp<IBinder>& who) {
|
||||||
void ConfirmationManager::serviceDied(uint64_t /* cookie */,
|
void ConfirmationManager::serviceDied(uint64_t /* cookie */,
|
||||||
const wp<android::hidl::base::V1_0::IBase>& /* who */) {
|
const wp<android::hidl::base::V1_0::IBase>& /* who */) {
|
||||||
ALOGW("The ConfirmationUI HAL died.\n");
|
ALOGW("The ConfirmationUI HAL died.\n");
|
||||||
finalizeTransaction(ConfirmationResponseCode::SystemError, {}, false);
|
finalizeTransaction(ConfirmationResponseCode::SystemError, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace keystore
|
} // namespace keystore
|
||||||
|
|
|
@ -84,8 +84,12 @@ class ConfirmationManager : public android::hardware::hidl_death_recipient,
|
||||||
private:
|
private:
|
||||||
friend class ConfirmationResultCallback;
|
friend class ConfirmationResultCallback;
|
||||||
|
|
||||||
|
// Set rate limiting to not decrement on next abort and aborts
|
||||||
|
// confirmationui.
|
||||||
|
void cancelPrompt();
|
||||||
|
|
||||||
void finalizeTransaction(ConfirmationResponseCode responseCode,
|
void finalizeTransaction(ConfirmationResponseCode responseCode,
|
||||||
hidl_vec<uint8_t> dataThatWasConfirmed, bool callAbortOnHal);
|
hidl_vec<uint8_t> dataThatWasConfirmed);
|
||||||
|
|
||||||
// This mutex protects all data below it.
|
// This mutex protects all data below it.
|
||||||
std::mutex mMutex;
|
std::mutex mMutex;
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace keystore {
|
||||||
|
|
||||||
using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
|
using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
|
||||||
|
|
||||||
using std::chrono::time_point;
|
|
||||||
using std::chrono::duration;
|
using std::chrono::duration;
|
||||||
|
using std::chrono::time_point;
|
||||||
|
|
||||||
template <typename Clock = std::chrono::steady_clock> class RateLimiting {
|
template <typename Clock = std::chrono::steady_clock> class RateLimiting {
|
||||||
private:
|
private:
|
||||||
|
@ -96,7 +96,17 @@ template <typename Clock = std::chrono::steady_clock> class RateLimiting {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The app is penalized for cancelling a request. Request are rolled back only if
|
||||||
|
// the prompt was cancelled by the system: e.g. a system error or asynchronous event.
|
||||||
|
// When the user cancels the prompt, it is subject to rate limiting.
|
||||||
|
static constexpr const uint_t kInvalidRequester = -1;
|
||||||
|
|
||||||
|
void cancelPrompt() { latest_requester_ = kInvalidRequester; }
|
||||||
|
|
||||||
void processResult(ConfirmationResponseCode rc) {
|
void processResult(ConfirmationResponseCode rc) {
|
||||||
|
if (latest_requester_ == kInvalidRequester) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case ConfirmationResponseCode::OK:
|
case ConfirmationResponseCode::OK:
|
||||||
// reset the counter slot
|
// reset the counter slot
|
||||||
|
|
Loading…
Reference in a new issue