bpf: Better Usdt error handling

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/329/head
Dave Tucker 2 years ago
parent 68ca1e1f3f
commit 0a5ac655de

@ -28,6 +28,15 @@ pub struct UsdtContext {
pub regs: *mut pt_regs, pub regs: *mut pt_regs,
} }
/// Errors from Usdt map operations
#[derive(Debug, Clone)]
pub enum UsdtError {
MaxArgCount,
SpecIdNotFound,
ValueError,
IpNotFound,
}
impl UsdtContext { impl UsdtContext {
/// Creates a new Usdtcontext. /// Creates a new Usdtcontext.
pub fn new(ctx: *mut c_void) -> UsdtContext { pub fn new(ctx: *mut c_void) -> UsdtContext {
@ -52,9 +61,13 @@ impl UsdtContext {
/// Access the spec_id using the `USDT_IP_TO_SPEC_ID` map /// Access the spec_id using the `USDT_IP_TO_SPEC_ID` map
#[cfg(not(feature = "cookie"))] #[cfg(not(feature = "cookie"))]
#[inline(always)] #[inline(always)]
fn spec_id(&self) -> Result<u32, ()> { fn spec_id(&self) -> Result<u32, UsdtError> {
let ip: i64 = self.ip().ok_or(())?; let ip: i64 = self.ip().ok_or(UsdtError::IpNotFound)?;
let spec = unsafe { USDT_IP_TO_SPEC_ID.get(&ip).ok_or(())? }; let spec = unsafe {
USDT_IP_TO_SPEC_ID
.get(&ip)
.ok_or(UsdtError::SpecIdNotFound)?
};
Ok(*spec) Ok(*spec)
} }
@ -63,15 +76,15 @@ impl UsdtContext {
/// This uses the USDT_SPEC_MAP to determine the correct specification to use in order /// This uses the USDT_SPEC_MAP to determine the correct specification to use in order
/// to read the value of argument `n` from the eBPF Context. /// to read the value of argument `n` from the eBPF Context.
#[inline(always)] #[inline(always)]
pub fn arg(&self, n: usize) -> Result<u64, ()> { pub fn arg(&self, n: usize) -> Result<u64, UsdtError> {
if n > USDT_MAX_ARG_COUNT { if n > USDT_MAX_ARG_COUNT {
return Err(()); return Err(UsdtError::MaxArgCount);
} }
let spec_id = self.spec_id()?; let spec_id = self.spec_id()?;
let spec = USDT_SPECS.get(spec_id).ok_or(())?; let spec = USDT_SPECS.get(spec_id).ok_or(UsdtError::SpecIdNotFound)?;
if n > (spec.arg_count as usize) { if n > (spec.arg_count as usize) {
return Err(()); return Err(UsdtError::MaxArgCount);
} }
let arg_spec = &spec.args[n]; let arg_spec = &spec.args[n];
@ -79,15 +92,16 @@ impl UsdtContext {
UsdtArgType::Const => arg_spec.val_off, UsdtArgType::Const => arg_spec.val_off,
UsdtArgType::Reg => unsafe { UsdtArgType::Reg => unsafe {
bpf_probe_read_kernel(self.as_ptr().offset(arg_spec.reg_off as isize) as *const _) bpf_probe_read_kernel(self.as_ptr().offset(arg_spec.reg_off as isize) as *const _)
.map_err(|_| ())? .map_err(|_| UsdtError::ValueError)?
}, },
UsdtArgType::RegDeref => unsafe { UsdtArgType::RegDeref => unsafe {
let ptr: u64 = bpf_probe_read_kernel( let ptr: u64 = bpf_probe_read_kernel(
self.as_ptr().offset(arg_spec.reg_off as isize) as *const _, self.as_ptr().offset(arg_spec.reg_off as isize) as *const _,
) )
.map_err(|_| ())?; .map_err(|_| UsdtError::ValueError)?;
let ptr = ptr as *const u64; let ptr = ptr as *const u64;
bpf_probe_read_user::<u64>(ptr.offset(arg_spec.val_off as isize)).map_err(|_| ())? bpf_probe_read_user::<u64>(ptr.offset(arg_spec.val_off as isize))
.map_err(|_| UsdtError::ValueError)?
// TODO: libbpf applies a bitshift here if the arch is big endian // TODO: libbpf applies a bitshift here if the arch is big endian
}, },
}; };

Loading…
Cancel
Save