Retain alloc'd and updated data in cpi (backport #16850) (#16890)

* Retain alloc'd and updated data in cpi (#16850)

(cherry picked from commit 9b3a59f030)

# Conflicts:
#	programs/bpf_loader/src/syscalls.rs
#	sdk/src/feature_set.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
This commit is contained in:
mergify[bot]
2021-04-27 23:01:43 +00:00
committed by GitHub
parent 4a3f851e49
commit dbc58455df
6 changed files with 100 additions and 9 deletions

View File

@ -374,6 +374,32 @@ fn process_instruction(
accounts[INVOKED_ARGUMENT_INDEX].data.borrow_mut()[..NUM_BYTES] accounts[INVOKED_ARGUMENT_INDEX].data.borrow_mut()[..NUM_BYTES]
); );
} }
msg!("Create account and init data");
{
let from_lamports = accounts[FROM_INDEX].lamports();
let to_lamports = accounts[DERIVED_KEY2_INDEX].lamports();
let instruction = create_instruction(
*accounts[INVOKED_PROGRAM_INDEX].key,
&[
(accounts[FROM_INDEX].key, true, true),
(accounts[DERIVED_KEY2_INDEX].key, true, false),
(accounts[SYSTEM_PROGRAM_INDEX].key, false, false),
],
vec![CREATE_AND_INIT, bump_seed2],
);
invoke(&instruction, accounts)?;
assert_eq!(accounts[FROM_INDEX].lamports(), from_lamports - 1);
assert_eq!(accounts[DERIVED_KEY2_INDEX].lamports(), to_lamports + 1);
let data = accounts[DERIVED_KEY2_INDEX].try_borrow_mut_data()?;
assert_eq!(data[0], 0x0e);
assert_eq!(data[MAX_PERMITTED_DATA_INCREASE - 1], 0x0f);
for i in 1..20 {
assert_eq!(data[i], i as u8);
}
}
} }
TEST_PRIVILEGE_ESCALATION_SIGNER => { TEST_PRIVILEGE_ESCALATION_SIGNER => {
msg!("Test privilege escalation signer"); msg!("Test privilege escalation signer");

View File

@ -17,6 +17,7 @@ pub const VERIFY_PRIVILEGE_DEESCALATION: u8 = 8;
pub const VERIFY_PRIVILEGE_DEESCALATION_ESCALATION_SIGNER: u8 = 9; pub const VERIFY_PRIVILEGE_DEESCALATION_ESCALATION_SIGNER: u8 = 9;
pub const VERIFY_PRIVILEGE_DEESCALATION_ESCALATION_WRITABLE: u8 = 10; pub const VERIFY_PRIVILEGE_DEESCALATION_ESCALATION_WRITABLE: u8 = 10;
pub const WRITE_ACCOUNT: u8 = 11; pub const WRITE_ACCOUNT: u8 = 11;
pub const CREATE_AND_INIT: u8 = 12;
pub fn create_instruction( pub fn create_instruction(
program_id: Pubkey, program_id: Pubkey,

View File

@ -6,11 +6,12 @@ use crate::instruction::*;
use solana_program::{ use solana_program::{
account_info::AccountInfo, account_info::AccountInfo,
bpf_loader, entrypoint, bpf_loader, entrypoint,
entrypoint::ProgramResult, entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE},
msg, msg,
program::{invoke, invoke_signed}, program::{invoke, invoke_signed},
program_error::ProgramError, program_error::ProgramError,
pubkey::Pubkey, pubkey::Pubkey,
system_instruction,
}; };
entrypoint!(process_instruction); entrypoint!(process_instruction);
@ -236,6 +237,52 @@ fn process_instruction(
accounts[ARGUMENT_INDEX].data.borrow_mut()[i as usize] = instruction_data[1]; accounts[ARGUMENT_INDEX].data.borrow_mut()[i as usize] = instruction_data[1];
} }
} }
CREATE_AND_INIT => {
msg!("Create and init data");
{
const FROM_INDEX: usize = 0;
const DERIVED_KEY2_INDEX: usize = 1;
let from_lamports = accounts[FROM_INDEX].lamports();
let to_lamports = accounts[DERIVED_KEY2_INDEX].lamports();
assert_eq!(accounts[DERIVED_KEY2_INDEX].data_len(), 0);
assert!(solana_program::system_program::check_id(
accounts[DERIVED_KEY2_INDEX].owner
));
let bump_seed2 = instruction_data[1];
let instruction = system_instruction::create_account(
accounts[FROM_INDEX].key,
accounts[DERIVED_KEY2_INDEX].key,
1,
MAX_PERMITTED_DATA_INCREASE as u64,
program_id,
);
invoke_signed(
&instruction,
accounts,
&[&[b"Lil'", b"Bits", &[bump_seed2]]],
)?;
assert_eq!(accounts[FROM_INDEX].lamports(), from_lamports - 1);
assert_eq!(accounts[DERIVED_KEY2_INDEX].lamports(), to_lamports + 1);
assert_eq!(program_id, accounts[DERIVED_KEY2_INDEX].owner);
assert_eq!(
accounts[DERIVED_KEY2_INDEX].data_len(),
MAX_PERMITTED_DATA_INCREASE
);
let mut data = accounts[DERIVED_KEY2_INDEX].try_borrow_mut_data()?;
assert_eq!(data[0], 0);
data[0] = 0x0e;
assert_eq!(data[0], 0x0e);
assert_eq!(data[MAX_PERMITTED_DATA_INCREASE - 1], 0);
data[MAX_PERMITTED_DATA_INCREASE - 1] = 0x0f;
assert_eq!(data[MAX_PERMITTED_DATA_INCREASE - 1], 0x0f);
for i in 1..20 {
data[i] = i as u8;
}
}
}
_ => panic!(), _ => panic!(),
} }

