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::{
limit_cpi_loader_invoke, pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled,
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},
instruction::{AccountMeta, Instruction, InstructionError},
@ -739,6 +739,7 @@ trait SyscallInvokeSigned<'a> {
) -> Result<Instruction, EbpfError<BPFError>>;
fn translate_accounts(
&self,
skip_program: bool,
account_keys: &[Pubkey],
program_account_index: usize,
account_infos_addr: u64,
@ -804,6 +805,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
fn translate_accounts(
&self,
skip_program: bool,
account_keys: &[Pubkey],
program_account_index: usize,
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 refs = Vec::with_capacity(account_keys.len());
'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
continue 'root;
}
@ -1103,6 +1105,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
fn translate_accounts(
&self,
skip_program: bool,
account_keys: &[Pubkey],
program_account_index: usize,
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 refs = Vec::with_capacity(account_keys.len());
'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
continue 'root;
}
@ -1306,6 +1309,9 @@ fn call<'a>(
.get_compute_meter()
.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
let instruction = syscall.translate_instruction(
@ -1328,15 +1334,16 @@ fn call<'a>(
.get_callers_keyed_accounts()
.iter()
.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)
.map_err(SyscallError::InstructionError)?;
if invoke_context.is_feature_active(&limit_cpi_loader_invoke::id()) {
check_authorized_program(&callee_program_id, &instruction.data)?;
}
let (mut accounts, mut account_refs) = syscall.translate_accounts(
use_loaded_program_accounts,
&message.account_keys,
program_id_index,
callee_program_id_index,
account_infos_addr,
account_infos_len as usize,
ro_regions,
@ -1347,12 +1354,21 @@ fn call<'a>(
invoke_context.record_instruction(&instruction);
let program_account =
invoke_context
.get_account(&callee_program_id)
let program_account = if use_loaded_program_accounts {
let program_account = invoke_context.get_account(&callee_program_id).ok_or(
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(
InstructionError::MissingAccount,
))?;
))?)
.clone()
};
if !program_account.borrow().executable {
return Err(SyscallError::InstructionError(InstructionError::AccountNotExecutable).into());
}
@ -1377,8 +1393,6 @@ fn call<'a>(
} else {
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)];
if let Some(programdata) = programdata_executable {
executable_accounts.push(programdata);

View File

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

View File

@ -122,6 +122,10 @@ pub mod try_find_program_address_syscall_enabled {
solana_sdk::declare_id!("EMsMNadQNhCYDyGpYH5Tx6dGHxiUqKHk782PU5XaWfmi");
}
pub mod use_loaded_program_accounts {
solana_sdk::declare_id!("FLjgLeg1PJkZimQCVa5sVFtaq6VmSDPw3NvH8iQ3nyHn");
}
lazy_static! {
/// Map of feature identifiers to user-visible description
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"),
(limit_cpi_loader_invoke::id(), "Loader not authorized via CPI"),
(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 ***************/
]
.iter()