Disable cross-program invocations for OperatingMode::Stable (#11272)

This commit is contained in:
Jack May
2020-07-29 15:29:52 -07:00
committed by GitHub
parent cd043b5d70
commit 2dbed80e48
7 changed files with 56 additions and 3 deletions

View File

@ -160,6 +160,7 @@ pub struct ThisInvokeContext {
pre_accounts: Vec<PreAccount>,
programs: Vec<(Pubkey, ProcessInstruction)>,
logger: Rc<RefCell<dyn Logger>>,
is_cross_program_supported: bool,
}
impl ThisInvokeContext {
const MAX_INVOCATION_DEPTH: usize = 5;
@ -169,6 +170,7 @@ impl ThisInvokeContext {
pre_accounts: Vec<PreAccount>,
programs: Vec<(Pubkey, ProcessInstruction)>,
log_collector: Option<Rc<LogCollector>>,
is_cross_program_supported: bool,
) -> Self {
let mut program_ids = Vec::with_capacity(Self::MAX_INVOCATION_DEPTH);
program_ids.push(*program_id);
@ -178,6 +180,7 @@ impl ThisInvokeContext {
pre_accounts,
programs,
logger: Rc::new(RefCell::new(ThisLogger { log_collector })),
is_cross_program_supported,
}
}
}
@ -225,6 +228,9 @@ impl InvokeContext for ThisInvokeContext {
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
self.logger.clone()
}
fn is_cross_program_supported(&self) -> bool {
self.is_cross_program_supported
}
}
pub struct ThisLogger {
log_collector: Option<Rc<LogCollector>>,
@ -244,7 +250,7 @@ impl Logger for ThisLogger {
pub type ProcessInstructionWithContext =
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
#[derive(Default, Deserialize, Serialize)]
#[derive(Deserialize, Serialize)]
pub struct MessageProcessor {
#[serde(skip)]
programs: Vec<(Pubkey, ProcessInstruction)>,
@ -252,6 +258,18 @@ pub struct MessageProcessor {
loaders: Vec<(Pubkey, ProcessInstructionWithContext)>,
#[serde(skip)]
native_loader: NativeLoader,
#[serde(skip)]
is_cross_program_supported: bool,
}
impl Default for MessageProcessor {
fn default() -> Self {
Self {
programs: vec![],
loaders: vec![],
native_loader: NativeLoader::default(),
is_cross_program_supported: true,
}
}
}
impl Clone for MessageProcessor {
fn clone(&self) -> Self {
@ -259,6 +277,7 @@ impl Clone for MessageProcessor {
programs: self.programs.clone(),
loaders: self.loaders.clone(),
native_loader: NativeLoader::default(),
is_cross_program_supported: self.is_cross_program_supported,
}
}
}
@ -292,6 +311,10 @@ impl MessageProcessor {
}
}
pub fn set_cross_program_support(&mut self, is_supported: bool) {
self.is_cross_program_supported = is_supported;
}
/// Create the KeyedAccounts that will be passed to the program
fn create_keyed_accounts<'a>(
message: &'a Message,
@ -369,6 +392,10 @@ impl MessageProcessor {
accounts: &[Rc<RefCell<Account>>],
invoke_context: &mut dyn InvokeContext,
) -> Result<(), InstructionError> {
if !self.is_cross_program_supported {
return Err(InstructionError::ReentrancyNotAllowed);
}
let instruction = &message.instructions[0];
// Verify the calling program hasn't misbehaved
@ -523,6 +550,7 @@ impl MessageProcessor {
pre_accounts,
self.programs.clone(), // get rid of clone
log_collector,
self.is_cross_program_supported,
);
let keyed_accounts =
Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?;
@ -595,8 +623,14 @@ mod tests {
true,
))
}
let mut invoke_context =
ThisInvokeContext::new(&program_ids[0], Rent::default(), pre_accounts, vec![], None);
let mut invoke_context = ThisInvokeContext::new(
&program_ids[0],
Rent::default(),
pre_accounts,
vec![],
None,
true,
);
// Check call depth increases and has a limit
let mut depth_reached = 1;
@ -1365,6 +1399,7 @@ mod tests {
vec![owned_preaccount, not_owned_preaccount],
vec![],
None,
true,
);
let metas = vec![
AccountMeta::new(owned_key, false),