View File

@ -884,6 +884,8 @@ fn test_program_bpf_invoke_sanity() {
invoked_program_id.clone(), invoked_program_id.clone(),
invoked_program_id.clone(), invoked_program_id.clone(),
invoked_program_id.clone(), invoked_program_id.clone(),
invoked_program_id.clone(),
solana_sdk::system_program::id(),
], ],
}; };
assert_eq!(invoked_programs.len(), expected_invoked_programs.len()); assert_eq!(invoked_programs.len(), expected_invoked_programs.len());

View File

@ -20,7 +20,7 @@ use solana_sdk::{
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
feature_set::{ feature_set::{
cpi_data_cost, cpi_share_ro_and_exec_accounts, demote_sysvar_write_locks, cpi_data_cost, cpi_share_ro_and_exec_accounts, demote_sysvar_write_locks,
enforce_aligned_host_addrs, sysvar_via_syscall, enforce_aligned_host_addrs, sysvar_via_syscall, update_data_on_realloc,
}, },
hash::{Hasher, HASH_BYTES}, hash::{Hasher, HASH_BYTES},
ic_msg, ic_msg,
@ -1997,7 +1997,7 @@ fn call<'a>(
let invoke_context = syscall.get_context()?; let invoke_context = syscall.get_context()?;
for (i, (account, account_ref)) in accounts.iter().zip(account_refs).enumerate() { for (i, (account, account_ref)) in accounts.iter().zip(account_refs).enumerate() {
let account = account.borrow(); let account = account.borrow();
if let Some(account_ref) = account_ref { if let Some(mut account_ref) = account_ref {
if message.is_writable(i, demote_sysvar_write_locks) && !account.executable { if message.is_writable(i, demote_sysvar_write_locks) && !account.executable {
*account_ref.lamports = account.lamports; *account_ref.lamports = account.lamports;
*account_ref.owner = account.owner; *account_ref.owner = account.owner;
@ -2027,12 +2027,22 @@ fn call<'a>(
) )
.into()); .into());
} }
let _ = translate( if invoke_context.is_feature_active(&update_data_on_realloc::id()) {
memory_mapping, account_ref.data = translate_slice_mut::<u8>(
AccessType::Store, memory_mapping,
account_ref.vm_data_addr, account_ref.vm_data_addr,
account.data().len() as u64, account.data().len() as u64,
)?; &bpf_loader_deprecated::id(), // Don't care since it is byte aligned
true,
)?;
} else {
let _ = translate(
memory_mapping,
AccessType::Store,
account_ref.vm_data_addr,
account.data().len() as u64,
)?;
}
*account_ref.ref_to_len_in_vm = account.data().len() as u64; *account_ref.ref_to_len_in_vm = account.data().len() as u64;
*account_ref.serialized_len_ptr = account.data().len() as u64; *account_ref.serialized_len_ptr = account.data().len() as u64;
} }

View File

@ -127,6 +127,10 @@ pub mod enforce_aligned_host_addrs {
solana_sdk::declare_id!("6Qob9Z4RwGdf599FDVCqsjuKjR8ZFR3oVs2ByRLWBsua"); solana_sdk::declare_id!("6Qob9Z4RwGdf599FDVCqsjuKjR8ZFR3oVs2ByRLWBsua");
} }
pub mod update_data_on_realloc {
solana_sdk::declare_id!("BkPcYCrwHXBoTsv9vMhiRF9gteZmDj3Uwisz9CDjoMKp");
}
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! {
(sysvar_via_syscall::id(), "provide sysvars via syscalls"), (sysvar_via_syscall::id(), "provide sysvars via syscalls"),
(check_duplicates_by_hash::id(), "use transaction message hash for duplicate check"), (check_duplicates_by_hash::id(), "use transaction message hash for duplicate check"),
(enforce_aligned_host_addrs::id(), "enforce aligned host addresses"), (enforce_aligned_host_addrs::id(), "enforce aligned host addresses"),
(update_data_on_realloc::id(), "Retain updated data values modified after realloc via CPI"),
/*************** ADD NEW FEATURES HERE ***************/ /*************** ADD NEW FEATURES HERE ***************/
] ]
.iter() .iter()