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),
|
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> {
|
fn check_prog_len(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
|
||||||
if prog.len() % ebpf::INSN_SIZE != 0 {
|
if prog.len() % ebpf::INSN_SIZE != 0 {
|
||||||
return Err(VerifierError::ProgramLengthNotMultiple.into());
|
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> {
|
fn check_imm_nonzero(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BPFError> {
|
||||||
if insn.imm == 0 {
|
if insn.imm == 0 {
|
||||||
return Err(VerifierError::DivisionByZero(insn_ptr).into());
|
return Err(VerifierError::DivisionByZero(adj_insn_ptr(insn_ptr)).into());
|
||||||
}
|
}
|
||||||
Ok(())
|
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> {
|
fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), BPFError> {
|
||||||
match insn.imm {
|
match insn.imm {
|
||||||
16 | 32 | 64 => Ok(()),
|
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);
|
let next_insn = ebpf::get_insn(prog, insn_ptr + 1);
|
||||||
if next_insn.opc != 0 {
|
if next_insn.opc != 0 {
|
||||||
return Err(VerifierError::IncompleteLDDW(insn_ptr).into());
|
return Err(VerifierError::IncompleteLDDW(adj_insn_ptr(insn_ptr)).into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_jmp_offset(prog: &[u8], insn_ptr: usize) -> Result<(), BPFError> {
|
fn check_jmp_offset(prog: &[u8], insn_ptr: usize) -> Result<(), BPFError> {
|
||||||
let insn = ebpf::get_insn(prog, insn_ptr);
|
let insn = ebpf::get_insn(prog, insn_ptr);
|
||||||
if insn.off == -1 {
|
// if insn.off == -1 {
|
||||||
return Err(VerifierError::InfiniteLoop(insn_ptr).into());
|
// return Err(VerifierError::InfiniteLoop(adj_insn_ptr(insn_ptr)).into());
|
||||||
}
|
// }
|
||||||
|
|
||||||
let dst_insn_ptr = insn_ptr as isize + 1 + insn.off as isize;
|
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) {
|
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);
|
let dst_insn = ebpf::get_insn(prog, dst_insn_ptr as usize);
|
||||||
if dst_insn.opc == 0 {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<(), BPFError> {
|
fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<(), BPFError> {
|
||||||
if insn.src > 10 {
|
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) {
|
match (insn.dst, store) {
|
||||||
(0..=9, _) | (10, true) => Ok(()),
|
(0..=9, _) | (10, true) => Ok(()),
|
||||||
(10, false) => Err(VerifierError::CannotWriteR10(insn_ptr).into()),
|
(10, false) => Err(VerifierError::CannotWriteR10(adj_insn_ptr(insn_ptr)).into()),
|
||||||
(_, _) => Err(VerifierError::InvalidDestinationRegister(insn_ptr).into()),
|
(_, _) => Err(VerifierError::InvalidDestinationRegister(adj_insn_ptr(insn_ptr)).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the imm is a valid shift operand
|
/// Check that the imm is a valid shift operand
|
||||||
fn check_imm_shift(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
fn check_imm_shift(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
||||||
if insn.imm < 0 || insn.imm as u64 >= 64 {
|
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(())
|
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
|
/// Check that the imm is a valid register number
|
||||||
fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
|
||||||
if insn.imm < 0 || insn.imm > 10 {
|
if insn.imm < 0 || insn.imm > 10 {
|
||||||
return Err(VerifierError::InvalidRegister(insn_ptr));
|
return Err(VerifierError::InvalidRegister(adj_insn_ptr(insn_ptr)));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -268,7 +278,7 @@ pub fn check(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> {
|
||||||
ebpf::EXIT => {},
|
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.
|
// insn_ptr should now be equal to number of instructions.
|
||||||
if insn_ptr != prog.len() / ebpf::INSN_SIZE {
|
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(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue