Match BPF instruction reporting to dump file (#15254)
This commit is contained in:
parent
e59a24d9f9
commit
10abd199e1
|
@ -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(())
|
||||
|
|
Loading…
Reference in New Issue