Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

crates/accounts: fix conflicting lock orders #665

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

BurtonQin
Copy link
Contributor

unlocked_secrets and unlocked are parking_lot::RwLock.
In fn sign(), unlocked_secrets.read() -> password() -> unlocked.write().

let account = self.sstore.account_ref(&address)?;
match self.unlocked_secrets.read().get(&account) {
Some(secret) => Ok(self.sstore.sign_with_secret(&secret, &message)?),
None => {
let password = password
.map(Ok)
.unwrap_or_else(|| self.password(&account))?;

fn password(&self, account: &StoreAccountRef) -> Result<Password, SignError> {
let mut unlocked = self.unlocked.write();

There are two other cases where unlocked is locked before unlocked_secrets.
If they are concurrent with the above case, a deadlock may happen.

  1. pub fn is_unlocked(&self, address: &Address) -> bool {
    let unlocked = self.unlocked.read();
    let unlocked_secrets = self.unlocked_secrets.read();
  2. let mut unlocked = self.unlocked.write();
    if let Some(data) = unlocked.get(&account) {
    if let Unlock::Perm = data.unlock {
    return Ok(());
    }
    }
    if self.unlock_keep_secret && unlock == Unlock::Perm {
    // verify password and get the secret
    let secret = self.sstore.raw_secret(&account, &password)?;
    self.unlocked_secrets
    .write()

The fix is to assign unlocked_secrets.read() to a variable secrets and explicitly drop it before calling password().

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant