From 4bb573ba82e2fffd75811dd861ce74cbf25857e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Wed, 5 Mar 2025 18:54:53 +0000 Subject: [PATCH 1/2] Adds test_invoke_non_program_account_owned_by_a_builtin(). --- runtime/src/bank/tests.rs | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 1c88b586f70529..3036ebdfeab4c2 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -8392,6 +8392,46 @@ fn test_program_is_native_loader() { ); } +#[test] +fn test_invoke_non_program_account_owned_by_a_builtin() { + let (genesis_config, mint_keypair) = create_genesis_config(10000000); + let mut bank = Bank::new_for_tests(&genesis_config); + bank.activate_feature(&feature_set::remove_accounts_executable_flag_checks::id()); + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); + + let bogus_program = Pubkey::new_unique(); + bank.transfer( + genesis_config.rent.minimum_balance(0), + &mint_keypair, + &bogus_program, + ) + .unwrap(); + + let created_account_keypair = Keypair::new(); + let mut ix = system_instruction::create_account( + &mint_keypair.pubkey(), + &created_account_keypair.pubkey(), + genesis_config.rent.minimum_balance(0), + 0, + &system_program::id(), + ); + // Calling an account owned by the system program, instead of calling the system program itself + ix.program_id = bogus_program; + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&mint_keypair.pubkey()), + &[&mint_keypair, &created_account_keypair], + bank.last_blockhash(), + ); + assert_eq!( + bank.process_transaction(&tx), + Err(TransactionError::InstructionError( + 0, + InstructionError::ExternalAccountDataModified + )) + ); +} + #[test] fn test_debug_bank() { let (genesis_config, _mint_keypair) = create_genesis_config(50000); From 64d3113d985a0c3a1f89ada15848a00f54a1cfd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Wed, 5 Mar 2025 18:58:34 +0000 Subject: [PATCH 2/2] Throws InstructionError::UnsupportedProgramId when invoking any non loader owned or non built-in account. --- program-runtime/src/invoke_context.rs | 17 ++++++++++++++++- runtime/src/bank/tests.rs | 6 +++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 65c9cd1638827e..e2adf026fe4249 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -28,7 +28,9 @@ use { program::{BuiltinFunction, SBPFVersion}, vm::{Config, ContextObject, EbpfVm}, }, - solana_sdk_ids::{bpf_loader_deprecated, native_loader, sysvar}, + solana_sdk_ids::{ + bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4, native_loader, sysvar, + }, solana_stable_layout::stable_instruction::StableInstruction, solana_timings::{ExecuteDetailsTimings, ExecuteTimings}, solana_transaction_context::{ @@ -523,6 +525,19 @@ impl<'a> InvokeContext<'a> { let owner_id = borrowed_root_account.get_owner(); if native_loader::check_id(owner_id) { *borrowed_root_account.get_key() + } else if self + .get_feature_set() + .is_active(&remove_accounts_executable_flag_checks::id()) + { + if bpf_loader_deprecated::check_id(owner_id) + || bpf_loader::check_id(owner_id) + || bpf_loader_upgradeable::check_id(owner_id) + || loader_v4::check_id(owner_id) + { + *owner_id + } else { + return Err(InstructionError::UnsupportedProgramId); + } } else { *owner_id } diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 3036ebdfeab4c2..77184b6e7e0063 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -8427,7 +8427,7 @@ fn test_invoke_non_program_account_owned_by_a_builtin() { bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - InstructionError::ExternalAccountDataModified + InstructionError::UnsupportedProgramId )) ); } @@ -13596,7 +13596,7 @@ fn test_loader_v3_to_v4_migration() { finalized_migration_transaction.clone(), Err(TransactionError::InstructionError( 0, - InstructionError::InvalidInstructionData, + InstructionError::UnsupportedProgramId, )), ), ( @@ -13604,7 +13604,7 @@ fn test_loader_v3_to_v4_migration() { finalized_migration_transaction.clone(), Err(TransactionError::InstructionError( 0, - InstructionError::InvalidInstructionData, + InstructionError::UnsupportedProgramId, )), ), (