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

Fix LDDW Related Bugs #140

Merged
merged 4 commits into from
Feb 12, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixes jumps close to the end of the program landing in exception hand…
…lers if lddw instructions are present (in JIT compiler).

Also updates test_large_program() accordingly.
  • Loading branch information
Lichtso committed Feb 12, 2021
commit 0f34e650b455a568d8e11158dfcc0d53e23c610c
27 changes: 13 additions & 14 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,19 @@ impl<E: UserDefinedError, I: InstructionMeter> PartialEq for JitProgram<E, I> {
}

// Special values for target_pc in struct Jump
const TARGET_OFFSET: usize = ebpf::PROG_MAX_INSNS;
const TARGET_PC_TRACE: usize = TARGET_OFFSET + 1;
const TARGET_PC_TRANSLATE_PC: usize = TARGET_OFFSET + 2;
const TARGET_PC_TRANSLATE_PC_LOOP: usize = TARGET_OFFSET + 3;
const TARGET_PC_CALL_EXCEEDED_MAX_INSTRUCTIONS: usize = TARGET_OFFSET + 4;
const TARGET_PC_CALL_DEPTH_EXCEEDED: usize = TARGET_OFFSET + 5;
const TARGET_PC_CALL_OUTSIDE_TEXT_SEGMENT: usize = TARGET_OFFSET + 6;
const TARGET_PC_CALLX_UNSUPPORTED_INSTRUCTION: usize = TARGET_OFFSET + 7;
const TARGET_PC_CALL_UNSUPPORTED_INSTRUCTION: usize = TARGET_OFFSET + 8;
const TARGET_PC_DIV_BY_ZERO: usize = TARGET_OFFSET + 9;
const TARGET_PC_EXCEPTION_AT: usize = TARGET_OFFSET + 10;
const TARGET_PC_SYSCALL_EXCEPTION: usize = TARGET_OFFSET + 11;
const TARGET_PC_EXIT: usize = TARGET_OFFSET + 12;
const TARGET_PC_EPILOGUE: usize = TARGET_OFFSET + 13;
const TARGET_PC_TRACE: usize = std::usize::MAX - 13;
const TARGET_PC_TRANSLATE_PC: usize = std::usize::MAX - 12;
const TARGET_PC_TRANSLATE_PC_LOOP: usize = std::usize::MAX - 11;
const TARGET_PC_CALL_EXCEEDED_MAX_INSTRUCTIONS: usize = std::usize::MAX - 10;
const TARGET_PC_CALL_DEPTH_EXCEEDED: usize = std::usize::MAX - 9;
const TARGET_PC_CALL_OUTSIDE_TEXT_SEGMENT: usize = std::usize::MAX - 8;
const TARGET_PC_CALLX_UNSUPPORTED_INSTRUCTION: usize = std::usize::MAX - 7;
const TARGET_PC_CALL_UNSUPPORTED_INSTRUCTION: usize = std::usize::MAX - 6;
const TARGET_PC_DIV_BY_ZERO: usize = std::usize::MAX - 5;
const TARGET_PC_EXCEPTION_AT: usize = std::usize::MAX - 4;
const TARGET_PC_SYSCALL_EXCEPTION: usize = std::usize::MAX - 3;
const TARGET_PC_EXIT: usize = std::usize::MAX - 2;
const TARGET_PC_EPILOGUE: usize = std::usize::MAX - 1;

#[derive(Copy, Clone)]
enum OperandSize {
Expand Down
76 changes: 28 additions & 48 deletions tests/ubpf_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3221,74 +3221,54 @@ fn test_tcp_sack_nomatch() {

#[test]
fn test_large_program() {
fn write_insn(prog: &mut [u8], insn: usize, asm: &str) {
prog[insn * ebpf::INSN_SIZE..insn * ebpf::INSN_SIZE + ebpf::INSN_SIZE]
.copy_from_slice(&assemble(asm).unwrap());
fn write_insn(prog: &mut [u8], index: usize, asm: &str) {
let insn = assemble(asm).unwrap();
prog[index * ebpf::INSN_SIZE..index * ebpf::INSN_SIZE + insn.len()].copy_from_slice(&insn);
}

let mut prog = vec![0; ebpf::PROG_MAX_INSNS * ebpf::INSN_SIZE];
let mut add_insn = vec![0; ebpf::INSN_SIZE];
write_insn(&mut add_insn, 0, "mov64 r0, 0");
for insn in (0..(ebpf::PROG_MAX_INSNS - 1) * ebpf::INSN_SIZE).step_by(ebpf::INSN_SIZE) {
prog[insn..insn + ebpf::INSN_SIZE].copy_from_slice(&add_insn);
let mut prog = vec![0; (ebpf::PROG_MAX_INSNS * 2 - 1) * ebpf::INSN_SIZE];
let mut insn = vec![0; ebpf::INSN_SIZE * 2];
write_insn(&mut insn, 0, "lddw r0, 0");
for index in (0..(ebpf::PROG_MAX_INSNS - 1) * ebpf::INSN_SIZE * 2).step_by(ebpf::INSN_SIZE * 2)
{
prog[index..index + ebpf::INSN_SIZE * 2].copy_from_slice(&insn);
}
write_insn(&mut prog, ebpf::PROG_MAX_INSNS - 1, "exit");
write_insn(&mut prog, ebpf::PROG_MAX_INSNS - 4, "ja 9");
write_insn(&mut prog, ebpf::PROG_MAX_INSNS - 3, "mov r0, 0");
write_insn(&mut prog, ebpf::PROG_MAX_INSNS * 2 - 2, "exit");

{
// Test jumping to pc larger then i16
write_insn(&mut prog, ebpf::PROG_MAX_INSNS - 2, "ja 0x0");
let config = Config {
enable_instruction_tracing: true,
..Config::default()
};

let executable = Executable::<UserError, DefaultInstructionMeter>::from_text_bytes(
&prog,
None,
Config::default(),
)
.unwrap();
let mut vm =
EbpfVm::<UserError, DefaultInstructionMeter>::new(executable.as_ref(), &mut [], &[])
#[allow(unused_mut)]
{
let mut executable =
Executable::<UserError, TestInstructionMeter>::from_text_bytes(&prog, None, config)
.unwrap();
assert_eq!(
0,
vm.execute_program_interpreted(&mut DefaultInstructionMeter {})
.unwrap()
test_interpreter_and_jit!(
executable,
[],
(),
{ |_vm, res: Result| res.unwrap() == 0x0 },
ebpf::PROG_MAX_INSNS as u64 - 4
);
}
// reset program
write_insn(&mut prog, ebpf::PROG_MAX_INSNS - 2, "mov64 r0, 0");

{
// test program that is too large
// Test program that is too large
prog.extend_from_slice(&assemble("exit").unwrap());

assert!(
Executable::<UserError, DefaultInstructionMeter>::from_text_bytes(
&prog,
Some(check),
Config::default()
config,
)
.is_err()
);
}
// reset program
prog.truncate(ebpf::PROG_MAX_INSNS * ebpf::INSN_SIZE);

// verify program still works
#[allow(unused_mut)]
{
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(
&prog,
None,
Config::default(),
)
.unwrap();
test_interpreter_and_jit!(
executable,
[],
(),
{ |_vm, res: Result| res.unwrap() == 0x0 },
ebpf::PROG_MAX_INSNS as u64
);
}
}

// Fuzzy
Expand Down