Disallow deployment of deprecated _sol_alloc_free syscall (#25179)
This commit is contained in:
parent
2fdc850176
commit
851958f77a
|
@ -2071,7 +2071,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
||||||
reject_broken_elfs: true,
|
reject_broken_elfs: true,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
},
|
},
|
||||||
register_syscalls(&mut invoke_context).unwrap(),
|
register_syscalls(&mut invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.map_err(|err| format!("ELF error: {}", err))?;
|
.map_err(|err| format!("ELF error: {}", err))?;
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
||||||
|
@ -224,7 +224,7 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
|
|
|
@ -9,7 +9,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||||
// Confirm large allocation fails
|
// Confirm large allocation fails
|
||||||
void *ptr = sol_calloc(1, UINT64_MAX);
|
void *ptr = sol_calloc(1, UINT64_MAX);
|
||||||
if (ptr != NULL) {
|
if (ptr != NULL) {
|
||||||
sol_log("Error: Alloc of very larger buffer should fail");
|
sol_log("Error: Alloc of very large type should fail");
|
||||||
sol_panic();
|
sol_panic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||||
// Confirm large allocation fails
|
// Confirm large allocation fails
|
||||||
void *ptr = sol_calloc(UINT64_MAX, 1);
|
void *ptr = sol_calloc(UINT64_MAX, 1);
|
||||||
if (ptr != NULL) {
|
if (ptr != NULL) {
|
||||||
sol_log("Error: Alloc of very larger buffer should fail");
|
sol_log("Error: Alloc of very large number of items should fail");
|
||||||
sol_panic();
|
sol_panic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,16 +42,37 @@ extern uint64_t entrypoint(const uint8_t *input) {
|
||||||
sol_log("Error: Alloc failed");
|
sol_log("Error: Alloc failed");
|
||||||
sol_panic();
|
sol_panic();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < iters; i++) {
|
for (uint64_t i = 0; i < iters; i++) {
|
||||||
*(ptr + i) = i;
|
*(ptr + i) = i;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < iters; i++) {
|
for (uint64_t i = 0; i < iters; i++) {
|
||||||
sol_assert(*(ptr + i) == i);
|
sol_assert(*(ptr + i) == i);
|
||||||
}
|
}
|
||||||
sol_log_64(0x3, 0, 0, 0, *(ptr + 42));
|
|
||||||
sol_assert(*(ptr + 42) == 42);
|
sol_assert(*(ptr + 42) == 42);
|
||||||
sol_free(ptr);
|
sol_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alloc to exhaustion
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < 31; i++) {
|
||||||
|
uint8_t *ptr = sol_calloc(1024, 1);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
sol_log("large alloc failed");
|
||||||
|
sol_panic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint64_t i = 0; i < 760; i++) {
|
||||||
|
uint8_t *ptr = sol_calloc(1, 1);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
sol_log("small alloc failed");
|
||||||
|
sol_panic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t *ptr = sol_calloc(1, 1);
|
||||||
|
if (ptr != NULL) {
|
||||||
|
sol_log("final alloc did not fail");
|
||||||
|
sol_panic();
|
||||||
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Example Rust-based BPF program tests loop iteration
|
//! Example Rust-based BPF program tests loop iteration
|
||||||
|
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use solana_program::{custom_panic_default, entrypoint::SUCCESS};
|
use solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
|
@ -50,6 +50,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use {
|
use {
|
||||||
solana_program::{custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg},
|
solana_program::{
|
||||||
|
custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg,
|
||||||
|
},
|
||||||
std::{alloc::Layout, mem},
|
std::{alloc::Layout, mem},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +85,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Example Rust-based BPF program that tests call depth and stack usage
|
//! Example Rust-based BPF program that tests call depth and stack usage
|
||||||
|
|
||||||
use solana_program::{custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg};
|
use solana_program::{
|
||||||
|
custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg,
|
||||||
|
};
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn recurse(data: &mut [u8]) {
|
pub fn recurse(data: &mut [u8]) {
|
||||||
|
@ -26,4 +28,5 @@ pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use solana_program::{
|
use solana_program::{
|
||||||
account_info::AccountInfo,
|
account_info::AccountInfo,
|
||||||
|
custom_heap_default,
|
||||||
entrypoint_deprecated::ProgramResult,
|
entrypoint_deprecated::ProgramResult,
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
msg,
|
msg,
|
||||||
|
@ -9,12 +10,6 @@ use solana_program::{
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
fn custom_panic(info: &core::panic::PanicInfo<'_>) {
|
|
||||||
// Full panic reporting
|
|
||||||
msg!(&format!("{}", info));
|
|
||||||
}
|
|
||||||
|
|
||||||
solana_program::entrypoint_deprecated!(process_instruction);
|
solana_program::entrypoint_deprecated!(process_instruction);
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
fn process_instruction(
|
fn process_instruction(
|
||||||
|
@ -39,3 +34,11 @@ fn process_instruction(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn custom_panic(info: &core::panic::PanicInfo<'_>) {
|
||||||
|
// Full panic reporting
|
||||||
|
msg!(&format!("{}", info));
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//! Example Rust-based BPF program tests loop iteration
|
//! Example Rust-based BPF program tests loop iteration
|
||||||
|
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use solana_program::{custom_panic_default, entrypoint::SUCCESS, log::sol_log_64};
|
use solana_program::{
|
||||||
|
custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64,
|
||||||
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
|
@ -18,6 +20,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
mod helper;
|
mod helper;
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use solana_program::{custom_panic_default, entrypoint::SUCCESS, msg};
|
use solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS, msg};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
|
@ -26,6 +26,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
extern crate compiler_builtins;
|
extern crate compiler_builtins;
|
||||||
use {
|
use {
|
||||||
solana_bpf_rust_mem::{run_mem_tests, MemOps},
|
solana_bpf_rust_mem::{run_mem_tests, MemOps},
|
||||||
solana_program::{custom_panic_default, entrypoint::SUCCESS},
|
solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -38,4 +38,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use {
|
use {
|
||||||
solana_bpf_rust_param_passing_dep::{Data, TestDep},
|
solana_bpf_rust_param_passing_dep::{Data, TestDep},
|
||||||
solana_program::{custom_panic_default, entrypoint::SUCCESS, log::sol_log_64},
|
solana_program::{
|
||||||
|
custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -25,6 +27,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Secp256k1Recover Syscall test
|
//! Secp256k1Recover Syscall test
|
||||||
|
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use solana_program::{custom_panic_default, msg};
|
use solana_program::{custom_heap_default, custom_panic_default, msg};
|
||||||
|
|
||||||
fn test_secp256k1_recover() {
|
fn test_secp256k1_recover() {
|
||||||
use solana_program::secp256k1_recover::secp256k1_recover;
|
use solana_program::secp256k1_recover::secp256k1_recover;
|
||||||
|
@ -41,4 +41,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! SHA Syscall test
|
//! SHA Syscall test
|
||||||
|
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use solana_program::{custom_panic_default, msg};
|
use solana_program::{custom_heap_default, custom_panic_default, msg};
|
||||||
|
|
||||||
fn test_sha256_hasher() {
|
fn test_sha256_hasher() {
|
||||||
use solana_program::hash::{hashv, Hasher};
|
use solana_program::hash::{hashv, Hasher};
|
||||||
|
@ -39,6 +39,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
extern crate solana_program;
|
extern crate solana_program;
|
||||||
use {
|
use {
|
||||||
solana_program::{custom_panic_default, msg},
|
solana_program::{custom_heap_default, custom_panic_default, msg},
|
||||||
solana_zk_token_sdk::zk_token_elgamal::{
|
solana_zk_token_sdk::zk_token_elgamal::{
|
||||||
ops,
|
ops,
|
||||||
pod::{ElGamalCiphertext, Zeroable},
|
pod::{ElGamalCiphertext, Zeroable},
|
||||||
|
@ -50,4 +50,5 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_heap_default!();
|
||||||
custom_panic_default!();
|
custom_panic_default!();
|
||||||
|
|
|
@ -40,7 +40,7 @@ use {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::{AccountSharedData, ReadableAccount},
|
account::{AccountSharedData, ReadableAccount, WritableAccount},
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
|
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
|
||||||
client::SyncClient,
|
client::SyncClient,
|
||||||
|
@ -226,7 +226,7 @@ fn run_program(name: &str) -> u64 {
|
||||||
&data,
|
&data,
|
||||||
None,
|
None,
|
||||||
config,
|
config,
|
||||||
register_syscalls(invoke_context).unwrap(),
|
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
|
||||||
|
@ -565,6 +565,10 @@ fn test_program_bpf_loader_deprecated() {
|
||||||
.accounts
|
.accounts
|
||||||
.remove(&solana_sdk::feature_set::disable_deprecated_loader::id())
|
.remove(&solana_sdk::feature_set::disable_deprecated_loader::id())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
genesis_config
|
||||||
|
.accounts
|
||||||
|
.remove(&solana_sdk::feature_set::disable_deploy_of_alloc_free_syscall::id())
|
||||||
|
.unwrap();
|
||||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||||
let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!();
|
let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!();
|
||||||
bank.add_builtin(&name, &id, entrypoint);
|
bank.add_builtin(&name, &id, entrypoint);
|
||||||
|
@ -583,6 +587,91 @@ fn test_program_bpf_loader_deprecated() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sol_alloc_free_no_longer_deployable() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let program_keypair = Keypair::new();
|
||||||
|
let program_address = program_keypair.pubkey();
|
||||||
|
let loader_address = bpf_loader_deprecated::id();
|
||||||
|
|
||||||
|
let GenesisConfigInfo {
|
||||||
|
genesis_config,
|
||||||
|
mint_keypair,
|
||||||
|
..
|
||||||
|
} = create_genesis_config(50);
|
||||||
|
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||||
|
|
||||||
|
bank.deactivate_feature(&solana_sdk::feature_set::disable_deprecated_loader::id());
|
||||||
|
let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!();
|
||||||
|
bank.add_builtin(&name, &id, entrypoint);
|
||||||
|
|
||||||
|
// Populate loader account with elf that depends on _sol_alloc_free syscall
|
||||||
|
let elf = read_bpf_program("solana_bpf_rust_deprecated_loader");
|
||||||
|
let mut program_account = AccountSharedData::new(1, elf.len(), &loader_address);
|
||||||
|
program_account
|
||||||
|
.data_as_mut_slice()
|
||||||
|
.get_mut(..)
|
||||||
|
.unwrap()
|
||||||
|
.copy_from_slice(&elf);
|
||||||
|
bank.store_account(&program_address, &program_account);
|
||||||
|
|
||||||
|
let finalize_tx = Transaction::new(
|
||||||
|
&[&mint_keypair, &program_keypair],
|
||||||
|
Message::new(
|
||||||
|
&[loader_instruction::finalize(
|
||||||
|
&program_keypair.pubkey(),
|
||||||
|
&loader_address,
|
||||||
|
)],
|
||||||
|
Some(&mint_keypair.pubkey()),
|
||||||
|
),
|
||||||
|
bank.last_blockhash(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let invoke_tx = Transaction::new(
|
||||||
|
&[&mint_keypair],
|
||||||
|
Message::new(
|
||||||
|
&[Instruction::new_with_bytes(
|
||||||
|
program_address,
|
||||||
|
&[1],
|
||||||
|
vec![AccountMeta::new(mint_keypair.pubkey(), true)],
|
||||||
|
)],
|
||||||
|
Some(&mint_keypair.pubkey()),
|
||||||
|
),
|
||||||
|
bank.last_blockhash(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try and deploy a program that depends on _sol_alloc_free
|
||||||
|
assert_eq!(
|
||||||
|
bank.process_transaction(&finalize_tx).unwrap_err(),
|
||||||
|
TransactionError::InstructionError(0, InstructionError::InvalidAccountData)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Enable _sol_alloc_free syscall
|
||||||
|
bank.deactivate_feature(&solana_sdk::feature_set::disable_deploy_of_alloc_free_syscall::id());
|
||||||
|
bank.clear_signatures();
|
||||||
|
bank.clear_executors();
|
||||||
|
|
||||||
|
// Try and finalize the program now that sol_alloc_free is re-enabled
|
||||||
|
assert!(bank.process_transaction(&finalize_tx).is_ok());
|
||||||
|
|
||||||
|
// invoke the program
|
||||||
|
assert!(bank.process_transaction(&invoke_tx).is_ok());
|
||||||
|
|
||||||
|
// disable _sol_alloc_free
|
||||||
|
bank.activate_feature(&solana_sdk::feature_set::disable_deploy_of_alloc_free_syscall::id());
|
||||||
|
bank.clear_signatures();
|
||||||
|
|
||||||
|
// invoke should still succeed because cached
|
||||||
|
assert!(bank.process_transaction(&invoke_tx).is_ok());
|
||||||
|
|
||||||
|
bank.clear_signatures();
|
||||||
|
bank.clear_executors();
|
||||||
|
|
||||||
|
// invoke should still succeed on execute because the program is already deployed
|
||||||
|
assert!(bank.process_transaction(&invoke_tx).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_program_bpf_duplicate_accounts() {
|
fn test_program_bpf_duplicate_accounts() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
@ -1439,7 +1528,7 @@ fn assert_instruction_count() {
|
||||||
{
|
{
|
||||||
programs.extend_from_slice(&[
|
programs.extend_from_slice(&[
|
||||||
("solana_bpf_rust_128bit", 584),
|
("solana_bpf_rust_128bit", 584),
|
||||||
("solana_bpf_rust_alloc", 4459),
|
("solana_bpf_rust_alloc", 4581),
|
||||||
("solana_bpf_rust_custom_heap", 469),
|
("solana_bpf_rust_custom_heap", 469),
|
||||||
("solana_bpf_rust_dep_crate", 2),
|
("solana_bpf_rust_dep_crate", 2),
|
||||||
("solana_bpf_rust_external_spend", 338),
|
("solana_bpf_rust_external_spend", 338),
|
||||||
|
@ -1452,7 +1541,7 @@ fn assert_instruction_count() {
|
||||||
("solana_bpf_rust_rand", 429),
|
("solana_bpf_rust_rand", 429),
|
||||||
("solana_bpf_rust_sanity", 52290),
|
("solana_bpf_rust_sanity", 52290),
|
||||||
("solana_bpf_rust_secp256k1_recover", 25707),
|
("solana_bpf_rust_secp256k1_recover", 25707),
|
||||||
("solana_bpf_rust_sha", 25251),
|
("solana_bpf_rust_sha", 25265),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,10 @@ use {
|
||||||
entrypoint::{HEAP_LENGTH, SUCCESS},
|
entrypoint::{HEAP_LENGTH, SUCCESS},
|
||||||
feature_set::{
|
feature_set::{
|
||||||
cap_accounts_data_len, disable_bpf_deprecated_load_instructions,
|
cap_accounts_data_len, disable_bpf_deprecated_load_instructions,
|
||||||
disable_bpf_unresolved_symbols_at_runtime, disable_deprecated_loader,
|
disable_bpf_unresolved_symbols_at_runtime, disable_deploy_of_alloc_free_syscall,
|
||||||
do_support_realloc, error_on_syscall_bpf_function_hash_collisions,
|
disable_deprecated_loader, do_support_realloc,
|
||||||
reduce_required_deploy_balance, reject_callx_r10, requestable_heap_size,
|
error_on_syscall_bpf_function_hash_collisions, reduce_required_deploy_balance,
|
||||||
|
reject_callx_r10, requestable_heap_size,
|
||||||
},
|
},
|
||||||
instruction::{AccountMeta, InstructionError},
|
instruction::{AccountMeta, InstructionError},
|
||||||
loader_instruction::LoaderInstruction,
|
loader_instruction::LoaderInstruction,
|
||||||
|
@ -109,9 +110,11 @@ pub fn create_executor(
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
use_jit: bool,
|
use_jit: bool,
|
||||||
reject_deployment_of_broken_elfs: bool,
|
reject_deployment_of_broken_elfs: bool,
|
||||||
|
disable_deploy_of_alloc_free_syscall: bool,
|
||||||
) -> Result<Arc<BpfExecutor>, InstructionError> {
|
) -> Result<Arc<BpfExecutor>, InstructionError> {
|
||||||
let mut register_syscalls_time = Measure::start("register_syscalls_time");
|
let mut register_syscalls_time = Measure::start("register_syscalls_time");
|
||||||
let register_syscall_result = syscalls::register_syscalls(invoke_context);
|
let register_syscall_result =
|
||||||
|
syscalls::register_syscalls(invoke_context, disable_deploy_of_alloc_free_syscall);
|
||||||
register_syscalls_time.stop();
|
register_syscalls_time.stop();
|
||||||
invoke_context.timings.create_executor_register_syscalls_us = invoke_context
|
invoke_context.timings.create_executor_register_syscalls_us = invoke_context
|
||||||
.timings
|
.timings
|
||||||
|
@ -383,7 +386,9 @@ fn process_instruction_common(
|
||||||
program_data_offset,
|
program_data_offset,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
use_jit,
|
use_jit,
|
||||||
false,
|
false, /* reject_deployment_of_broken_elfs */
|
||||||
|
// allow _sol_alloc_free syscall for execution
|
||||||
|
false, /* disable_sol_alloc_free_syscall */
|
||||||
)?;
|
)?;
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
|
@ -627,6 +632,9 @@ fn process_loader_upgradeable_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
use_jit,
|
use_jit,
|
||||||
true,
|
true,
|
||||||
|
invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&disable_deploy_of_alloc_free_syscall::id()),
|
||||||
)?;
|
)?;
|
||||||
invoke_context.update_executor(&new_program_id, executor);
|
invoke_context.update_executor(&new_program_id, executor);
|
||||||
|
|
||||||
|
@ -806,6 +814,9 @@ fn process_loader_upgradeable_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
use_jit,
|
use_jit,
|
||||||
true,
|
true,
|
||||||
|
invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&disable_deploy_of_alloc_free_syscall::id()),
|
||||||
)?;
|
)?;
|
||||||
invoke_context.update_executor(&new_program_id, executor);
|
invoke_context.update_executor(&new_program_id, executor);
|
||||||
|
|
||||||
|
@ -1101,8 +1112,16 @@ fn process_loader_instruction(
|
||||||
ic_msg!(invoke_context, "key[0] did not sign the transaction");
|
ic_msg!(invoke_context, "key[0] did not sign the transaction");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let executor =
|
let executor = create_executor(
|
||||||
create_executor(first_instruction_account, 0, invoke_context, use_jit, true)?;
|
first_instruction_account,
|
||||||
|
0,
|
||||||
|
invoke_context,
|
||||||
|
use_jit,
|
||||||
|
true,
|
||||||
|
invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&disable_deploy_of_alloc_free_syscall::id()),
|
||||||
|
)?;
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let mut program =
|
let mut program =
|
||||||
|
|
|
@ -128,6 +128,7 @@ macro_rules! register_feature_gated_syscall {
|
||||||
|
|
||||||
pub fn register_syscalls(
|
pub fn register_syscalls(
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
|
disable_deploy_of_alloc_free_syscall: bool,
|
||||||
) -> Result<SyscallRegistry, EbpfError<BpfError>> {
|
) -> Result<SyscallRegistry, EbpfError<BpfError>> {
|
||||||
let secp256k1_recover_syscall_enabled = invoke_context
|
let secp256k1_recover_syscall_enabled = invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
|
@ -328,7 +329,9 @@ pub fn register_syscalls(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Memory allocator
|
// Memory allocator
|
||||||
syscall_registry.register_syscall_by_name(
|
register_feature_gated_syscall!(
|
||||||
|
syscall_registry,
|
||||||
|
!disable_deploy_of_alloc_free_syscall,
|
||||||
b"sol_alloc_free_",
|
b"sol_alloc_free_",
|
||||||
SyscallAllocFree::init,
|
SyscallAllocFree::init,
|
||||||
SyscallAllocFree::call,
|
SyscallAllocFree::call,
|
||||||
|
|
|
@ -270,7 +270,7 @@ native machine code before execting it in the virtual machine.",
|
||||||
file.seek(SeekFrom::Start(0)).unwrap();
|
file.seek(SeekFrom::Start(0)).unwrap();
|
||||||
let mut contents = Vec::new();
|
let mut contents = Vec::new();
|
||||||
file.read_to_end(&mut contents).unwrap();
|
file.read_to_end(&mut contents).unwrap();
|
||||||
let syscall_registry = register_syscalls(&mut invoke_context).unwrap();
|
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
|
||||||
let mut executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
let mut executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
||||||
Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||||
&contents,
|
&contents,
|
||||||
|
|
|
@ -481,6 +481,10 @@ impl CachedExecutors {
|
||||||
let _ = self.executors.remove(pubkey);
|
let _ = self.executors.remove(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
*self = CachedExecutors::default();
|
||||||
|
}
|
||||||
|
|
||||||
fn get_primer_count_upper_bound_inclusive(counts: &[(&Pubkey, u64)]) -> u64 {
|
fn get_primer_count_upper_bound_inclusive(counts: &[(&Pubkey, u64)]) -> u64 {
|
||||||
const PRIMER_COUNT_TARGET_PERCENTILE: u64 = 85;
|
const PRIMER_COUNT_TARGET_PERCENTILE: u64 = 85;
|
||||||
#[allow(clippy::assertions_on_constants)]
|
#[allow(clippy::assertions_on_constants)]
|
||||||
|
@ -4163,6 +4167,11 @@ impl Bank {
|
||||||
Arc::make_mut(&mut cache).remove(pubkey);
|
Arc::make_mut(&mut cache).remove(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_executors(&self) {
|
||||||
|
let mut cache = self.cached_executors.write().unwrap();
|
||||||
|
Arc::make_mut(&mut cache).clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute a transaction using the provided loaded accounts and update
|
/// Execute a transaction using the provided loaded accounts and update
|
||||||
/// the executors cache if the transaction was successful.
|
/// the executors cache if the transaction was successful.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
|
|
@ -56,30 +56,63 @@ static size_t sol_strlen(const char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal memory alloc/free function
|
* Start address of the memory region used for program heap.
|
||||||
*/
|
*/
|
||||||
#ifndef SOL_SBFV2
|
#define HEAP_START_ADDRESS (0x300000000)
|
||||||
void* sol_alloc_free_(uint64_t, void *);
|
/**
|
||||||
#else
|
* Length of the heap memory region used for program heap.
|
||||||
typedef void*(*sol_alloc_free__pointer_type)(uint64_t, void *);
|
*/
|
||||||
static void* sol_alloc_free_(uint64_t arg1, void * arg2) {
|
#define HEAP_LENGTH (32 * 1024)
|
||||||
sol_alloc_free__pointer_type sol_alloc_free__pointer = (sol_alloc_free__pointer_type) 2213547663;
|
|
||||||
return sol_alloc_free__pointer(arg1, arg2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alloc zero-initialized memory
|
* Alloc zero-initialized memory
|
||||||
*/
|
*/
|
||||||
static void *sol_calloc(size_t nitems, size_t size) {
|
static void *sol_calloc(size_t nitems, size_t size) {
|
||||||
return sol_alloc_free_(nitems * size, 0);
|
// Bump allocator
|
||||||
|
uint64_t* pos_ptr = (uint64_t*)HEAP_START_ADDRESS;
|
||||||
|
|
||||||
|
uint64_t pos = *pos_ptr;
|
||||||
|
if (pos == 0) {
|
||||||
|
/** First time, set starting position */
|
||||||
|
pos = HEAP_START_ADDRESS + HEAP_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t bytes = (uint64_t)(nitems * size);
|
||||||
|
if (size == 0 ||
|
||||||
|
!(nitems == 0 || size == 0) &&
|
||||||
|
!(nitems == bytes / size)) {
|
||||||
|
/** Overflow */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (pos < bytes) {
|
||||||
|
/** Saturated */
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
pos -= bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t align = size;
|
||||||
|
align--;
|
||||||
|
align |= align >> 1;
|
||||||
|
align |= align >> 2;
|
||||||
|
align |= align >> 4;
|
||||||
|
align |= align >> 8;
|
||||||
|
align |= align >> 16;
|
||||||
|
align |= align >> 32;
|
||||||
|
align++;
|
||||||
|
pos &= ~(align - 1);
|
||||||
|
if (pos < HEAP_START_ADDRESS + sizeof(uint8_t*)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*pos_ptr = pos;
|
||||||
|
return (void*)pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocates the memory previously allocated by sol_calloc
|
* Deallocates the memory previously allocated by sol_calloc
|
||||||
*/
|
*/
|
||||||
static void sol_free(void *ptr) {
|
static void sol_free(void *ptr) {
|
||||||
(void) sol_alloc_free_(0, ptr);
|
// I'm a bump allocator, I don't free
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in New Issue