Enforce host aligned memory for program regions (#16590)
This commit is contained in:
parent
8e69dd42c1
commit
08d5253651
|
@ -5471,9 +5471,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14e36c51d5aa290416c5dea3c43ac467cb57c0b643184af23e6bdab7434710fb"
|
||||
checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"combine",
|
||||
|
|
|
@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.7.0" }
|
|||
solana-faucet = { path = "../faucet", version = "=1.7.0" }
|
||||
solana-logger = { path = "../logger", version = "=1.7.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.7"
|
||||
solana_rbpf = "=0.2.8"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.7.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.7.0" }
|
||||
|
|
|
@ -3595,9 +3595,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14e36c51d5aa290416c5dea3c43ac467cb57c0b643184af23e6bdab7434710fb"
|
||||
checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e"
|
||||
dependencies = [
|
||||
"byteorder 1.3.4",
|
||||
"combine",
|
||||
|
|
|
@ -29,7 +29,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.7.0" }
|
|||
solana-cli-output = { path = "../../cli-output", version = "=1.7.0" }
|
||||
solana-logger = { path = "../../logger", version = "=1.7.0" }
|
||||
solana-measure = { path = "../../measure", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.7"
|
||||
solana_rbpf = "=0.2.8"
|
||||
solana-runtime = { path = "../../runtime", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.7.0" }
|
||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.7.0" }
|
||||
|
|
|
@ -75,9 +75,12 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
|
|||
let elf = load_elf("bench_alu").unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ =
|
||||
<dyn Executable::<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
||||
.unwrap();
|
||||
let _ = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -95,7 +98,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||
|
||||
let elf = load_elf("bench_alu").unwrap();
|
||||
let mut executable =
|
||||
<dyn Executable::<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
||||
.unwrap();
|
||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
||||
executable.jit_compile().unwrap();
|
||||
|
@ -223,7 +226,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
|
||||
let elf = load_elf("tuner").unwrap();
|
||||
let mut executable =
|
||||
<dyn Executable::<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
||||
.unwrap();
|
||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
|
@ -231,7 +234,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
&mut serialized,
|
||||
serialized.as_slice_mut(),
|
||||
&mut invoke_context,
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -217,7 +217,7 @@ fn run_program(
|
|||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
&mut parameter_bytes,
|
||||
parameter_bytes.as_slice_mut(),
|
||||
&mut invoke_context,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -256,7 +256,7 @@ fn run_program(
|
|||
deserialize_parameters(
|
||||
&bpf_loader::id(),
|
||||
parameter_accounts,
|
||||
¶meter_bytes,
|
||||
parameter_bytes.as_slice(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -20,7 +20,7 @@ rand_core = "0.6.2"
|
|||
solana-measure = { path = "../../measure", version = "=1.7.0" }
|
||||
solana-runtime = { path = "../../runtime", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.7"
|
||||
solana_rbpf = "=0.2.8"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
use crate::alloc;
|
||||
|
||||
use alloc::{Alloc, AllocErr};
|
||||
use solana_rbpf::aligned_memory::AlignedMemory;
|
||||
use std::alloc::Layout;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BpfAllocator {
|
||||
heap: Vec<u8>,
|
||||
heap: AlignedMemory,
|
||||
start: u64,
|
||||
len: u64,
|
||||
pos: u64,
|
||||
}
|
||||
|
||||
impl BpfAllocator {
|
||||
pub fn new(heap: Vec<u8>, virtual_address: u64) -> Self {
|
||||
pub fn new(heap: AlignedMemory, virtual_address: u64) -> Self {
|
||||
let len = heap.len() as u64;
|
||||
Self {
|
||||
heap,
|
||||
|
|
|
@ -17,7 +17,8 @@ use crate::{
|
|||
use log::{log_enabled, trace, Level::Trace};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_rbpf::{
|
||||
ebpf::MM_HEAP_START,
|
||||
aligned_memory::AlignedMemory,
|
||||
ebpf::{HOST_ALIGN, MM_HEAP_START},
|
||||
error::{EbpfError, UserDefinedError},
|
||||
memory_region::MemoryRegion,
|
||||
vm::{Config, EbpfVm, Executable, InstructionMeter},
|
||||
|
@ -147,8 +148,8 @@ pub fn create_vm<'a>(
|
|||
parameter_bytes: &mut [u8],
|
||||
invoke_context: &'a mut dyn InvokeContext,
|
||||
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
||||
let heap = vec![0_u8; DEFAULT_HEAP_SIZE];
|
||||
let heap_region = MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true);
|
||||
let heap = AlignedMemory::new(DEFAULT_HEAP_SIZE, HOST_ALIGN);
|
||||
let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true);
|
||||
let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?;
|
||||
syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?;
|
||||
Ok(vm)
|
||||
|
@ -759,7 +760,7 @@ impl Executor for BpfExecutor {
|
|||
let mut vm = match create_vm(
|
||||
loader_id,
|
||||
self.executable.as_ref(),
|
||||
&mut parameter_bytes,
|
||||
parameter_bytes.as_slice_mut(),
|
||||
invoke_context,
|
||||
) {
|
||||
Ok(info) => info,
|
||||
|
@ -823,7 +824,7 @@ impl Executor for BpfExecutor {
|
|||
deserialize_parameters(
|
||||
loader_id,
|
||||
keyed_accounts,
|
||||
¶meter_bytes,
|
||||
parameter_bytes.as_slice(),
|
||||
invoke_context.is_feature_active(&skip_ro_deserialization::id()),
|
||||
)?;
|
||||
deserialize_time.stop();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
|
||||
use solana_rbpf::{aligned_memory::AlignedMemory, ebpf::HOST_ALIGN};
|
||||
use solana_sdk::{
|
||||
account::ReadableAccount, bpf_loader_deprecated, entrypoint::MAX_PERMITTED_DATA_INCREASE,
|
||||
instruction::InstructionError, keyed_account::KeyedAccount, pubkey::Pubkey,
|
||||
|
@ -23,7 +24,7 @@ pub fn serialize_parameters(
|
|||
program_id: &Pubkey,
|
||||
keyed_accounts: &[KeyedAccount],
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, InstructionError> {
|
||||
) -> Result<AlignedMemory, InstructionError> {
|
||||
if *loader_id == bpf_loader_deprecated::id() {
|
||||
serialize_parameters_unaligned(program_id, keyed_accounts, data)
|
||||
} else {
|
||||
|
@ -65,7 +66,7 @@ pub fn serialize_parameters_unaligned(
|
|||
program_id: &Pubkey,
|
||||
keyed_accounts: &[KeyedAccount],
|
||||
instruction_data: &[u8],
|
||||
) -> Result<Vec<u8>, InstructionError> {
|
||||
) -> Result<AlignedMemory, InstructionError> {
|
||||
// Calculate size in order to alloc once
|
||||
let mut size = size_of::<u64>();
|
||||
for (i, keyed_account) in keyed_accounts.iter().enumerate() {
|
||||
|
@ -78,7 +79,7 @@ pub fn serialize_parameters_unaligned(
|
|||
size += size_of::<u64>() // instruction data len
|
||||
+ instruction_data.len() // instruction data
|
||||
+ size_of::<Pubkey>(); // program id
|
||||
let mut v: Vec<u8> = Vec::with_capacity(size);
|
||||
let mut v = AlignedMemory::new(size, HOST_ALIGN);
|
||||
|
||||
v.write_u64::<LittleEndian>(keyed_accounts.len() as u64)
|
||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
|
@ -177,7 +178,7 @@ pub fn serialize_parameters_aligned(
|
|||
program_id: &Pubkey,
|
||||
keyed_accounts: &[KeyedAccount],
|
||||
instruction_data: &[u8],
|
||||
) -> Result<Vec<u8>, InstructionError> {
|
||||
) -> Result<AlignedMemory, InstructionError> {
|
||||
// Calculate size in order to alloc once
|
||||
let mut size = size_of::<u64>();
|
||||
for (i, keyed_account) in keyed_accounts.iter().enumerate() {
|
||||
|
@ -192,14 +193,11 @@ pub fn serialize_parameters_aligned(
|
|||
size += size_of::<u64>() // data len
|
||||
+ instruction_data.len()
|
||||
+ size_of::<Pubkey>(); // program id;
|
||||
let mut v: Vec<u8> = Vec::with_capacity(size);
|
||||
let mut v = AlignedMemory::new(size, HOST_ALIGN);
|
||||
|
||||
// Serialize into the buffer
|
||||
v.write_u64::<LittleEndian>(keyed_accounts.len() as u64)
|
||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
if v.as_ptr().align_offset(align_of::<u128>()) != 0 {
|
||||
panic!();
|
||||
}
|
||||
for (i, keyed_account) in keyed_accounts.iter().enumerate() {
|
||||
let (is_dup, position) = is_dup(&keyed_accounts[..i], keyed_account);
|
||||
if is_dup {
|
||||
|
@ -228,12 +226,12 @@ pub fn serialize_parameters_aligned(
|
|||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
v.write_all(&keyed_account.try_account_ref()?.data())
|
||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
v.resize(
|
||||
v.len()
|
||||
+ MAX_PERMITTED_DATA_INCREASE
|
||||
+ (v.len() as *const u8).align_offset(align_of::<u128>()),
|
||||
v.fill(
|
||||
MAX_PERMITTED_DATA_INCREASE
|
||||
+ (v.write_index() as *const u8).align_offset(align_of::<u128>()),
|
||||
0,
|
||||
);
|
||||
)
|
||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
v.write_u64::<LittleEndian>(keyed_account.rent_epoch()? as u64)
|
||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
}
|
||||
|
@ -410,7 +408,8 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let (de_program_id, de_accounts, de_instruction_data) =
|
||||
unsafe { deserialize(&mut serialized[0] as *mut u8) };
|
||||
unsafe { deserialize(&mut serialized.as_slice_mut()[0] as *mut u8) };
|
||||
|
||||
assert_eq!(&program_id, de_program_id);
|
||||
assert_eq!(instruction_data, de_instruction_data);
|
||||
assert_eq!(
|
||||
|
@ -453,7 +452,13 @@ mod tests {
|
|||
}
|
||||
})
|
||||
.collect();
|
||||
deserialize_parameters(&bpf_loader::id(), &de_keyed_accounts, &serialized, true).unwrap();
|
||||
deserialize_parameters(
|
||||
&bpf_loader::id(),
|
||||
&de_keyed_accounts,
|
||||
serialized.as_slice(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
for ((account, de_keyed_account), key) in
|
||||
accounts.iter().zip(de_keyed_accounts).zip(keys.clone())
|
||||
{
|
||||
|
@ -480,7 +485,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let (de_program_id, de_accounts, de_instruction_data) =
|
||||
unsafe { deserialize_unaligned(&mut serialized[0] as *mut u8) };
|
||||
unsafe { deserialize_unaligned(&mut serialized.as_slice_mut()[0] as *mut u8) };
|
||||
assert_eq!(&program_id, de_program_id);
|
||||
assert_eq!(instruction_data, de_instruction_data);
|
||||
for ((account, account_info), key) in accounts.iter().zip(de_accounts).zip(keys.clone()) {
|
||||
|
@ -509,7 +514,7 @@ mod tests {
|
|||
deserialize_parameters(
|
||||
&bpf_loader_deprecated::id(),
|
||||
&de_keyed_accounts,
|
||||
&serialized,
|
||||
serialized.as_slice(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -135,6 +135,10 @@ pub mod check_duplicates_by_hash {
|
|||
solana_sdk::declare_id!("8ZqTSYHgzyaYCcXJPMViRy6afCFSgNvYooPDeVdyj5GC");
|
||||
}
|
||||
|
||||
pub mod enforce_aligned_host_addrs {
|
||||
solana_sdk::declare_id!("6Qob9Z4RwGdf599FDVCqsjuKjR8ZFR3oVs2ByRLWBsua");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -156,8 +160,8 @@ lazy_static! {
|
|||
(turbine_retransmit_peers_patch::id(), "turbine retransmit peers patch #14631"),
|
||||
(require_custodian_for_locked_stake_authorize::id(), "require custodian to authorize withdrawer change for locked stake"),
|
||||
(spl_token_v2_self_transfer_fix::id(), "spl-token self-transfer fix"),
|
||||
(full_inflation::mainnet::certusone::enable::id(), "Full inflation enabled by Certus One"),
|
||||
(full_inflation::mainnet::certusone::vote::id(), "Community vote allowing Certus One to enable full inflation"),
|
||||
(full_inflation::mainnet::certusone::enable::id(), "full inflation enabled by Certus One"),
|
||||
(full_inflation::mainnet::certusone::vote::id(), "community vote allowing Certus One to enable full inflation"),
|
||||
(warp_timestamp_again::id(), "warp timestamp again, adjust bounding to 25% fast 80% slow #15204"),
|
||||
(check_init_vote_data::id(), "check initialized Vote data"),
|
||||
(check_program_owner::id(), "limit programs to operating on accounts owned by itself"),
|
||||
|
@ -167,8 +171,9 @@ lazy_static! {
|
|||
(cpi_data_cost::id(), "charge the compute budget for data passed via CPI"),
|
||||
(upgradeable_close_instruction::id(), "close upgradeable buffer accounts"),
|
||||
(demote_sysvar_write_locks::id(), "demote builtins and sysvar write locks to readonly #15497"),
|
||||
(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"),
|
||||
(enforce_aligned_host_addrs::id(), "enforce aligned host addresses"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
|
Loading…
Reference in New Issue