Always bail if program modifies a ro account (#17569)

This commit is contained in:
Jack May
2021-05-28 09:50:25 -07:00
committed by GitHub
parent 8924fbf6a0
commit a3240aebde
13 changed files with 248 additions and 151 deletions

View File

@@ -17,7 +17,7 @@ use solana_bpf_loader_program::{
use solana_cli_output::display::println_transaction;
use solana_rbpf::{
static_analysis::Analysis,
vm::{Config, Executable, Tracer}
vm::{Config, Executable, Tracer},
};
use solana_runtime::{
bank::{Bank, ExecuteTimings, NonceRollbackInfo, TransactionBalancesSet, TransactionResults},
@@ -278,7 +278,6 @@ fn run_program(
&bpf_loader::id(),
parameter_accounts,
parameter_bytes.as_slice(),
true,
)
.unwrap();
}
@@ -757,6 +756,7 @@ fn test_program_bpf_invoke_sanity() {
const TEST_RETURN_ERROR: u8 = 11;
const TEST_PRIVILEGE_DEESCALATION_ESCALATION_SIGNER: u8 = 12;
const TEST_PRIVILEGE_DEESCALATION_ESCALATION_WRITABLE: u8 = 13;
const TEST_WRITABLE_DEESCALATION_WRITABLE: u8 = 14;
#[allow(dead_code)]
#[derive(Debug)]
@@ -874,7 +874,6 @@ fn test_program_bpf_invoke_sanity() {
invoked_program_id.clone(),
invoked_program_id.clone(),
invoked_program_id.clone(),
invoked_program_id.clone(),
],
Languages::Rust => vec![
solana_sdk::system_program::id(),
@@ -894,7 +893,6 @@ fn test_program_bpf_invoke_sanity() {
invoked_program_id.clone(),
invoked_program_id.clone(),
invoked_program_id.clone(),
invoked_program_id.clone(),
solana_sdk::system_program::id(),
],
};
@@ -1000,6 +998,12 @@ fn test_program_bpf_invoke_sanity() {
&[invoked_program_id.clone()],
);
do_invoke_failure_test_local(
TEST_WRITABLE_DEESCALATION_WRITABLE,
TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified),
&[invoked_program_id.clone()],
);
// Check resulting state
assert_eq!(43, bank.get_balance(&derived_key1));
@@ -2454,3 +2458,68 @@ fn test_program_bpf_finalize() {
TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
);
}
#[cfg(feature = "bpf_rust")]
#[test]
fn test_program_bpf_ro_account_modify() {
solana_logger::setup();
let GenesisConfigInfo {
genesis_config,
mint_keypair,
..
} = create_genesis_config(50);
let mut bank = Bank::new(&genesis_config);
let (name, id, entrypoint) = solana_bpf_loader_program!();
bank.add_builtin(&name, id, entrypoint);
let bank = Arc::new(bank);
let bank_client = BankClient::new_shared(&bank);
let program_id = load_bpf_program(
&bank_client,
&bpf_loader::id(),
&mint_keypair,
"solana_bpf_rust_ro_account_modify",
);
let argument_keypair = Keypair::new();
let account = AccountSharedData::new(42, 100, &program_id);
bank.store_account(&argument_keypair.pubkey(), &account);
let from_keypair = Keypair::new();
let account = AccountSharedData::new(84, 0, &solana_sdk::system_program::id());
bank.store_account(&from_keypair.pubkey(), &account);
let mint_pubkey = mint_keypair.pubkey();
let account_metas = vec![
AccountMeta::new_readonly(argument_keypair.pubkey(), false),
AccountMeta::new_readonly(program_id, false),
];
let instruction = Instruction::new_with_bytes(program_id, &[0], account_metas.clone());
let message = Message::new(&[instruction], Some(&mint_pubkey));
let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
println!("result: {:?}", result);
assert_eq!(
result.unwrap_err().unwrap(),
TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
);
let instruction = Instruction::new_with_bytes(program_id, &[1], account_metas.clone());
let message = Message::new(&[instruction], Some(&mint_pubkey));
let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
println!("result: {:?}", result);
assert_eq!(
result.unwrap_err().unwrap(),
TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
);
let instruction = Instruction::new_with_bytes(program_id, &[2], account_metas.clone());
let message = Message::new(&[instruction], Some(&mint_pubkey));
let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
println!("result: {:?}", result);
assert_eq!(
result.unwrap_err().unwrap(),
TransactionError::InstructionError(0, InstructionError::ReadonlyDataModified)
);
}