* Moves syscall_registry into the rbpf Executable constructor.
* Adds the reject_unresolved_syscalls flag which is only set when deploying programs via the CLI.
(cherry picked from commit 8d5c04e257
)
Co-authored-by: Alexander Meißner <AlexanderMeissner@gmx.net>
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -1640,9 +1640,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "goblin"
|
name = "goblin"
|
||||||
version = "0.3.0"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c69552f48b18aa6102ce0c82dd9bc9d3f8af5fc0a5797069b1b466b90570e39c"
|
checksum = "0b1800b95efee8ad4ef04517d4d69f8e209e763b1668f1179aeeedd0e454da55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log 0.4.14",
|
"log 0.4.14",
|
||||||
"plain",
|
"plain",
|
||||||
@ -5886,9 +5886,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.2.11"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c1c5bdfa63c68d848d95024c7f4335bae4b1917f7df2e48e2d945f4664a8b45"
|
checksum = "fc1dced9892c2b0273318ef4d8486112ea7c7a7b8eb563a20e7858ad921b4719"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"combine",
|
"combine",
|
||||||
|
@ -40,7 +40,7 @@ solana-config-program = { path = "../programs/config", version = "=1.8.5" }
|
|||||||
solana-faucet = { path = "../faucet", version = "=1.8.5" }
|
solana-faucet = { path = "../faucet", version = "=1.8.5" }
|
||||||
solana-logger = { path = "../logger", version = "=1.8.5" }
|
solana-logger = { path = "../logger", version = "=1.8.5" }
|
||||||
solana-net-utils = { path = "../net-utils", version = "=1.8.5" }
|
solana-net-utils = { path = "../net-utils", version = "=1.8.5" }
|
||||||
solana_rbpf = "=0.2.11"
|
solana_rbpf = "=0.2.13"
|
||||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.8.5" }
|
solana-remote-wallet = { path = "../remote-wallet", version = "=1.8.5" }
|
||||||
solana-sdk = { path = "../sdk", version = "=1.8.5" }
|
solana-sdk = { path = "../sdk", version = "=1.8.5" }
|
||||||
solana-transaction-status = { path = "../transaction-status", version = "=1.8.5" }
|
solana-transaction-status = { path = "../transaction-status", version = "=1.8.5" }
|
||||||
|
@ -9,7 +9,7 @@ use bip39::{Language, Mnemonic, MnemonicType, Seed};
|
|||||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||||
use log::*;
|
use log::*;
|
||||||
use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig};
|
use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig};
|
||||||
use solana_bpf_loader_program::{bpf_verifier, BpfError, ThisInstructionMeter};
|
use solana_bpf_loader_program::{syscalls::register_syscalls, BpfError, ThisInstructionMeter};
|
||||||
use solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*};
|
use solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*};
|
||||||
use solana_cli_output::{
|
use solana_cli_output::{
|
||||||
CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId,
|
CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId,
|
||||||
@ -24,7 +24,10 @@ use solana_client::{
|
|||||||
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
|
||||||
tpu_client::{TpuClient, TpuClientConfig},
|
tpu_client::{TpuClient, TpuClientConfig},
|
||||||
};
|
};
|
||||||
use solana_rbpf::vm::{Config, Executable};
|
use solana_rbpf::{
|
||||||
|
verifier,
|
||||||
|
vm::{Config, Executable},
|
||||||
|
};
|
||||||
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
@ -37,6 +40,7 @@ use solana_sdk::{
|
|||||||
message::Message,
|
message::Message,
|
||||||
native_token::Sol,
|
native_token::Sol,
|
||||||
packet::PACKET_DATA_SIZE,
|
packet::PACKET_DATA_SIZE,
|
||||||
|
process_instruction::MockInvokeContext,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer},
|
signature::{keypair_from_seed, read_keypair_file, Keypair, Signature, Signer},
|
||||||
system_instruction::{self, SystemError},
|
system_instruction::{self, SystemError},
|
||||||
@ -1983,12 +1987,17 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
|||||||
let mut program_data = Vec::new();
|
let mut program_data = Vec::new();
|
||||||
file.read_to_end(&mut program_data)
|
file.read_to_end(&mut program_data)
|
||||||
.map_err(|err| format!("Unable to read program file: {}", err))?;
|
.map_err(|err| format!("Unable to read program file: {}", err))?;
|
||||||
|
let mut invoke_context = MockInvokeContext::new(vec![]);
|
||||||
|
|
||||||
// Verify the program
|
// Verify the program
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
&program_data,
|
&program_data,
|
||||||
Some(|x| bpf_verifier::check(x)),
|
Some(verifier::check),
|
||||||
Config::default(),
|
Config {
|
||||||
|
reject_unresolved_syscalls: true,
|
||||||
|
..Config::default()
|
||||||
|
},
|
||||||
|
register_syscalls(&mut invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.map_err(|err| format!("ELF error: {}", err))?;
|
.map_err(|err| format!("ELF error: {}", err))?;
|
||||||
|
|
||||||
|
BIN
cli/tests/fixtures/noop.so
vendored
BIN
cli/tests/fixtures/noop.so
vendored
Binary file not shown.
8
programs/bpf/Cargo.lock
generated
8
programs/bpf/Cargo.lock
generated
@ -1159,9 +1159,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "goblin"
|
name = "goblin"
|
||||||
version = "0.3.0"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c69552f48b18aa6102ce0c82dd9bc9d3f8af5fc0a5797069b1b466b90570e39c"
|
checksum = "0b1800b95efee8ad4ef04517d4d69f8e209e763b1668f1179aeeedd0e454da55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"plain",
|
"plain",
|
||||||
@ -3699,9 +3699,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.2.11"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c1c5bdfa63c68d848d95024c7f4335bae4b1917f7df2e48e2d945f4664a8b45"
|
checksum = "fc1dced9892c2b0273318ef4d8486112ea7c7a7b8eb563a20e7858ad921b4719"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.4",
|
"byteorder 1.3.4",
|
||||||
"combine",
|
"combine",
|
||||||
|
@ -30,7 +30,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.8.5" }
|
|||||||
solana-cli-output = { path = "../../cli-output", version = "=1.8.5" }
|
solana-cli-output = { path = "../../cli-output", version = "=1.8.5" }
|
||||||
solana-logger = { path = "../../logger", version = "=1.8.5" }
|
solana-logger = { path = "../../logger", version = "=1.8.5" }
|
||||||
solana-measure = { path = "../../measure", version = "=1.8.5" }
|
solana-measure = { path = "../../measure", version = "=1.8.5" }
|
||||||
solana_rbpf = "=0.2.11"
|
solana_rbpf = "=0.2.13"
|
||||||
solana-runtime = { path = "../../runtime", version = "=1.8.5" }
|
solana-runtime = { path = "../../runtime", version = "=1.8.5" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.8.5" }
|
solana-sdk = { path = "../../sdk", version = "=1.8.5" }
|
||||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.8.5" }
|
solana-transaction-status = { path = "../../transaction-status", version = "=1.8.5" }
|
||||||
|
@ -11,7 +11,7 @@ use solana_bpf_loader_program::{
|
|||||||
ThisInstructionMeter,
|
ThisInstructionMeter,
|
||||||
};
|
};
|
||||||
use solana_measure::measure::Measure;
|
use solana_measure::measure::Measure;
|
||||||
use solana_rbpf::vm::{Config, Executable, InstructionMeter};
|
use solana_rbpf::vm::{Config, Executable, InstructionMeter, SyscallRegistry};
|
||||||
use solana_runtime::{
|
use solana_runtime::{
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
bank_client::BankClient,
|
bank_client::BankClient,
|
||||||
@ -79,6 +79,7 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
|
|||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
|
SyscallRegistry::default(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
@ -97,10 +98,13 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||||||
let mut invoke_context = MockInvokeContext::new(vec![]);
|
let mut invoke_context = MockInvokeContext::new(vec![]);
|
||||||
|
|
||||||
let elf = load_elf("bench_alu").unwrap();
|
let elf = load_elf("bench_alu").unwrap();
|
||||||
let mut executable =
|
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
&elf,
|
||||||
.unwrap();
|
None,
|
||||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
Config::default(),
|
||||||
|
register_syscalls(&mut invoke_context).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
@ -225,10 +229,13 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let elf = load_elf("noop").unwrap();
|
let elf = load_elf("noop").unwrap();
|
||||||
let mut executable =
|
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
&elf,
|
||||||
.unwrap();
|
None,
|
||||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
Config::default(),
|
||||||
|
register_syscalls(&mut invoke_context).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let _ = create_vm(
|
let _ = create_vm(
|
||||||
@ -273,10 +280,13 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let elf = load_elf("tuner").unwrap();
|
let elf = load_elf("tuner").unwrap();
|
||||||
let mut executable =
|
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&elf, None, Config::default())
|
&elf,
|
||||||
.unwrap();
|
None,
|
||||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
Config::default(),
|
||||||
|
register_syscalls(&mut invoke_context).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
|
@ -211,14 +211,16 @@ fn run_program(
|
|||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
|
|
||||||
let config = Config {
|
let config = Config {
|
||||||
max_call_depth: 20,
|
|
||||||
stack_frame_size: 4096,
|
|
||||||
enable_instruction_meter: true,
|
|
||||||
enable_instruction_tracing: true,
|
enable_instruction_tracing: true,
|
||||||
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut executable =
|
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&data, None, config).unwrap();
|
&data,
|
||||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
None,
|
||||||
|
config,
|
||||||
|
register_syscalls(&mut invoke_context).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
|
|
||||||
let mut instruction_count = 0;
|
let mut instruction_count = 0;
|
||||||
|
@ -22,7 +22,7 @@ sha3 = "0.9.1"
|
|||||||
solana-measure = { path = "../../measure", version = "=1.8.5" }
|
solana-measure = { path = "../../measure", version = "=1.8.5" }
|
||||||
solana-runtime = { path = "../../runtime", version = "=1.8.5" }
|
solana-runtime = { path = "../../runtime", version = "=1.8.5" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.8.5" }
|
solana-sdk = { path = "../../sdk", version = "=1.8.5" }
|
||||||
solana_rbpf = "=0.2.11"
|
solana_rbpf = "=0.2.13"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -1,294 +0,0 @@
|
|||||||
#![allow(clippy::upper_case_acronyms)]
|
|
||||||
|
|
||||||
use crate::BpfError;
|
|
||||||
use solana_rbpf::ebpf;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Error definitions
|
|
||||||
#[derive(Debug, Error, PartialEq)]
|
|
||||||
pub enum VerifierError {
|
|
||||||
/// ProgramLengthNotMultiple
|
|
||||||
#[error("program length must be a multiple of {} octets", ebpf::INSN_SIZE)]
|
|
||||||
ProgramLengthNotMultiple,
|
|
||||||
/// ProgramTooLarge
|
|
||||||
#[error("program too big, max {}, is {}", ebpf::PROG_MAX_INSNS, .0)]
|
|
||||||
ProgramTooLarge(usize),
|
|
||||||
/// NoProgram
|
|
||||||
#[error("no program set, call prog_set() to load one")]
|
|
||||||
NoProgram,
|
|
||||||
#[error("division by 0 (insn #{0})")]
|
|
||||||
DivisionByZero(usize),
|
|
||||||
/// UnsupportedLEBEArgument
|
|
||||||
#[error("unsupported argument for LE/BE (insn #{0})")]
|
|
||||||
UnsupportedLEBEArgument(usize),
|
|
||||||
/// LDDWCannotBeLast
|
|
||||||
#[error("LD_DW instruction cannot be last in program")]
|
|
||||||
LDDWCannotBeLast,
|
|
||||||
/// IncompleteLDDW
|
|
||||||
#[error("incomplete LD_DW instruction (insn #{0})")]
|
|
||||||
IncompleteLDDW(usize),
|
|
||||||
/// InfiniteLoop
|
|
||||||
#[error("infinite loop (insn #{0})")]
|
|
||||||
InfiniteLoop(usize),
|
|
||||||
/// JumpOutOfCode
|
|
||||||
#[error("jump out of code to #{0} (insn #{1})")]
|
|
||||||
JumpOutOfCode(usize, usize),
|
|
||||||
/// JumpToMiddleOfLDDW
|
|
||||||
#[error("jump to middle of LD_DW at #{0} (insn #{1})")]
|
|
||||||
JumpToMiddleOfLDDW(usize, usize),
|
|
||||||
/// InvalidSourceRegister
|
|
||||||
#[error("invalid source register (insn #{0})")]
|
|
||||||
InvalidSourceRegister(usize),
|
|
||||||
/// CannotWriteR10
|
|
||||||
#[error("cannot write into register r10 (insn #{0})")]
|
|
||||||
CannotWriteR10(usize),
|
|
||||||
/// InvalidDestinationRegister
|
|
||||||
#[error("invalid destination register (insn #{0})")]
|
|
||||||
InvalidDestinationRegister(usize),
|
|
||||||
/// UnknownOpCode
|
|
||||||
#[error("unknown eBPF opcode {0:#2x} (insn #{1:?})")]
|
|
||||||
UnknownOpCode(u8, usize),
|
|
||||||
/// Shift with overflow
|
|
||||||
#[error("Shift with overflow at instruction {0}")]
|
|
||||||
ShiftWithOverflow(usize),
|
|
||||||
/// Invalid register specified
|
|
||||||
#[error("Invalid register specified at instruction {0}")]
|
|
||||||
InvalidRegister(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn adj_insn_ptr(insn_ptr: usize) -> usize {
|
|
||||||
insn_ptr + ebpf::ELF_INSN_DUMP_OFFSET
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_prog_len(prog: &[u8]) -> Result<(), BpfError> {
|
|
||||||
if prog.len() % ebpf::INSN_SIZE != 0 {
|
|
||||||
return Err(VerifierError::ProgramLengthNotMultiple.into());
|
|
||||||
}
|
|
||||||
if prog.is_empty() {
|
|
||||||
return Err(VerifierError::NoProgram.into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_imm_nonzero(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BpfError> {
|
|
||||||
if insn.imm == 0 {
|
|
||||||
return Err(VerifierError::DivisionByZero(adj_insn_ptr(insn_ptr)).into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BpfError> {
|
|
||||||
match insn.imm {
|
|
||||||
16 | 32 | 64 => Ok(()),
|
|
||||||
_ => Err(VerifierError::UnsupportedLEBEArgument(adj_insn_ptr(insn_ptr)).into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_load_dw(prog: &[u8], insn_ptr: usize) -> Result<(), BpfError> {
|
|
||||||
if insn_ptr + 1 >= (prog.len() / ebpf::INSN_SIZE) {
|
|
||||||
// Last instruction cannot be LD_DW because there would be no 2nd DW
|
|
||||||
return Err(VerifierError::LDDWCannotBeLast.into());
|
|
||||||
}
|
|
||||||
let next_insn = ebpf::get_insn(prog, insn_ptr + 1);
|
|
||||||
if next_insn.opc != 0 {
|
|
||||||
return Err(VerifierError::IncompleteLDDW(adj_insn_ptr(insn_ptr)).into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_jmp_offset(prog: &[u8], insn_ptr: usize) -> Result<(), BpfError> {
|
|
||||||
let insn = ebpf::get_insn(prog, insn_ptr);
|
|
||||||
// if insn.off == -1 {
|
|
||||||
// return Err(VerifierError::InfiniteLoop(adj_insn_ptr(insn_ptr)).into());
|
|
||||||
// }
|
|
||||||
|
|
||||||
let dst_insn_ptr = insn_ptr as isize + 1 + insn.off as isize;
|
|
||||||
if dst_insn_ptr < 0 || dst_insn_ptr as usize >= (prog.len() / ebpf::INSN_SIZE) {
|
|
||||||
return Err(
|
|
||||||
VerifierError::JumpOutOfCode(dst_insn_ptr as usize, adj_insn_ptr(insn_ptr)).into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let dst_insn = ebpf::get_insn(prog, dst_insn_ptr as usize);
|
|
||||||
if dst_insn.opc == 0 {
|
|
||||||
return Err(VerifierError::JumpToMiddleOfLDDW(
|
|
||||||
dst_insn_ptr as usize,
|
|
||||||
adj_insn_ptr(insn_ptr),
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<(), BpfError> {
|
|
||||||
if insn.src > 10 {
|
|
||||||
return Err(VerifierError::InvalidSourceRegister(adj_insn_ptr(insn_ptr)).into());
|
|
||||||
}
|
|
||||||
match (insn.dst, store) {
|
|
||||||
(0..=9, _) | (10, true) => Ok(()),
|
|
||||||
(10, false) => Err(VerifierError::CannotWriteR10(adj_insn_ptr(insn_ptr)).into()),
|
|
||||||
(_, _) => Err(VerifierError::InvalidDestinationRegister(adj_insn_ptr(insn_ptr)).into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that the imm is a valid shift operand
|
|
||||||
fn check_imm_shift(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
|
||||||
if insn.imm < 0 || insn.imm as u64 >= 64 {
|
|
||||||
return Err(VerifierError::ShiftWithOverflow(adj_insn_ptr(insn_ptr)));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that the imm is a valid register number
|
|
||||||
fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
|
||||||
if insn.imm < 0 || insn.imm > 10 {
|
|
||||||
return Err(VerifierError::InvalidRegister(adj_insn_ptr(insn_ptr)));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
pub fn check(prog: &[u8]) -> Result<(), BpfError> {
|
|
||||||
check_prog_len(prog)?;
|
|
||||||
|
|
||||||
let mut insn_ptr: usize = 0;
|
|
||||||
while insn_ptr * ebpf::INSN_SIZE < prog.len() {
|
|
||||||
let insn = ebpf::get_insn(prog, insn_ptr);
|
|
||||||
let mut store = false;
|
|
||||||
|
|
||||||
match insn.opc {
|
|
||||||
|
|
||||||
// BPF_LD class
|
|
||||||
ebpf::LD_ABS_B => {},
|
|
||||||
ebpf::LD_ABS_H => {},
|
|
||||||
ebpf::LD_ABS_W => {},
|
|
||||||
ebpf::LD_ABS_DW => {},
|
|
||||||
ebpf::LD_IND_B => {},
|
|
||||||
ebpf::LD_IND_H => {},
|
|
||||||
ebpf::LD_IND_W => {},
|
|
||||||
ebpf::LD_IND_DW => {},
|
|
||||||
|
|
||||||
ebpf::LD_DW_IMM => {
|
|
||||||
store = true;
|
|
||||||
check_load_dw(prog, insn_ptr)?;
|
|
||||||
insn_ptr += 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
// BPF_LDX class
|
|
||||||
ebpf::LD_B_REG => {},
|
|
||||||
ebpf::LD_H_REG => {},
|
|
||||||
ebpf::LD_W_REG => {},
|
|
||||||
ebpf::LD_DW_REG => {},
|
|
||||||
|
|
||||||
// BPF_ST class
|
|
||||||
ebpf::ST_B_IMM => store = true,
|
|
||||||
ebpf::ST_H_IMM => store = true,
|
|
||||||
ebpf::ST_W_IMM => store = true,
|
|
||||||
ebpf::ST_DW_IMM => store = true,
|
|
||||||
|
|
||||||
// BPF_STX class
|
|
||||||
ebpf::ST_B_REG => store = true,
|
|
||||||
ebpf::ST_H_REG => store = true,
|
|
||||||
ebpf::ST_W_REG => store = true,
|
|
||||||
ebpf::ST_DW_REG => store = true,
|
|
||||||
|
|
||||||
// BPF_ALU class
|
|
||||||
ebpf::ADD32_IMM => {},
|
|
||||||
ebpf::ADD32_REG => {},
|
|
||||||
ebpf::SUB32_IMM => {},
|
|
||||||
ebpf::SUB32_REG => {},
|
|
||||||
ebpf::MUL32_IMM => {},
|
|
||||||
ebpf::MUL32_REG => {},
|
|
||||||
ebpf::DIV32_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
|
|
||||||
ebpf::DIV32_REG => {},
|
|
||||||
ebpf::OR32_IMM => {},
|
|
||||||
ebpf::OR32_REG => {},
|
|
||||||
ebpf::AND32_IMM => {},
|
|
||||||
ebpf::AND32_REG => {},
|
|
||||||
ebpf::LSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::LSH32_REG => {},
|
|
||||||
ebpf::RSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::RSH32_REG => {},
|
|
||||||
ebpf::NEG32 => {},
|
|
||||||
ebpf::MOD32_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
|
|
||||||
ebpf::MOD32_REG => {},
|
|
||||||
ebpf::XOR32_IMM => {},
|
|
||||||
ebpf::XOR32_REG => {},
|
|
||||||
ebpf::MOV32_IMM => {},
|
|
||||||
ebpf::MOV32_REG => {},
|
|
||||||
ebpf::ARSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::ARSH32_REG => {},
|
|
||||||
ebpf::LE => { check_imm_endian(&insn, insn_ptr)?; },
|
|
||||||
ebpf::BE => { check_imm_endian(&insn, insn_ptr)?; },
|
|
||||||
|
|
||||||
// BPF_ALU64 class
|
|
||||||
ebpf::ADD64_IMM => {},
|
|
||||||
ebpf::ADD64_REG => {},
|
|
||||||
ebpf::SUB64_IMM => {},
|
|
||||||
ebpf::SUB64_REG => {},
|
|
||||||
ebpf::MUL64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
|
|
||||||
ebpf::MUL64_REG => {},
|
|
||||||
ebpf::DIV64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
|
|
||||||
ebpf::DIV64_REG => {},
|
|
||||||
ebpf::OR64_IMM => {},
|
|
||||||
ebpf::OR64_REG => {},
|
|
||||||
ebpf::AND64_IMM => {},
|
|
||||||
ebpf::AND64_REG => {},
|
|
||||||
ebpf::LSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::LSH64_REG => {},
|
|
||||||
ebpf::RSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::RSH64_REG => {},
|
|
||||||
ebpf::NEG64 => {},
|
|
||||||
ebpf::MOD64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
|
|
||||||
ebpf::MOD64_REG => {},
|
|
||||||
ebpf::XOR64_IMM => {},
|
|
||||||
ebpf::XOR64_REG => {},
|
|
||||||
ebpf::MOV64_IMM => {},
|
|
||||||
ebpf::MOV64_REG => {},
|
|
||||||
ebpf::ARSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
|
|
||||||
ebpf::ARSH64_REG => {},
|
|
||||||
|
|
||||||
// BPF_JMP class
|
|
||||||
ebpf::JA => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JEQ_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JEQ_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JGT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JGT_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JGE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JGE_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JLT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JLT_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JLE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JLE_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSET_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSET_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JNE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JNE_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSGT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSGT_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSGE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSGE_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSLT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSLT_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSLE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::JSLE_REG => { check_jmp_offset(prog, insn_ptr)?; },
|
|
||||||
ebpf::CALL_IMM => {},
|
|
||||||
ebpf::CALL_REG => { check_imm_register(&insn, insn_ptr)?; },
|
|
||||||
ebpf::EXIT => {},
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
return Err(VerifierError::UnknownOpCode(insn.opc, adj_insn_ptr(insn_ptr)).into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check_registers(&insn, store, insn_ptr)?;
|
|
||||||
|
|
||||||
insn_ptr += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insn_ptr should now be equal to number of instructions.
|
|
||||||
if insn_ptr != prog.len() / ebpf::INSN_SIZE {
|
|
||||||
return Err(VerifierError::JumpOutOfCode(adj_insn_ptr(insn_ptr), adj_insn_ptr(insn_ptr)).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)]
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod allocator_bump;
|
pub mod allocator_bump;
|
||||||
pub mod bpf_verifier;
|
|
||||||
pub mod deprecated;
|
pub mod deprecated;
|
||||||
pub mod serialization;
|
pub mod serialization;
|
||||||
pub mod syscalls;
|
pub mod syscalls;
|
||||||
@ -10,7 +9,6 @@ pub mod upgradeable_with_jit;
|
|||||||
pub mod with_jit;
|
pub mod with_jit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bpf_verifier::VerifierError,
|
|
||||||
serialization::{deserialize_parameters, serialize_parameters},
|
serialization::{deserialize_parameters, serialize_parameters},
|
||||||
syscalls::SyscallError,
|
syscalls::SyscallError,
|
||||||
};
|
};
|
||||||
@ -22,6 +20,7 @@ use solana_rbpf::{
|
|||||||
error::{EbpfError, UserDefinedError},
|
error::{EbpfError, UserDefinedError},
|
||||||
memory_region::MemoryRegion,
|
memory_region::MemoryRegion,
|
||||||
static_analysis::Analysis,
|
static_analysis::Analysis,
|
||||||
|
verifier::{self, VerifierError},
|
||||||
vm::{Config, EbpfVm, Executable, InstructionMeter},
|
vm::{Config, EbpfVm, Executable, InstructionMeter},
|
||||||
};
|
};
|
||||||
use solana_runtime::message_processor::MessageProcessor;
|
use solana_runtime::message_processor::MessageProcessor;
|
||||||
@ -86,23 +85,27 @@ pub fn create_executor(
|
|||||||
let config = Config {
|
let config = Config {
|
||||||
max_call_depth: bpf_compute_budget.max_call_depth,
|
max_call_depth: bpf_compute_budget.max_call_depth,
|
||||||
stack_frame_size: bpf_compute_budget.stack_frame_size,
|
stack_frame_size: bpf_compute_budget.stack_frame_size,
|
||||||
enable_instruction_meter: true,
|
|
||||||
enable_instruction_tracing: log_enabled!(Trace),
|
enable_instruction_tracing: log_enabled!(Trace),
|
||||||
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut executable = {
|
let mut executable = {
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||||
let program = keyed_account_at_index(keyed_accounts, program_account_index)?;
|
let program = keyed_account_at_index(keyed_accounts, program_account_index)?;
|
||||||
let account = program.try_account_ref()?;
|
let account = program.try_account_ref()?;
|
||||||
let data = &account.data()[program_data_offset..];
|
let data = &account.data()[program_data_offset..];
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(data, None, config)
|
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
|
data,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
syscall_registry,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||||
let (_, elf_bytes) = executable
|
let (_, elf_bytes) = executable
|
||||||
.get_text_bytes()
|
.get_text_bytes()
|
||||||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||||
bpf_verifier::check(elf_bytes)
|
verifier::check(elf_bytes)
|
||||||
.map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?;
|
.map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e.into())))?;
|
||||||
executable.set_syscall_registry(syscall_registry);
|
|
||||||
if use_jit {
|
if use_jit {
|
||||||
if let Err(err) = executable.jit_compile() {
|
if let Err(err) = executable.jit_compile() {
|
||||||
ic_msg!(invoke_context, "Failed to compile program {:?}", err);
|
ic_msg!(invoke_context, "Failed to compile program {:?}", err);
|
||||||
@ -1001,6 +1004,7 @@ impl Executor for BpfExecutor {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use solana_rbpf::vm::SyscallRegistry;
|
||||||
use solana_runtime::{bank::Bank, bank_client::BankClient};
|
use solana_runtime::{bank::Bank, bank_client::BankClient};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{
|
account::{
|
||||||
@ -1054,9 +1058,10 @@ mod tests {
|
|||||||
solana_rbpf::elf::register_bpf_function(&mut bpf_functions, 0, "entrypoint").unwrap();
|
solana_rbpf::elf::register_bpf_function(&mut bpf_functions, 0, "entrypoint").unwrap();
|
||||||
let program = <dyn Executable<BpfError, TestInstructionMeter>>::from_text_bytes(
|
let program = <dyn Executable<BpfError, TestInstructionMeter>>::from_text_bytes(
|
||||||
program,
|
program,
|
||||||
bpf_functions,
|
|
||||||
None,
|
None,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
|
SyscallRegistry::default(),
|
||||||
|
bpf_functions,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut vm =
|
let mut vm =
|
||||||
@ -1067,12 +1072,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "VerifierError(LDDWCannotBeLast)")]
|
#[should_panic(expected = "LDDWCannotBeLast")]
|
||||||
fn test_bpf_loader_check_load_dw() {
|
fn test_bpf_loader_check_load_dw() {
|
||||||
let prog = &[
|
let prog = &[
|
||||||
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
|
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
|
||||||
];
|
];
|
||||||
bpf_verifier::check(prog).unwrap();
|
verifier::check(prog).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2764,13 +2764,6 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
const DEFAULT_CONFIG: Config = Config {
|
|
||||||
max_call_depth: 20,
|
|
||||||
stack_frame_size: 4_096,
|
|
||||||
enable_instruction_meter: true,
|
|
||||||
enable_instruction_tracing: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
macro_rules! assert_access_violation {
|
macro_rules! assert_access_violation {
|
||||||
($result:expr, $va:expr, $len:expr) => {
|
($result:expr, $va:expr, $len:expr) => {
|
||||||
match $result {
|
match $result {
|
||||||
@ -2792,9 +2785,10 @@ mod tests {
|
|||||||
const LENGTH: u64 = 1000;
|
const LENGTH: u64 = 1000;
|
||||||
let data = vec![0u8; LENGTH as usize];
|
let data = vec![0u8; LENGTH as usize];
|
||||||
let addr = data.as_ptr() as u64;
|
let addr = data.as_ptr() as u64;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion::new_from_slice(&data, START, 0, false)],
|
vec![MemoryRegion::new_from_slice(&data, START, 0, false)],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -2831,6 +2825,7 @@ mod tests {
|
|||||||
// Pubkey
|
// Pubkey
|
||||||
let pubkey = solana_sdk::pubkey::new_rand();
|
let pubkey = solana_sdk::pubkey::new_rand();
|
||||||
let addr = &pubkey as *const _ as u64;
|
let addr = &pubkey as *const _ as u64;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -2839,7 +2834,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_pubkey =
|
let translated_pubkey =
|
||||||
@ -2861,7 +2856,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_instruction =
|
let translated_instruction =
|
||||||
@ -2880,6 +2875,7 @@ mod tests {
|
|||||||
let data: Vec<u8> = vec![];
|
let data: Vec<u8> = vec![];
|
||||||
assert_eq!(0x1 as *const u8, data.as_ptr());
|
assert_eq!(0x1 as *const u8, data.as_ptr());
|
||||||
let addr = good_data.as_ptr() as *const _ as u64;
|
let addr = good_data.as_ptr() as *const _ as u64;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -2888,7 +2884,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data = translate_slice::<u8>(
|
let translated_data = translate_slice::<u8>(
|
||||||
@ -2913,7 +2909,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data = translate_slice::<u8>(
|
let translated_data = translate_slice::<u8>(
|
||||||
@ -2956,7 +2952,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data = translate_slice::<u64>(
|
let translated_data = translate_slice::<u64>(
|
||||||
@ -2986,7 +2982,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data = translate_slice::<Pubkey>(
|
let translated_data = translate_slice::<Pubkey>(
|
||||||
@ -3006,6 +3002,7 @@ mod tests {
|
|||||||
fn test_translate_string_and_do() {
|
fn test_translate_string_and_do() {
|
||||||
let string = "Gaggablaghblagh!";
|
let string = "Gaggablaghblagh!";
|
||||||
let addr = string.as_ptr() as *const _ as u64;
|
let addr = string.as_ptr() as *const _ as u64;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -3014,7 +3011,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -3037,9 +3034,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "UserError(SyscallError(Abort))")]
|
#[should_panic(expected = "UserError(SyscallError(Abort))")]
|
||||||
fn test_syscall_abort() {
|
fn test_syscall_abort() {
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping =
|
let memory_mapping =
|
||||||
MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &DEFAULT_CONFIG)
|
MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
|
||||||
.unwrap();
|
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
SyscallAbort::call(
|
SyscallAbort::call(
|
||||||
&mut SyscallAbort {},
|
&mut SyscallAbort {},
|
||||||
@ -3059,6 +3056,7 @@ mod tests {
|
|||||||
fn test_syscall_sol_panic() {
|
fn test_syscall_sol_panic() {
|
||||||
let string = "Gaggablaghblagh!";
|
let string = "Gaggablaghblagh!";
|
||||||
let addr = string.as_ptr() as *const _ as u64;
|
let addr = string.as_ptr() as *const _ as u64;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -3067,7 +3065,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3135,6 +3133,7 @@ mod tests {
|
|||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
enforce_aligned_host_addrs: true,
|
enforce_aligned_host_addrs: true,
|
||||||
};
|
};
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -3143,7 +3142,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3248,7 +3247,8 @@ mod tests {
|
|||||||
compute_meter,
|
compute_meter,
|
||||||
logger,
|
logger,
|
||||||
};
|
};
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(vec![], &DEFAULT_CONFIG).unwrap();
|
let config = Config::default();
|
||||||
|
let memory_mapping = MemoryMapping::new::<UserError>(vec![], &config).unwrap();
|
||||||
|
|
||||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||||
syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result);
|
syscall_sol_log_u64.call(1, 2, 3, 4, 5, &memory_mapping, &mut result);
|
||||||
@ -3275,6 +3275,7 @@ mod tests {
|
|||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
enforce_aligned_host_addrs: true,
|
enforce_aligned_host_addrs: true,
|
||||||
};
|
};
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion {
|
vec![MemoryRegion {
|
||||||
host_addr: addr,
|
host_addr: addr,
|
||||||
@ -3283,7 +3284,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3318,6 +3319,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_syscall_sol_alloc_free() {
|
fn test_syscall_sol_alloc_free() {
|
||||||
|
let config = Config::default();
|
||||||
// large alloc
|
// large alloc
|
||||||
{
|
{
|
||||||
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
||||||
@ -3328,7 +3330,7 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
)],
|
)],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut syscall = SyscallAllocFree {
|
let mut syscall = SyscallAllocFree {
|
||||||
@ -3355,7 +3357,7 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
)],
|
)],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut syscall = SyscallAllocFree {
|
let mut syscall = SyscallAllocFree {
|
||||||
@ -3381,7 +3383,7 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
)],
|
)],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut syscall = SyscallAllocFree {
|
let mut syscall = SyscallAllocFree {
|
||||||
@ -3401,6 +3403,7 @@ mod tests {
|
|||||||
|
|
||||||
fn check_alignment<T>() {
|
fn check_alignment<T>() {
|
||||||
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![MemoryRegion::new_from_slice(
|
vec![MemoryRegion::new_from_slice(
|
||||||
heap.as_slice(),
|
heap.as_slice(),
|
||||||
@ -3408,7 +3411,7 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
true,
|
true,
|
||||||
)],
|
)],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut syscall = SyscallAllocFree {
|
let mut syscall = SyscallAllocFree {
|
||||||
@ -3454,6 +3457,7 @@ mod tests {
|
|||||||
let ro_len = bytes_to_hash.len() as u64;
|
let ro_len = bytes_to_hash.len() as u64;
|
||||||
let ro_va = 96;
|
let ro_va = 96;
|
||||||
let rw_va = 192;
|
let rw_va = 192;
|
||||||
|
let config = Config::default();
|
||||||
let memory_mapping = MemoryMapping::new::<UserError>(
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
||||||
vec![
|
vec![
|
||||||
MemoryRegion {
|
MemoryRegion {
|
||||||
@ -3485,7 +3489,7 @@ mod tests {
|
|||||||
is_writable: true,
|
is_writable: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
||||||
@ -3551,6 +3555,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_syscall_get_sysvar() {
|
fn test_syscall_get_sysvar() {
|
||||||
|
let config = Config::default();
|
||||||
// Test clock sysvar
|
// Test clock sysvar
|
||||||
{
|
{
|
||||||
let got_clock = Clock::default();
|
let got_clock = Clock::default();
|
||||||
@ -3564,7 +3569,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: true,
|
is_writable: true,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3606,7 +3611,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: true,
|
is_writable: true,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3656,7 +3661,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: true,
|
is_writable: true,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -3696,7 +3701,7 @@ mod tests {
|
|||||||
vm_gap_shift: 63,
|
vm_gap_shift: 63,
|
||||||
is_writable: true,
|
is_writable: true,
|
||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&config,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -185,14 +185,21 @@ 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 mut executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
let mut executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
||||||
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(&contents, None, config)
|
<dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||||
.map_err(|err| format!("Executable constructor failed: {:?}", err))
|
&contents,
|
||||||
|
None,
|
||||||
|
config,
|
||||||
|
syscall_registry,
|
||||||
|
)
|
||||||
|
.map_err(|err| format!("Executable constructor failed: {:?}", err))
|
||||||
} else {
|
} else {
|
||||||
assemble::<BpfError, ThisInstructionMeter>(
|
assemble::<BpfError, ThisInstructionMeter>(
|
||||||
std::str::from_utf8(contents.as_slice()).unwrap(),
|
std::str::from_utf8(contents.as_slice()).unwrap(),
|
||||||
None,
|
None,
|
||||||
config,
|
config,
|
||||||
|
syscall_registry,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -201,7 +208,6 @@ native machine code before execting it in the virtual machine.",
|
|||||||
let (_, elf_bytes) = executable.get_text_bytes().unwrap();
|
let (_, elf_bytes) = executable.get_text_bytes().unwrap();
|
||||||
check(elf_bytes).unwrap();
|
check(elf_bytes).unwrap();
|
||||||
}
|
}
|
||||||
executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap());
|
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
let analysis = Analysis::from_executable(executable.as_ref());
|
let analysis = Analysis::from_executable(executable.as_ref());
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user