Match BPF instruction reporting to dump file (#15254)

This commit is contained in:
Jack May 2021-02-10 16:48:19 -08:00 committed by GitHub
parent e59a24d9f9
commit 10abd199e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 15 deletions

View File

@ -54,6 +54,10 @@ pub enum VerifierError {
InvalidRegister(usize),
}
fn adj_insn_ptr(insn_ptr: usize) -> usize {
insn_ptr + ebpf::ELF_INSN_DUMP_OFFSET
}
fn check_prog_len(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
if prog.len() % ebpf::INSN_SIZE != 0 {
return Err(VerifierError::ProgramLengthNotMultiple.into());
@ -70,7 +74,7 @@ fn check_prog_len(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError
fn check_imm_nonzero(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BPFError> {
if insn.imm == 0 {
return Err(VerifierError::DivisionByZero(insn_ptr).into());
return Err(VerifierError::DivisionByZero(adj_insn_ptr(insn_ptr)).into());
}
Ok(())
}
@ -78,7 +82,7 @@ fn check_imm_nonzero(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BPFError>
fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BPFError> {
match insn.imm {
16 | 32 | 64 => Ok(()),
_ => Err(VerifierError::UnsupportedLEBEArgument(insn_ptr).into()),
_ => Err(VerifierError::UnsupportedLEBEArgument(adj_insn_ptr(insn_ptr)).into()),
}
}
@ -89,43 +93,49 @@ fn check_load_dw(prog: &[u8], insn_ptr: usize) -> Result<(), BPFError> {
}
let next_insn = ebpf::get_insn(prog, insn_ptr + 1);
if next_insn.opc != 0 {
return Err(VerifierError::IncompleteLDDW(insn_ptr).into());
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(insn_ptr).into());
}
// 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, insn_ptr).into());
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, insn_ptr).into());
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(insn_ptr).into());
return Err(VerifierError::InvalidSourceRegister(adj_insn_ptr(insn_ptr)).into());
}
match (insn.dst, store) {
(0..=9, _) | (10, true) => Ok(()),
(10, false) => Err(VerifierError::CannotWriteR10(insn_ptr).into()),
(_, _) => Err(VerifierError::InvalidDestinationRegister(insn_ptr).into()),
(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(insn_ptr));
return Err(VerifierError::ShiftWithOverflow(adj_insn_ptr(insn_ptr)));
}
Ok(())
}
@ -133,7 +143,7 @@ fn check_imm_shift(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierErr
/// 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(insn_ptr));
return Err(VerifierError::InvalidRegister(adj_insn_ptr(insn_ptr)));
}
Ok(())
}
@ -268,7 +278,7 @@ pub fn check(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
ebpf::EXIT => {},
_ => {
return Err(VerifierError::UnknownOpCode(insn.opc, insn_ptr).into());
return Err(VerifierError::UnknownOpCode(insn.opc, adj_insn_ptr(insn_ptr)).into());
}
}
@ -279,7 +289,7 @@ pub fn check(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
// insn_ptr should now be equal to number of instructions.
if insn_ptr != prog.len() / ebpf::INSN_SIZE {
return Err(VerifierError::JumpOutOfCode(insn_ptr, insn_ptr).into());
return Err(VerifierError::JumpOutOfCode(adj_insn_ptr(insn_ptr), adj_insn_ptr(insn_ptr)).into());
}
Ok(())