diff --git a/feature-set/src/lib.rs b/feature-set/src/lib.rs index e1b471d54ec..5931b05dd78 100644 --- a/feature-set/src/lib.rs +++ b/feature-set/src/lib.rs @@ -751,7 +751,7 @@ pub mod apply_cost_tracker_during_replay { } pub mod stricter_abi_and_runtime_constraints { - solana_pubkey::declare_id!("C37iaPi6VE4CZDueU1vL8y6pGp5i8amAbEsF31xzz723"); + solana_pubkey::declare_id!("CxeBn9PVeeXbmjbNwLv6U4C6svNxnC4JX6mfkvgeMocM"); } pub mod add_set_tx_loaded_accounts_data_size_instruction { @@ -1277,7 +1277,7 @@ pub static FEATURE_NAMES: LazyLock> = LazyLock::n (clean_up_delegation_errors::id(), "Return InsufficientDelegation instead of InsufficientFunds or InsufficientStake where applicable #31206"), (vote_state_add_vote_latency::id(), "replace Lockout with LandedVote (including vote latency) in vote state #31264"), (checked_arithmetic_in_fee_validation::id(), "checked arithmetic in fee validation #31273"), - (stricter_abi_and_runtime_constraints::id(), "use memory regions to map account data into the rbpf vm instead of copying the data"), + (stricter_abi_and_runtime_constraints::id(), "SIMD-0219: Stricter ABI and Runtime Constraints"), (last_restart_slot_sysvar::id(), "enable new sysvar last_restart_slot"), (reduce_stake_warmup_cooldown::id(), "reduce stake warmup cooldown from 25% to 9%"), (revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"), diff --git a/programs/sbf/rust/sysvar/src/lib.rs b/programs/sbf/rust/sysvar/src/lib.rs index b9186a6ce8f..1994cdff6a1 100644 --- a/programs/sbf/rust/sysvar/src/lib.rs +++ b/programs/sbf/rust/sysvar/src/lib.rs @@ -209,6 +209,16 @@ pub fn process_instruction( Ok(()) } + Some(&4) => { + // Attempt to store the result in the input region instead of the stack or heap + unsafe { + solana_define_syscall::definitions::sol_get_epoch_rewards_sysvar( + accounts[2].data.borrow_mut().as_mut_ptr(), + ) + }; + + Ok(()) + } _ => Err(ProgramError::InvalidInstructionData), } } diff --git a/programs/sbf/tests/sysvar.rs b/programs/sbf/tests/sysvar.rs index bb95a08ca99..6728e259949 100644 --- a/programs/sbf/tests/sysvar.rs +++ b/programs/sbf/tests/sysvar.rs @@ -69,7 +69,13 @@ fn test_sysvar_syscalls() { &authority_keypair, "solana_sbf_rust_sysvar", ); + let dummy_account_key = Pubkey::new_unique(); + bank.store_account( + &dummy_account_key, + &solana_account::AccountSharedData::new(1, 32, &program_id), + ); bank.freeze(); + let blockhash = bank.last_blockhash(); for ix_discriminator in 0..4 { let instruction = Instruction::new_with_bincode( @@ -77,7 +83,7 @@ fn test_sysvar_syscalls() { &[ix_discriminator], vec![ AccountMeta::new(mint_keypair.pubkey(), true), - AccountMeta::new(Pubkey::new_unique(), false), + AccountMeta::new(dummy_account_key, false), AccountMeta::new_readonly(clock::id(), false), AccountMeta::new_readonly(epoch_schedule::id(), false), AccountMeta::new_readonly(instructions::id(), false), @@ -90,11 +96,27 @@ fn test_sysvar_syscalls() { AccountMeta::new_readonly(epoch_rewards::id(), false), ], ); - let blockhash = bank.last_blockhash(); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let transaction = Transaction::new(&[&mint_keypair], message, blockhash); let sanitized_tx = RuntimeTransaction::from_transaction_for_tests(transaction); let result = bank.simulate_transaction(&sanitized_tx, false); assert!(result.result.is_ok()); } + + // Storing the result of get_sysvar() in the input region is not allowed + // because of the 16 byte alignment requirement of the EpochRewards sysvar. + let instruction = Instruction::new_with_bincode( + program_id, + &[4], + vec![ + AccountMeta::new(mint_keypair.pubkey(), true), + AccountMeta::new_readonly(epoch_rewards::id(), false), + AccountMeta::new(dummy_account_key, false), + ], + ); + let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); + let transaction = Transaction::new(&[&mint_keypair], message, blockhash); + let sanitized_tx = RuntimeTransaction::from_transaction_for_tests(transaction); + let result = bank.simulate_transaction(&sanitized_tx, false); + assert!(result.result.is_err()); } diff --git a/syscalls/src/sysvar.rs b/syscalls/src/sysvar.rs index a692b881307..17c03b9006f 100644 --- a/syscalls/src/sysvar.rs +++ b/syscalls/src/sysvar.rs @@ -1,6 +1,6 @@ use { super::*, crate::translate_mut, - solana_program_runtime::execution_budget::SVMTransactionExecutionCost, + solana_program_runtime::execution_budget::SVMTransactionExecutionCost, solana_sbpf::ebpf, }; fn get_sysvar( @@ -17,6 +17,14 @@ fn get_sysvar( .sysvar_base_cost .saturating_add(size_of::() as u64), )?; + + if var_addr >= ebpf::MM_INPUT_START + && invoke_context + .get_feature_set() + .stricter_abi_and_runtime_constraints + { + return Err(SyscallError::InvalidPointer.into()); + } translate_mut!( memory_mapping, check_aligned, @@ -203,6 +211,13 @@ declare_builtin_function!( .saturating_add(std::cmp::max(sysvar_buf_cost, mem_op_base_cost)), )?; + if var_addr >= ebpf::MM_INPUT_START + && invoke_context + .get_feature_set() + .stricter_abi_and_runtime_constraints + { + return Err(SyscallError::InvalidPointer.into()); + } // Abort: "Not all bytes in VM memory range `[var_addr, var_addr + length)` are writable." translate_mut!( memory_mapping,