fix(security): synchronize SecureVault::scope_ between the main thread and worker security ops
Concurrency audit: SecureVault::scope_ (std::string) is written by setWalletScope() on the main thread (wallet switch) while getVaultPath() — reached from retrieve()/hasVault()/changePin()/store() — runs on RPC worker threads during a send-time or startup unlock. A concurrent wallet switch and a worker vault op is a data race on the string (and could resolve the wrong vault file). Guard scope_ with a small mutex: setWalletScope() assigns under it; getVaultPath() copies it out under the lock and uses the copy. The lock is held only for the string copy — never across Argon2id or file I/O — and getVaultPath() never calls setWalletScope(), so no deadlock. Argon2id params, key derivation, AEAD, the vault file format and retrieve/store/changePin are byte-identical. SecureVault is held via unique_ptr and used by pointer, so the added (non-movable) mutex is fine. Synchronization only. Threading fix — clean build + ctest; the race is runtime-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
||||
namespace dragonx {
|
||||
namespace util {
|
||||
@@ -101,6 +102,9 @@ private:
|
||||
const uint8_t* salt, size_t saltLen,
|
||||
uint8_t* key, size_t keyLen) const;
|
||||
|
||||
// Guards scope_: setWalletScope() runs on the main thread (wallet switch) while retrieve()/hasVault()/
|
||||
// changePin() run on RPC worker threads and read it via getVaultPath().
|
||||
mutable std::mutex scopeMutex_;
|
||||
std::string scope_; // "" = default/legacy wallet (vault.dat); else a sanitized wallet-file tag
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user