Gate cpi program account passing (bp #14443) (#14505)

* Gate cpi program account passing (#14443)

(cherry picked from commit a8b5a32b50)

# Conflicts:
#	sdk/src/feature_set.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
This commit is contained in:
mergify[bot]
2021-01-09 03:16:26 +00:00
committed by GitHub
parent 463e377ccc
commit 35b42e1541
3 changed files with 31 additions and 12 deletions

View File

@ -18,7 +18,7 @@ use solana_sdk::{
feature_set::{ feature_set::{
limit_cpi_loader_invoke, pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, limit_cpi_loader_invoke, pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled,
sha256_syscall_enabled, sol_log_compute_units_syscall, sha256_syscall_enabled, sol_log_compute_units_syscall,
try_find_program_address_syscall_enabled, try_find_program_address_syscall_enabled, use_loaded_program_accounts,
}, },
hash::{Hasher, HASH_BYTES}, hash::{Hasher, HASH_BYTES},
instruction::{AccountMeta, Instruction, InstructionError}, instruction::{AccountMeta, Instruction, InstructionError},
@ -739,6 +739,7 @@ trait SyscallInvokeSigned<'a> {
) -> Result<Instruction, EbpfError<BPFError>>; ) -> Result<Instruction, EbpfError<BPFError>>;
fn translate_accounts( fn translate_accounts(
&self, &self,
skip_program: bool,
account_keys: &[Pubkey], account_keys: &[Pubkey],
program_account_index: usize, program_account_index: usize,
account_infos_addr: u64, account_infos_addr: u64,
@ -804,6 +805,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
fn translate_accounts( fn translate_accounts(
&self, &self,
skip_program: bool,
account_keys: &[Pubkey], account_keys: &[Pubkey],
program_account_index: usize, program_account_index: usize,
account_infos_addr: u64, account_infos_addr: u64,
@ -826,7 +828,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
let mut accounts = Vec::with_capacity(account_keys.len()); let mut accounts = Vec::with_capacity(account_keys.len());
let mut refs = Vec::with_capacity(account_keys.len()); let mut refs = Vec::with_capacity(account_keys.len());
'root: for (i, account_key) in account_keys.iter().enumerate() { 'root: for (i, account_key) in account_keys.iter().enumerate() {
if i == program_account_index { if skip_program && i == program_account_index {
// Don't look for caller passed executable, runtime already has it // Don't look for caller passed executable, runtime already has it
continue 'root; continue 'root;
} }
@ -1103,6 +1105,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
fn translate_accounts( fn translate_accounts(
&self, &self,
skip_program: bool,
account_keys: &[Pubkey], account_keys: &[Pubkey],
program_account_index: usize, program_account_index: usize,
account_infos_addr: u64, account_infos_addr: u64,
@ -1120,7 +1123,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
let mut accounts = Vec::with_capacity(account_keys.len()); let mut accounts = Vec::with_capacity(account_keys.len());
let mut refs = Vec::with_capacity(account_keys.len()); let mut refs = Vec::with_capacity(account_keys.len());
'root: for (i, account_key) in account_keys.iter().enumerate() { 'root: for (i, account_key) in account_keys.iter().enumerate() {
if i == program_account_index { if skip_program && i == program_account_index {
// Don't look for caller passed executable, runtime already has it // Don't look for caller passed executable, runtime already has it
continue 'root; continue 'root;
} }
@ -1306,6 +1309,9 @@ fn call<'a>(
.get_compute_meter() .get_compute_meter()
.consume(invoke_context.get_bpf_compute_budget().invoke_units)?; .consume(invoke_context.get_bpf_compute_budget().invoke_units)?;
let use_loaded_program_accounts =
invoke_context.is_feature_active(&use_loaded_program_accounts::id());
// Translate and verify caller's data // Translate and verify caller's data
let instruction = syscall.translate_instruction( let instruction = syscall.translate_instruction(
@ -1328,15 +1334,16 @@ fn call<'a>(
.get_callers_keyed_accounts() .get_callers_keyed_accounts()
.iter() .iter()
.collect::<Vec<&KeyedAccount>>(); .collect::<Vec<&KeyedAccount>>();
let (message, callee_program_id, program_id_index) = let (message, callee_program_id, callee_program_id_index) =
MessageProcessor::create_message(&instruction, &keyed_account_refs, &signers) MessageProcessor::create_message(&instruction, &keyed_account_refs, &signers)
.map_err(SyscallError::InstructionError)?; .map_err(SyscallError::InstructionError)?;
if invoke_context.is_feature_active(&limit_cpi_loader_invoke::id()) { if invoke_context.is_feature_active(&limit_cpi_loader_invoke::id()) {
check_authorized_program(&callee_program_id, &instruction.data)?; check_authorized_program(&callee_program_id, &instruction.data)?;
} }
let (mut accounts, mut account_refs) = syscall.translate_accounts( let (mut accounts, mut account_refs) = syscall.translate_accounts(
use_loaded_program_accounts,
&message.account_keys, &message.account_keys,
program_id_index, callee_program_id_index,
account_infos_addr, account_infos_addr,
account_infos_len as usize, account_infos_len as usize,
ro_regions, ro_regions,
@ -1347,12 +1354,21 @@ fn call<'a>(
invoke_context.record_instruction(&instruction); invoke_context.record_instruction(&instruction);
let program_account = let program_account = if use_loaded_program_accounts {
invoke_context let program_account = invoke_context.get_account(&callee_program_id).ok_or(
.get_account(&callee_program_id) SyscallError::InstructionError(InstructionError::MissingAccount),
)?;
accounts.insert(callee_program_id_index, Rc::new(program_account.clone()));
account_refs.insert(callee_program_id_index, None);
program_account
} else {
(**accounts
.get(callee_program_id_index)
.ok_or(SyscallError::InstructionError( .ok_or(SyscallError::InstructionError(
InstructionError::MissingAccount, InstructionError::MissingAccount,
))?; ))?)
.clone()
};
if !program_account.borrow().executable { if !program_account.borrow().executable {
return Err(SyscallError::InstructionError(InstructionError::AccountNotExecutable).into()); return Err(SyscallError::InstructionError(InstructionError::AccountNotExecutable).into());
} }
@ -1377,8 +1393,6 @@ fn call<'a>(
} else { } else {
None None
}; };
accounts.insert(program_id_index, Rc::new(program_account.clone()));
account_refs.insert(program_id_index, None);
let mut executable_accounts = vec![(callee_program_id, program_account)]; let mut executable_accounts = vec![(callee_program_id, program_account)];
if let Some(programdata) = programdata_executable { if let Some(programdata) = programdata_executable {
executable_accounts.push(programdata); executable_accounts.push(programdata);

View File

@ -546,7 +546,7 @@ impl MessageProcessor {
let _ = keyed_accounts let _ = keyed_accounts
.iter() .iter()
.find_map(|keyed_account| { .find_map(|keyed_account| {
if &instruction.program_id == keyed_account.unsigned_key() { if &program_id == keyed_account.unsigned_key() {
Some(keyed_account) Some(keyed_account)
} else { } else {
None None

View File

@ -122,6 +122,10 @@ pub mod try_find_program_address_syscall_enabled {
solana_sdk::declare_id!("EMsMNadQNhCYDyGpYH5Tx6dGHxiUqKHk782PU5XaWfmi"); solana_sdk::declare_id!("EMsMNadQNhCYDyGpYH5Tx6dGHxiUqKHk782PU5XaWfmi");
} }
pub mod use_loaded_program_accounts {
solana_sdk::declare_id!("FLjgLeg1PJkZimQCVa5sVFtaq6VmSDPw3NvH8iQ3nyHn");
}
lazy_static! { lazy_static! {
/// Map of feature identifiers to user-visible description /// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [ pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -154,6 +158,7 @@ lazy_static! {
(max_cpi_instruction_size_ipv6_mtu::id(), "Max cross-program invocation size 1280"), (max_cpi_instruction_size_ipv6_mtu::id(), "Max cross-program invocation size 1280"),
(limit_cpi_loader_invoke::id(), "Loader not authorized via CPI"), (limit_cpi_loader_invoke::id(), "Loader not authorized via CPI"),
(try_find_program_address_syscall_enabled::id(), "add try_find_program_address syscall"), (try_find_program_address_syscall_enabled::id(), "add try_find_program_address syscall"),
(use_loaded_program_accounts::id(), "Use loaded program accounts"),
/*************** ADD NEW FEATURES HERE ***************/ /*************** ADD NEW FEATURES HERE ***************/
] ]
.iter() .iter()