mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-17 21:50:43 +02:00
rpc: Fix rpcRunLater race in walletpassphrase
This commit is contained in:
parent
d2db25233c
commit
7b8e15728d
@ -1918,44 +1918,52 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
|
|||||||
},
|
},
|
||||||
}.Check(request);
|
}.Check(request);
|
||||||
|
|
||||||
auto locked_chain = pwallet->chain().lock();
|
int64_t nSleepTime;
|
||||||
LOCK(pwallet->cs_wallet);
|
{
|
||||||
|
auto locked_chain = pwallet->chain().lock();
|
||||||
|
LOCK(pwallet->cs_wallet);
|
||||||
|
|
||||||
if (!pwallet->IsCrypted()) {
|
if (!pwallet->IsCrypted()) {
|
||||||
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
|
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
|
||||||
|
SecureString strWalletPass;
|
||||||
|
strWalletPass.reserve(100);
|
||||||
|
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||||
|
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
||||||
|
strWalletPass = request.params[0].get_str().c_str();
|
||||||
|
|
||||||
|
// Get the timeout
|
||||||
|
nSleepTime = request.params[1].get_int64();
|
||||||
|
// Timeout cannot be negative, otherwise it will relock immediately
|
||||||
|
if (nSleepTime < 0) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
|
||||||
|
}
|
||||||
|
// Clamp timeout
|
||||||
|
constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
|
||||||
|
if (nSleepTime > MAX_SLEEP_TIME) {
|
||||||
|
nSleepTime = MAX_SLEEP_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strWalletPass.empty()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pwallet->Unlock(strWalletPass)) {
|
||||||
|
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
|
||||||
|
}
|
||||||
|
|
||||||
|
pwallet->TopUpKeyPool();
|
||||||
|
|
||||||
|
pwallet->nRelockTime = GetTime() + nSleepTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
|
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
|
||||||
SecureString strWalletPass;
|
// can occur. The deadlock would happen when RPCRunLater removes the
|
||||||
strWalletPass.reserve(100);
|
// previous timer (and waits for the callback to finish if already running)
|
||||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
// and the callback locks cs_wallet.
|
||||||
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
AssertLockNotHeld(wallet->cs_wallet);
|
||||||
strWalletPass = request.params[0].get_str().c_str();
|
|
||||||
|
|
||||||
// Get the timeout
|
|
||||||
int64_t nSleepTime = request.params[1].get_int64();
|
|
||||||
// Timeout cannot be negative, otherwise it will relock immediately
|
|
||||||
if (nSleepTime < 0) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
|
|
||||||
}
|
|
||||||
// Clamp timeout
|
|
||||||
constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
|
|
||||||
if (nSleepTime > MAX_SLEEP_TIME) {
|
|
||||||
nSleepTime = MAX_SLEEP_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strWalletPass.empty()) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pwallet->Unlock(strWalletPass)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
|
|
||||||
}
|
|
||||||
|
|
||||||
pwallet->TopUpKeyPool();
|
|
||||||
|
|
||||||
pwallet->nRelockTime = GetTime() + nSleepTime;
|
|
||||||
|
|
||||||
// Keep a weak pointer to the wallet so that it is possible to unload the
|
// Keep a weak pointer to the wallet so that it is possible to unload the
|
||||||
// wallet before the following callback is called. If a valid shared pointer
|
// wallet before the following callback is called. If a valid shared pointer
|
||||||
// is acquired in the callback then the wallet is still loaded.
|
// is acquired in the callback then the wallet is still loaded.
|
||||||
|
Loading…
Reference in New Issue
Block a user