Prevent the invoke and upgrade of programs in the same tx batch (#14653)
* Prevent the invoke and upgrade of programs in the same tx batch * Pass program address as writable in the upgrade instruction
This commit is contained in:
@ -26,7 +26,7 @@ use solana_sdk::{
|
||||
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||
clock::Clock,
|
||||
entrypoint::SUCCESS,
|
||||
feature_set::bpf_compute_budget_balancing,
|
||||
feature_set::{bpf_compute_budget_balancing, prevent_upgrade_and_invoke},
|
||||
instruction::InstructionError,
|
||||
keyed_account::{from_keyed_account, next_keyed_account, KeyedAccount},
|
||||
loader_instruction::LoaderInstruction,
|
||||
@ -470,6 +470,12 @@ fn process_loader_upgradeable_instruction(
|
||||
log!(logger, "Program account not executable");
|
||||
return Err(InstructionError::AccountNotExecutable);
|
||||
}
|
||||
if !program.is_writable()
|
||||
&& invoke_context.is_feature_active(&prevent_upgrade_and_invoke::id())
|
||||
{
|
||||
log!(logger, "Program account not writeable");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
if &program.owner()? != program_id {
|
||||
log!(logger, "Program account not owned by loader");
|
||||
return Err(InstructionError::IncorrectProgramId);
|
||||
@ -2000,7 +2006,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2062,7 +2068,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2095,7 +2101,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2128,7 +2134,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2162,7 +2168,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2192,6 +2198,39 @@ mod tests {
|
||||
program_account.borrow_mut().owner = Pubkey::new_unique();
|
||||
assert_eq!(
|
||||
Err(InstructionError::IncorrectProgramId),
|
||||
process_instruction(
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
KeyedAccount::new_readonly(&sysvar::clock::id(), false, &clock_account),
|
||||
KeyedAccount::new_readonly(
|
||||
&upgrade_authority_address,
|
||||
true,
|
||||
&upgrade_authority_account
|
||||
)
|
||||
],
|
||||
&instruction,
|
||||
&mut MockInvokeContext::default()
|
||||
)
|
||||
);
|
||||
|
||||
// Case: Program account not writable
|
||||
let (buffer_account, program_account, programdata_account, spill_account) = get_accounts(
|
||||
&buffer_address,
|
||||
&programdata_address,
|
||||
&upgrade_authority_address,
|
||||
slot,
|
||||
&elf_orig,
|
||||
&elf_new,
|
||||
min_program_balance,
|
||||
min_programdata_balance,
|
||||
);
|
||||
assert_eq!(
|
||||
Err(InstructionError::InvalidArgument),
|
||||
process_instruction(
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
@ -2233,7 +2272,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2270,7 +2309,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2303,7 +2342,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&Pubkey::new_unique(), false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2340,7 +2379,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2384,7 +2423,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
@ -2419,7 +2458,7 @@ mod tests {
|
||||
&bpf_loader_upgradeable::id(),
|
||||
&[
|
||||
KeyedAccount::new(&programdata_address, false, &programdata_account),
|
||||
KeyedAccount::new_readonly(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&program_address, false, &program_account),
|
||||
KeyedAccount::new(&buffer_address, false, &buffer_account),
|
||||
KeyedAccount::new(&spill_address, false, &spill_account),
|
||||
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
|
||||
|
Reference in New Issue
Block a user