Get verifier logs when loading programs

pull/641/head
Tamir Duberstein 1 year ago
parent 6b94b2080d
commit b45a5bb71b
No known key found for this signature in database

@ -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,14 +349,22 @@ impl<'a> BpfLoader<'a> {
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn load(&mut self, data: &[u8]) -> Result<Bpf, BpfError> {
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)? {
// load btf to the kernel
Some(load_btf(btf.to_bytes())?)
let btf = load_btf(btf.to_bytes(), *verifier_log_level)?;
Some(btf)
} else {
None
}
@ -364,7 +372,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 +383,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 +408,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 +474,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 &section {
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 +547,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 +585,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),
})
}
}
@ -906,9 +914,10 @@ pub enum BpfError {
ProgramError(#[from] ProgramError),
}
fn load_btf(raw_btf: Vec<u8>) -> Result<RawFd, BtfError> {
let (ret, verifier_log) =
retry_with_verifier_logs(10, |logger| bpf_load_btf(raw_btf.as_slice(), logger));
fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<RawFd, BtfError> {
let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| {
bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level)
});
match ret {
Ok(fd) => Ok(fd as RawFd),
Err((_, io_error)) => Err(BtfError::LoadError {

@ -16,6 +16,7 @@ use crate::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
VerifierLogLevel,
};
/// A program used to inspect or filter network activity for a given cgroup.
@ -151,7 +152,7 @@ impl CgroupSkb {
path: P,
expected_attach_type: CgroupSkbAttachType,
) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self {
data,
expected_attach_type: Some(expected_attach_type),

@ -15,6 +15,7 @@ use crate::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
VerifierLogLevel,
};
/// A program that is called on socket creation, bind and release.
@ -126,7 +127,7 @@ impl CgroupSock {
path: P,
attach_type: CgroupSockAttachType,
) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, attach_type })
}
}

@ -15,6 +15,7 @@ use crate::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
VerifierLogLevel,
};
/// A program that can be used to inspect or modify socket addresses (`struct sockaddr`).
@ -132,7 +133,7 @@ impl CgroupSockAddr {
path: P,
attach_type: CgroupSockAddrAttachType,
) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, attach_type })
}
}

@ -15,6 +15,7 @@ use crate::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
VerifierLogLevel,
};
/// A program that can be used to get or set options on sockets.
@ -127,7 +128,7 @@ impl CgroupSockopt {
path: P,
attach_type: CgroupSockoptAttachType,
) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, attach_type })
}
}

@ -10,6 +10,7 @@ use crate::{
probe::{attach, ProbeKind},
ProgramData, ProgramError,
},
VerifierLogLevel,
};
/// A kernel probe.
@ -91,7 +92,7 @@ impl KProbe {
/// On drop, any managed links are detached and the program is unloaded. This will not result in
/// the program being unloaded from the kernel if it is still pinned.
pub fn from_pin<P: AsRef<Path>>(path: P, kind: ProbeKind) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, kind })
}
}

@ -114,6 +114,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.
@ -414,7 +415,7 @@ pub(crate) struct ProgramData<T: Link> {
pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>,
pub(crate) verifier_log_level: u32,
pub(crate) verifier_log_level: VerifierLogLevel,
pub(crate) path: Option<PathBuf>,
pub(crate) flags: u32,
}
@ -424,7 +425,7 @@ impl<T: Link> ProgramData<T> {
name: Option<String>,
obj: (obj::Program, obj::Function),
btf_fd: Option<RawFd>,
verifier_log_level: u32,
verifier_log_level: VerifierLogLevel,
) -> ProgramData<T> {
ProgramData {
name,
@ -447,6 +448,7 @@ impl<T: Link> ProgramData<T> {
fd: RawFd,
path: &Path,
info: bpf_prog_info,
verifier_log_level: VerifierLogLevel,
) -> Result<ProgramData<T>, ProgramError> {
let attach_btf_id = if info.attach_btf_id > 0 {
Some(info.attach_btf_id)
@ -475,7 +477,7 @@ impl<T: Link> ProgramData<T> {
attach_btf_id,
attach_prog_fd: None,
btf_fd: None,
verifier_log_level: 0,
verifier_log_level,
path: Some(path.to_path_buf()),
flags: 0,
})
@ -483,6 +485,7 @@ impl<T: Link> ProgramData<T> {
pub(crate) fn from_pinned_path<P: AsRef<Path>>(
path: P,
verifier_log_level: VerifierLogLevel,
) -> Result<ProgramData<T>, ProgramError> {
let path_string =
CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap();
@ -497,9 +500,8 @@ impl<T: Link> ProgramData<T> {
io_error,
})?;
let info = ProgramInfo(info);
let name = info.name_as_str().map(|s| s.to_string());
ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info.0)
let name = ProgramInfo(info).name_as_str().map(|s| s.to_string());
ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info, verifier_log_level)
}
}
@ -549,7 +551,20 @@ fn load_program<T: Link>(
prog_type: bpf_prog_type,
data: &mut ProgramData<T>,
) -> 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);
}
@ -583,7 +598,7 @@ fn load_program<T: Link>(
(u32::from(major) << 16) + (u32::from(minor) << 8) + u32::from(patch)
});
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);
@ -601,21 +616,20 @@ fn load_program<T: Link>(
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 {
@ -823,7 +837,7 @@ macro_rules! impl_from_pin {
/// On drop, any managed links are detached and the program is unloaded. This will not result in
/// the program being unloaded from the kernel if it is still pinned.
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data })
}
}

@ -13,6 +13,7 @@ use crate::{
ProgramError,
},
sys::bpf_prog_attach,
VerifierLogLevel,
};
/// The kind of [`SkSkb`] program.
@ -113,7 +114,7 @@ impl SkSkb {
/// On drop, any managed links are detached and the program is unloaded. This will not result in
/// the program being unloaded from the kernel if it is still pinned.
pub fn from_pin<P: AsRef<Path>>(path: P, kind: SkSkbKind) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, kind })
}
}

@ -17,6 +17,7 @@ use crate::{
netlink_qdisc_detach,
},
util::{ifindex_from_ifname, tc_handler_make},
VerifierLogLevel,
};
/// Traffic control attach type.
@ -199,7 +200,7 @@ impl SchedClassifier {
/// On drop, any managed links are detached and the program is unloaded. This will not result in
/// the program being unloaded from the kernel if it is still pinned.
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
let cname = CString::new(data.name.clone().unwrap_or_default())
.unwrap()
.into_boxed_c_str();

@ -21,6 +21,7 @@ use crate::{
probe::{attach, ProbeKind},
ProgramData, ProgramError,
},
VerifierLogLevel,
};
const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache";
@ -145,7 +146,7 @@ impl UProbe {
/// On drop, any managed links are detached and the program is unloaded. This will not result in
/// the program being unloaded from the kernel if it is still pinned.
pub fn from_pin<P: AsRef<Path>>(path: P, kind: ProbeKind) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path)?;
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, kind })
}
}

@ -30,7 +30,7 @@ use crate::{
copy_instructions,
},
sys::{syscall, SysResult, Syscall},
Btf, Pod, BPF_OBJ_NAME_LEN,
Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN,
};
pub(crate) fn bpf_create_map(
@ -130,7 +130,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::<bpf_attr>() };
@ -175,7 +175,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;
}
@ -548,13 +548,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::<bpf_attr>() };
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;
}

Loading…
Cancel
Save