|
|
@ -1,4 +1,5 @@
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
|
|
|
|
borrow::Cow,
|
|
|
|
cmp::{self, min},
|
|
|
|
cmp::{self, min},
|
|
|
|
ffi::{CStr, CString},
|
|
|
|
ffi::{CStr, CString},
|
|
|
|
io,
|
|
|
|
io,
|
|
|
@ -29,7 +30,6 @@ use crate::{
|
|
|
|
copy_instructions,
|
|
|
|
copy_instructions,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
sys::{syscall, SysResult, Syscall},
|
|
|
|
sys::{syscall, SysResult, Syscall},
|
|
|
|
util::VerifierLog,
|
|
|
|
|
|
|
|
Btf, Pod, BPF_OBJ_NAME_LEN,
|
|
|
|
Btf, Pod, BPF_OBJ_NAME_LEN,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -129,7 +129,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_load_program(
|
|
|
|
pub(crate) fn bpf_load_program(
|
|
|
|
aya_attr: &BpfLoadProgramAttrs,
|
|
|
|
aya_attr: &BpfLoadProgramAttrs,
|
|
|
|
logger: &mut VerifierLog,
|
|
|
|
log_buf: &mut [u8],
|
|
|
|
verifier_log_level: u32,
|
|
|
|
verifier_log_level: u32,
|
|
|
|
) -> SysResult {
|
|
|
|
) -> SysResult {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
@ -174,11 +174,10 @@ pub(crate) fn bpf_load_program(
|
|
|
|
u.func_info_rec_size = aya_attr.func_info_rec_size as u32;
|
|
|
|
u.func_info_rec_size = aya_attr.func_info_rec_size as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let log_buf = logger.buf();
|
|
|
|
if !log_buf.is_empty() {
|
|
|
|
if log_buf.capacity() > 0 {
|
|
|
|
|
|
|
|
u.log_level = verifier_log_level;
|
|
|
|
u.log_level = verifier_log_level;
|
|
|
|
u.log_buf = log_buf.as_mut_ptr() as u64;
|
|
|
|
u.log_buf = log_buf.as_mut_ptr() as u64;
|
|
|
|
u.log_size = log_buf.capacity() as u32;
|
|
|
|
u.log_size = log_buf.len() as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(v) = aya_attr.attach_btf_obj_fd {
|
|
|
|
if let Some(v) = aya_attr.attach_btf_obj_fd {
|
|
|
|
u.__bindgen_anon_1.attach_btf_obj_fd = v;
|
|
|
|
u.__bindgen_anon_1.attach_btf_obj_fd = v;
|
|
|
@ -549,16 +548,15 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy
|
|
|
|
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> SysResult {
|
|
|
|
pub(crate) fn bpf_load_btf(raw_btf: &[u8], log_buf: &mut [u8]) -> SysResult {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_7 };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_7 };
|
|
|
|
u.btf = raw_btf.as_ptr() as *const _ as u64;
|
|
|
|
u.btf = raw_btf.as_ptr() as *const _ as u64;
|
|
|
|
u.btf_size = mem::size_of_val(raw_btf) as u32;
|
|
|
|
u.btf_size = mem::size_of_val(raw_btf) as u32;
|
|
|
|
let log_buf = log.buf();
|
|
|
|
if !log_buf.is_empty() {
|
|
|
|
if log_buf.capacity() > 0 {
|
|
|
|
|
|
|
|
u.btf_log_level = 1;
|
|
|
|
u.btf_log_level = 1;
|
|
|
|
u.btf_log_buf = log_buf.as_mut_ptr() as u64;
|
|
|
|
u.btf_log_buf = log_buf.as_mut_ptr() as u64;
|
|
|
|
u.btf_log_size = log_buf.capacity() as u32;
|
|
|
|
u.btf_log_size = log_buf.len() as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -993,35 +991,41 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, (c_long, io::
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn retry_with_verifier_logs<F>(
|
|
|
|
pub(crate) fn retry_with_verifier_logs<F>(
|
|
|
|
max_retries: usize,
|
|
|
|
max_retries: usize,
|
|
|
|
log: &mut VerifierLog,
|
|
|
|
|
|
|
|
f: F,
|
|
|
|
f: F,
|
|
|
|
) -> SysResult
|
|
|
|
) -> (SysResult, Cow<'static, str>)
|
|
|
|
where
|
|
|
|
where
|
|
|
|
F: Fn(&mut VerifierLog) -> SysResult,
|
|
|
|
F: Fn(&mut [u8]) -> SysResult,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 1. Try the syscall
|
|
|
|
const MIN_LOG_BUF_SIZE: usize = 1024 * 10;
|
|
|
|
let ret = f(log);
|
|
|
|
const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize;
|
|
|
|
if ret.is_ok() {
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Grow the log buffer so we can capture verifier output
|
|
|
|
let mut log_buf = Vec::new();
|
|
|
|
// Retry this up to max_retries times
|
|
|
|
|
|
|
|
log.grow();
|
|
|
|
|
|
|
|
let mut retries = 0;
|
|
|
|
let mut retries = 0;
|
|
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
loop {
|
|
|
|
let ret = f(log);
|
|
|
|
let ret = f(log_buf.as_mut_slice());
|
|
|
|
match ret {
|
|
|
|
if retries != max_retries {
|
|
|
|
Err((v, io_error)) if retries == 0 || io_error.raw_os_error() == Some(ENOSPC) => {
|
|
|
|
if let Err((_, io_error)) = &ret {
|
|
|
|
if retries == max_retries {
|
|
|
|
if retries == 0 || io_error.raw_os_error() == Some(ENOSPC) {
|
|
|
|
return Err((v, io_error));
|
|
|
|
let len = (log_buf.capacity() * 10).clamp(MIN_LOG_BUF_SIZE, MAX_LOG_BUF_SIZE);
|
|
|
|
|
|
|
|
log_buf.resize(len, 0);
|
|
|
|
|
|
|
|
if let Some(first) = log_buf.first_mut() {
|
|
|
|
|
|
|
|
*first = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
retries += 1;
|
|
|
|
retries += 1;
|
|
|
|
log.grow();
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r => return r,
|
|
|
|
if let Some(pos) = log_buf.iter().position(|b| *b == 0) {
|
|
|
|
|
|
|
|
log_buf.truncate(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let log_buf = if log_buf.is_empty() {
|
|
|
|
|
|
|
|
"none".into()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
String::from_utf8(log_buf).unwrap().into()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break (ret, log_buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|