Gate cpi program account passing (#14443)

This commit is contained in:
Jack May
2021-01-05 13:53:41 -08:00
committed by GitHub
parent 53d65009a0
commit a8b5a32b50
3 changed files with 31 additions and 12 deletions

View File

@ -19,7 +19,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},
@ -851,6 +851,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,
@ -913,6 +914,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,
@ -933,7 +935,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;
} }
@ -1199,6 +1201,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,
@ -1214,7 +1217,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;
} }
@ -1400,6 +1403,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(
@ -1422,15 +1428,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)?; check_authorized_program(&callee_program_id)?;
} }
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, account_infos_len,
memory_mapping, memory_mapping,
@ -1440,12 +1447,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());
} }
@ -1470,8 +1486,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

@ -126,6 +126,10 @@ pub mod limit_cpi_loader_invoke {
solana_sdk::declare_id!("xGbcW7EEC7zMRJ6LaJCob65EJxKryWjwM4rv8f57SRM"); solana_sdk::declare_id!("xGbcW7EEC7zMRJ6LaJCob65EJxKryWjwM4rv8f57SRM");
} }
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> = [
@ -159,6 +163,7 @@ lazy_static! {
(stake_program_v3::id(), "solana_stake_program v3"), (stake_program_v3::id(), "solana_stake_program v3"),
(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"),
(use_loaded_program_accounts::id(), "Use loaded program accounts"),
/*************** ADD NEW FEATURES HERE ***************/ /*************** ADD NEW FEATURES HERE ***************/
] ]
.iter() .iter()