From efa6a0a13f7d3238f47b646519ef79eab0c4a403 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 9 Jul 2023 18:29:20 -0400 Subject: [PATCH] Get verifier logs when loading programs --- aya/src/bpf.rs | 86 ++++++++++++++++++++++------------------- aya/src/programs/mod.rs | 39 ++++++++++++------- aya/src/sys/bpf.rs | 14 ++++--- 3 files changed, 82 insertions(+), 57 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 83896b1d..66eca1a6 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -133,7 +133,7 @@ pub struct BpfLoader<'a> { bitflags! { /// Used to set the verifier log level flags in [BpfLoader](BpfLoader::verifier_log_level()). - #[derive(Debug)] + #[derive(Clone, Copy, Debug)] pub struct VerifierLogLevel: u32 { /// Sets no verifier logging. const DISABLE = 0; @@ -349,9 +349,16 @@ impl<'a> BpfLoader<'a> { /// # Ok::<(), aya::BpfError>(()) /// ``` pub fn load(&mut self, data: &[u8]) -> Result { - let verifier_log_level = self.verifier_log_level.bits(); + let Self { + btf, + map_pin_path, + globals, + max_entries, + extensions, + verifier_log_level, + } = self; let mut obj = Object::parse(data)?; - obj.patch_map_data(self.globals.clone())?; + obj.patch_map_data(globals.clone())?; let btf_fd = if let Some(features) = &FEATURES.btf() { if let Some(btf) = obj.fixup_and_sanitize_btf(features)? { @@ -364,7 +371,7 @@ impl<'a> BpfLoader<'a> { None }; - if let Some(btf) = &self.btf { + if let Some(btf) = &btf { obj.relocate_btf(btf)?; } let mut maps = HashMap::new(); @@ -375,7 +382,7 @@ impl<'a> BpfLoader<'a> { continue; } - match self.max_entries.get(name.as_str()) { + match max_entries.get(name.as_str()) { Some(size) => obj.set_max_entries(*size), None => { if obj.map_type() == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 @@ -400,7 +407,7 @@ impl<'a> BpfLoader<'a> { }; let fd = match map.obj.pinning() { PinningType::ByName => { - let path = match &self.map_pin_path { + let path = match &map_pin_path { Some(p) => p, None => return Err(BpfError::NoPinPath), }; @@ -466,72 +473,72 @@ impl<'a> BpfLoader<'a> { let section = prog_obj.section.clone(); let obj = (prog_obj, function_obj); - let program = if self.extensions.contains(name.as_str()) { + let program = if extensions.contains(name.as_str()) { Program::Extension(Extension { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } else { match §ion { ProgramSection::KProbe { .. } => Program::KProbe(KProbe { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: ProbeKind::KProbe, }), ProgramSection::KRetProbe { .. } => Program::KProbe(KProbe { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: ProbeKind::KRetProbe, }), ProgramSection::UProbe { .. } => Program::UProbe(UProbe { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: ProbeKind::UProbe, }), ProgramSection::URetProbe { .. } => Program::UProbe(UProbe { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: ProbeKind::URetProbe, }), ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::SocketFilter { .. } => { Program::SocketFilter(SocketFilter { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } ProgramSection::Xdp { frags, .. } => { let mut data = - ProgramData::new(prog_name, obj, btf_fd, verifier_log_level); + ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); if *frags { data.flags = BPF_F_XDP_HAS_FRAGS; } Program::Xdp(Xdp { data }) } ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::CgroupSysctl { .. } => { Program::CgroupSysctl(CgroupSysctl { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } ProgramSection::CgroupSockopt { attach_type, .. } => { Program::CgroupSockopt(CgroupSockopt { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), attach_type: *attach_type, }) } ProgramSection::SkSkbStreamParser { .. } => Program::SkSkb(SkSkb { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: SkSkbKind::StreamParser, }), ProgramSection::SkSkbStreamVerdict { .. } => Program::SkSkb(SkSkb { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), kind: SkSkbKind::StreamVerdict, }), ProgramSection::SockOps { .. } => Program::SockOps(SockOps { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::SchedClassifier { .. } => { Program::SchedClassifier(SchedClassifier { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), name: unsafe { CString::from_vec_unchecked(Vec::from(name.clone())) .into_boxed_c_str() @@ -539,37 +546,37 @@ impl<'a> BpfLoader<'a> { }) } ProgramSection::CgroupSkb { .. } => Program::CgroupSkb(CgroupSkb { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), expected_attach_type: None, }), ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), expected_attach_type: Some(CgroupSkbAttachType::Ingress), }), ProgramSection::CgroupSkbEgress { .. } => Program::CgroupSkb(CgroupSkb { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), expected_attach_type: Some(CgroupSkbAttachType::Egress), }), ProgramSection::CgroupSockAddr { attach_type, .. } => { Program::CgroupSockAddr(CgroupSockAddr { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), attach_type: *attach_type, }) } ProgramSection::LircMode2 { .. } => Program::LircMode2(LircMode2 { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::PerfEvent { .. } => Program::PerfEvent(PerfEvent { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::RawTracePoint { .. } => { Program::RawTracePoint(RawTracePoint { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } ProgramSection::Lsm { sleepable, .. } => { let mut data = - ProgramData::new(prog_name, obj, btf_fd, verifier_log_level); + ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); if *sleepable { data.flags = BPF_F_SLEEPABLE; } @@ -577,30 +584,30 @@ impl<'a> BpfLoader<'a> { } ProgramSection::BtfTracePoint { .. } => { Program::BtfTracePoint(BtfTracePoint { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } ProgramSection::FEntry { .. } => Program::FEntry(FEntry { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::FExit { .. } => Program::FExit(FExit { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::Extension { .. } => Program::Extension(Extension { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::SkLookup { .. } => Program::SkLookup(SkLookup { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), ProgramSection::CgroupSock { attach_type, .. } => { Program::CgroupSock(CgroupSock { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), attach_type: *attach_type, }) } ProgramSection::CgroupDevice { .. } => { Program::CgroupDevice(CgroupDevice { - data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }) } } @@ -907,8 +914,9 @@ pub enum BpfError { } fn load_btf(raw_btf: Vec) -> Result { - let (ret, verifier_log) = - retry_with_verifier_logs(10, |logger| bpf_load_btf(raw_btf.as_slice(), logger)); + let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| { + bpf_load_btf(raw_btf.as_slice(), logger, VerifierLogLevel::default()) + }); match ret { Ok(fd) => Ok(fd as RawFd), Err((_, io_error)) => Err(BtfError::LoadError { diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 004083d7..c6f30550 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -113,6 +113,7 @@ use crate::{ bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query, retry_with_verifier_logs, BpfLoadProgramAttrs, }, + VerifierLogLevel, }; /// Error type returned when working with programs. @@ -413,7 +414,7 @@ pub(crate) struct ProgramData { pub(crate) attach_btf_id: Option, pub(crate) attach_prog_fd: Option, pub(crate) btf_fd: Option, - pub(crate) verifier_log_level: u32, + pub(crate) verifier_log_level: VerifierLogLevel, pub(crate) path: Option, pub(crate) flags: u32, } @@ -423,7 +424,7 @@ impl ProgramData { name: Option, obj: (obj::Program, obj::Function), btf_fd: Option, - verifier_log_level: u32, + verifier_log_level: VerifierLogLevel, ) -> ProgramData { ProgramData { name, @@ -474,7 +475,7 @@ impl ProgramData { attach_btf_id, attach_prog_fd: None, btf_fd: None, - verifier_log_level: 0, + verifier_log_level: VerifierLogLevel::default(), path: Some(path.to_path_buf()), flags: 0, }) @@ -548,7 +549,20 @@ fn load_program( prog_type: bpf_prog_type, data: &mut ProgramData, ) -> Result<(), ProgramError> { - let ProgramData { obj, fd, .. } = data; + let ProgramData { + name, + obj, + fd, + links: _, + expected_attach_type, + attach_btf_obj_fd, + attach_btf_id, + attach_prog_fd, + btf_fd, + verifier_log_level, + path: _, + flags, + } = data; if fd.is_some() { return Err(ProgramError::AlreadyLoaded); } @@ -581,7 +595,7 @@ fn load_program( _ => (*kernel_version).into(), }; - let prog_name = if let Some(name) = &data.name { + let prog_name = if let Some(name) = name { let mut name = name.clone(); if name.len() > 15 { name.truncate(15); @@ -599,21 +613,20 @@ fn load_program( insns: instructions, license, kernel_version: target_kernel_version, - expected_attach_type: data.expected_attach_type, - prog_btf_fd: data.btf_fd, - attach_btf_obj_fd: data.attach_btf_obj_fd, - attach_btf_id: data.attach_btf_id, - attach_prog_fd: data.attach_prog_fd, + expected_attach_type: *expected_attach_type, + prog_btf_fd: *btf_fd, + attach_btf_obj_fd: *attach_btf_obj_fd, + attach_btf_id: *attach_btf_id, + attach_prog_fd: *attach_prog_fd, func_info_rec_size: *func_info_rec_size, func_info: func_info.clone(), line_info_rec_size: *line_info_rec_size, line_info: line_info.clone(), - flags: data.flags, + flags: *flags, }; - let verifier_log_level = data.verifier_log_level; let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| { - bpf_load_program(&attr, logger, verifier_log_level) + bpf_load_program(&attr, logger, *verifier_log_level) }); match ret { diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index edeaceaa..cd45093b 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -29,7 +29,7 @@ use crate::{ copy_instructions, }, sys::{kernel_version, syscall, SysResult, Syscall}, - Btf, Pod, BPF_OBJ_NAME_LEN, + Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN, }; pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option) -> SysResult { @@ -125,7 +125,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> { pub(crate) fn bpf_load_program( aya_attr: &BpfLoadProgramAttrs, log_buf: &mut [u8], - verifier_log_level: u32, + verifier_log_level: VerifierLogLevel, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; @@ -170,7 +170,7 @@ pub(crate) fn bpf_load_program( } } if !log_buf.is_empty() { - u.log_level = verifier_log_level; + u.log_level = verifier_log_level.bits(); u.log_buf = log_buf.as_mut_ptr() as u64; u.log_size = log_buf.len() as u32; } @@ -543,13 +543,17 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr) } -pub(crate) fn bpf_load_btf(raw_btf: &[u8], log_buf: &mut [u8]) -> SysResult { +pub(crate) fn bpf_load_btf( + raw_btf: &[u8], + log_buf: &mut [u8], + verifier_log_level: VerifierLogLevel, +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_7 }; u.btf = raw_btf.as_ptr() as *const _ as u64; u.btf_size = mem::size_of_val(raw_btf) as u32; if !log_buf.is_empty() { - u.btf_log_level = 1; + u.btf_log_level = verifier_log_level.bits(); u.btf_log_buf = log_buf.as_mut_ptr() as u64; u.btf_log_size = log_buf.len() as u32; }