Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Configurable enforcement of syscalls to be resolved when an ELF file …
Browse files Browse the repository at this point in the history
…is loaded.
  • Loading branch information
Lichtso committed Jun 25, 2021
1 parent 5f9a1fd commit 49a715d
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
20 changes: 17 additions & 3 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {
pub fn load(
config: Config,
bytes: &[u8],
syscall_registry: SyscallRegistry,
mut syscall_registry: SyscallRegistry,
) -> Result<Self, ElfError> {
let elf = Elf::parse(bytes)?;
let mut elf_bytes = AlignedMemory::new_with_data(bytes, ebpf::HOST_ALIGN);
Expand All @@ -385,8 +385,10 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {
let mut bpf_functions = BTreeMap::default();
let mut syscall_symbols = BTreeMap::default();
Self::relocate(
&config,
&mut bpf_functions,
&mut syscall_symbols,
&mut syscall_registry,
&elf,
elf_bytes.as_slice_mut(),
)?;
Expand Down Expand Up @@ -539,8 +541,10 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {

/// Relocates the ELF in-place
fn relocate(
config: &Config,
bpf_functions: &mut BTreeMap<u32, (usize, String)>,
syscall_symbols: &mut BTreeMap<u32, String>,
syscall_registry: &mut SyscallRegistry,
elf: &Elf,
elf_bytes: &mut [u8],
) -> Result<(), ElfError> {
Expand Down Expand Up @@ -635,10 +639,20 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {
register_bpf_function(bpf_functions, target_pc, name)?
} else {
// syscall
syscall_cache
let hash = syscall_cache
.entry(sym.st_name)
.or_insert_with(|| (ebpf::hash_symbol_name(name.as_bytes()), name))
.0
.0;
if config.reject_unresolved_syscalls
&& syscall_registry.lookup_syscall(hash).is_none()
{
return Err(ElfError::UnresolvedSymbol(
name.to_string(),
r_offset / ebpf::INSN_SIZE + ebpf::ELF_INSN_DUMP_OFFSET,
r_offset,
));
}
hash
};
let mut checked_slice = elf_bytes
.get_mut(imm_offset..imm_offset.saturating_add(BYTE_LENGTH_IMMEIDATE))
Expand Down
3 changes: 3 additions & 0 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ pub struct Config {
pub enable_instruction_meter: bool,
/// Enable instruction tracing
pub enable_instruction_tracing: bool,
/// Reject ELF files containing syscalls which are not in the SyscallRegistry
pub reject_unresolved_syscalls: bool,
/// Ratio of random no-ops per instruction in JIT (0.0 = OFF)
pub noop_instruction_ratio: f64,
/// Enable disinfection of immediate values and offsets provided by the user in JIT
Expand All @@ -197,6 +199,7 @@ impl Default for Config {
stack_frame_size: 4_096,
enable_instruction_meter: true,
enable_instruction_tracing: false,
reject_unresolved_syscalls: false,
noop_instruction_ratio: 1.0 / 256.0,
sanitize_user_provided_values: true,
encrypt_environment_registers: true,
Expand Down
21 changes: 11 additions & 10 deletions tests/ubpf_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3054,16 +3054,17 @@ fn test_err_call_unresolved() {

#[test]
fn test_err_unresolved_elf() {
test_interpreter_and_jit_elf!(
"tests/elfs/unresolved_syscall.so",
[],
(
b"log" => syscalls::BpfSyscallString::call; syscalls::BpfSyscallString {},
),
{
|_vm, res: Result| matches!(res.unwrap_err(), EbpfError::ElfError(ElfError::UnresolvedSymbol(symbol, pc, offset)) if symbol == "log_64" && pc == 550 && offset == 4168)
},
9
let mut syscall_registry = SyscallRegistry::default();
test_interpreter_and_jit!(register, syscall_registry, b"log" => syscalls::BpfSyscallString::call; syscalls::BpfSyscallString {});
let mut file = File::open("tests/elfs/unresolved_syscall.so").unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let config = Config {
reject_unresolved_syscalls: true,
..Default::default()
};
assert!(
matches!(<dyn Executable::<UserError, TestInstructionMeter>>::from_elf(&elf, None, config, syscall_registry), Err(EbpfError::ElfError(ElfError::UnresolvedSymbol(symbol, pc, offset))) if symbol == "log_64" && pc == 550 && offset == 4168)
);
}

Expand Down

0 comments on commit 49a715d

Please sign in to comment.