Fix CPI duplicate account privilege escalation (#22752)
* Adds TEST_DUPLICATE_PRIVILEGE_ESCALATION_SIGNER and TEST_DUPLICATE_PRIVILEGE_ESCALATION_WRITABLE. * Moves CPI privilege verification out of deduplication loop.
This commit is contained in:
committed by
GitHub
parent
fa51e5b704
commit
a71f05f86c
@@ -698,33 +698,6 @@ impl<'a> InvokeContext<'a> {
|
||||
);
|
||||
InstructionError::MissingAccount
|
||||
})?;
|
||||
let borrowed_account = instruction_context
|
||||
.try_borrow_account(self.transaction_context, index_in_caller)?;
|
||||
|
||||
// Readonly in caller cannot become writable in callee
|
||||
if account_meta.is_writable && !borrowed_account.is_writable() {
|
||||
ic_msg!(
|
||||
self,
|
||||
"{}'s writable privilege escalated",
|
||||
borrowed_account.get_key(),
|
||||
);
|
||||
return Err(InstructionError::PrivilegeEscalation);
|
||||
}
|
||||
|
||||
// To be signed in the callee,
|
||||
// it must be either signed in the caller or by the program
|
||||
if account_meta.is_signer
|
||||
&& !(borrowed_account.is_signer()
|
||||
|| signers.contains(borrowed_account.get_key()))
|
||||
{
|
||||
ic_msg!(
|
||||
self,
|
||||
"{}'s signer privilege escalated",
|
||||
borrowed_account.get_key()
|
||||
);
|
||||
return Err(InstructionError::PrivilegeEscalation);
|
||||
}
|
||||
|
||||
duplicate_indicies.push(deduplicated_instruction_accounts.len());
|
||||
deduplicated_instruction_accounts.push(InstructionAccount {
|
||||
index_in_transaction,
|
||||
@@ -734,6 +707,35 @@ impl<'a> InvokeContext<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
for instruction_account in deduplicated_instruction_accounts.iter() {
|
||||
let borrowed_account = instruction_context.try_borrow_account(
|
||||
self.transaction_context,
|
||||
instruction_account.index_in_caller,
|
||||
)?;
|
||||
|
||||
// Readonly in caller cannot become writable in callee
|
||||
if instruction_account.is_writable && !borrowed_account.is_writable() {
|
||||
ic_msg!(
|
||||
self,
|
||||
"{}'s writable privilege escalated",
|
||||
borrowed_account.get_key(),
|
||||
);
|
||||
return Err(InstructionError::PrivilegeEscalation);
|
||||
}
|
||||
|
||||
// To be signed in the callee,
|
||||
// it must be either signed in the caller or by the program
|
||||
if instruction_account.is_signer
|
||||
&& !(borrowed_account.is_signer() || signers.contains(borrowed_account.get_key()))
|
||||
{
|
||||
ic_msg!(
|
||||
self,
|
||||
"{}'s signer privilege escalated",
|
||||
borrowed_account.get_key()
|
||||
);
|
||||
return Err(InstructionError::PrivilegeEscalation);
|
||||
}
|
||||
}
|
||||
let instruction_accounts: Vec<InstructionAccount> = duplicate_indicies
|
||||
.into_iter()
|
||||
.map(|duplicate_index| deduplicated_instruction_accounts[duplicate_index].clone())
|
||||
|
Reference in New Issue
Block a user