aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2020-05-13 17:29:10 +0800
committerfanquake <fanquake@gmail.com>2020-05-13 17:36:06 +0800
commita33901cb6d82e2f75aab67f80a8852b7e6e9817a (patch)
tree6bb6f8d297527442b60042de64971cae50a5bbf9 /src/wallet
parent246e878e784584dd0d323a612007dfdafddeba42 (diff)
parent9f59dde9740d065118bdddde75ef9f4e4603a7b1 (diff)
downloadbitcoin-a33901cb6d82e2f75aab67f80a8852b7e6e9817a.tar.xz
Merge #18814: rpc: Relock wallet only if most recent callback
9f59dde9740d065118bdddde75ef9f4e4603a7b1 rpc: Relock wallet only if most recent callback (João Barbosa) a2e6db5c4f1bb52a8814102b628e51652493d06a rpc: Add mutex to guard deadlineTimers (João Barbosa) Pull request description: This PR fixes an early relocking race condition from #18811 where old relock callback runs after new wallet unlock code and nRelockTime update but before rpcRunLater call, causing early relock and incorrect nRelockTime time Issue introduced in #18487. Fixes #18811. ACKs for top commit: MarcoFalke: ACK 9f59dde9740d065118bdddde75ef9f4e4603a7b1 ryanofsky: Code review ACK 9f59dde9740d065118bdddde75ef9f4e4603a7b1. No changes since last review except squashing commits. jonatack: ACK 9f59dde9740d065118bdddde75ef Tree-SHA512: 2f7fc03e5ab6037337f2d82dfad432495cc337c77d07c968ee2355105db6292f24543c03456f5402e0e759577a4327758f9372f7ea29de6d56dc3695fda9b379
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/rpcwallet.cpp8
-rw-r--r--src/wallet/wallet.h4
2 files changed, 10 insertions, 2 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index dda00f1fe7..c2d314140c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1892,6 +1892,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
}.Check(request);
int64_t nSleepTime;
+ int64_t relock_time;
+ // Prevent concurrent calls to walletpassphrase with the same wallet.
+ LOCK(pwallet->m_unlock_mutex);
{
LOCK(pwallet->cs_wallet);
@@ -1929,6 +1932,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime;
+ relock_time = pwallet->nRelockTime;
}
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
@@ -1940,9 +1944,11 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
// wallet before the following callback is called. If a valid shared pointer
// is acquired in the callback then the wallet is still loaded.
std::weak_ptr<CWallet> weak_wallet = wallet;
- pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
+ pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet, relock_time] {
if (auto shared_wallet = weak_wallet.lock()) {
LOCK(shared_wallet->cs_wallet);
+ // Skip if this is not the most recent rpcRunLater callback.
+ if (shared_wallet->nRelockTime != relock_time) return;
shared_wallet->Lock();
shared_wallet->nRelockTime = 0;
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 8f624c25d7..a29fa22207 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -871,8 +871,10 @@ public:
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
- int64_t nRelockTime = 0;
+ int64_t nRelockTime GUARDED_BY(cs_wallet){0};
+ // Used to prevent concurrent calls to walletpassphrase RPC.
+ Mutex m_unlock_mutex;
bool Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);