|
|
@ -64,7 +64,6 @@ pub mod uprobe;
|
|
|
|
mod utils;
|
|
|
|
mod utils;
|
|
|
|
pub mod xdp;
|
|
|
|
pub mod xdp;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::util::KernelVersion;
|
|
|
|
|
|
|
|
use libc::ENOSPC;
|
|
|
|
use libc::ENOSPC;
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
ffi::CString,
|
|
|
|
ffi::CString,
|
|
|
@ -112,8 +111,9 @@ use crate::{
|
|
|
|
sys::{
|
|
|
|
sys::{
|
|
|
|
bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
|
|
|
|
bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
|
|
|
|
bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query,
|
|
|
|
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,
|
|
|
|
retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
util::KernelVersion,
|
|
|
|
VerifierLogLevel,
|
|
|
|
VerifierLogLevel,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -147,14 +147,8 @@ pub enum ProgramError {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/// A syscall failed.
|
|
|
|
/// A syscall failed.
|
|
|
|
#[error("`{call}` failed")]
|
|
|
|
#[error(transparent)]
|
|
|
|
SyscallError {
|
|
|
|
SyscallError(#[from] SyscallError),
|
|
|
|
/// The name of the syscall which failed.
|
|
|
|
|
|
|
|
call: &'static str,
|
|
|
|
|
|
|
|
/// The [`io::Error`] returned by the syscall.
|
|
|
|
|
|
|
|
#[source]
|
|
|
|
|
|
|
|
io_error: io::Error,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The network interface does not exist.
|
|
|
|
/// The network interface does not exist.
|
|
|
|
#[error("unknown network interface {name}")]
|
|
|
|
#[error("unknown network interface {name}")]
|
|
|
@ -456,12 +450,11 @@ impl<T: Link> ProgramData<T> {
|
|
|
|
None
|
|
|
|
None
|
|
|
|
};
|
|
|
|
};
|
|
|
|
let attach_btf_obj_fd = if info.attach_btf_obj_id > 0 {
|
|
|
|
let attach_btf_obj_fd = if info.attach_btf_obj_id > 0 {
|
|
|
|
let fd = bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| {
|
|
|
|
let fd =
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| SyscallError {
|
|
|
|
call: "bpf_btf_get_fd_by_id",
|
|
|
|
call: "bpf_btf_get_fd_by_id",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Some(fd as u32)
|
|
|
|
Some(fd as u32)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
None
|
|
|
@ -489,13 +482,12 @@ impl<T: Link> ProgramData<T> {
|
|
|
|
) -> Result<ProgramData<T>, ProgramError> {
|
|
|
|
) -> Result<ProgramData<T>, ProgramError> {
|
|
|
|
let path_string =
|
|
|
|
let path_string =
|
|
|
|
CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap();
|
|
|
|
CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap();
|
|
|
|
let fd =
|
|
|
|
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
|
|
|
|
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
|
|
|
|
call: "bpf_obj_get",
|
|
|
|
call: "bpf_obj_get",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})? as RawFd;
|
|
|
|
})? as RawFd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError {
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
@ -537,8 +529,8 @@ fn pin_program<T: Link, P: AsRef<Path>>(data: &ProgramData<T>, path: P) -> Resul
|
|
|
|
error: e.to_string(),
|
|
|
|
error: e.to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
|
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
|
|
|
|
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| SyscallError {
|
|
|
|
name: "BPF_OBJ_PIN",
|
|
|
|
call: "BPF_OBJ_PIN",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
@ -665,15 +657,17 @@ pub(crate) fn query<T: AsRawFd>(
|
|
|
|
prog_ids.resize(prog_cnt as usize, 0);
|
|
|
|
prog_ids.resize(prog_cnt as usize, 0);
|
|
|
|
return Ok(prog_ids);
|
|
|
|
return Ok(prog_ids);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err((_, io_error)) if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) => {
|
|
|
|
|
|
|
|
prog_ids.resize(prog_cnt as usize, 0);
|
|
|
|
|
|
|
|
retries += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Err((_, io_error)) => {
|
|
|
|
Err((_, io_error)) => {
|
|
|
|
return Err(ProgramError::SyscallError {
|
|
|
|
if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) {
|
|
|
|
call: "bpf_prog_query",
|
|
|
|
prog_ids.resize(prog_cnt as usize, 0);
|
|
|
|
io_error,
|
|
|
|
retries += 1;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return Err(SyscallError {
|
|
|
|
|
|
|
|
call: "bpf_prog_query",
|
|
|
|
|
|
|
|
io_error,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.into());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -951,24 +945,22 @@ impl ProgramInfo {
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// The returned fd must be closed when no longer needed.
|
|
|
|
/// The returned fd must be closed when no longer needed.
|
|
|
|
pub fn fd(&self) -> Result<RawFd, ProgramError> {
|
|
|
|
pub fn fd(&self) -> Result<RawFd, ProgramError> {
|
|
|
|
let fd =
|
|
|
|
let fd = bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| SyscallError {
|
|
|
|
bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(fd.into_raw_fd())
|
|
|
|
Ok(fd.into_raw_fd())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Loads a program from a pinned path in bpffs.
|
|
|
|
/// Loads a program from a pinned path in bpffs.
|
|
|
|
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<ProgramInfo, ProgramError> {
|
|
|
|
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<ProgramInfo, ProgramError> {
|
|
|
|
let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap();
|
|
|
|
let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap();
|
|
|
|
let fd =
|
|
|
|
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
|
|
|
|
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
|
|
|
|
call: "BPF_OBJ_GET",
|
|
|
|
call: "BPF_OBJ_GET",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})? as RawFd;
|
|
|
|
})? as RawFd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError {
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
@ -999,18 +991,19 @@ impl Iterator for ProgramsIter {
|
|
|
|
self.current = next;
|
|
|
|
self.current = next;
|
|
|
|
Some(
|
|
|
|
Some(
|
|
|
|
bpf_prog_get_fd_by_id(next)
|
|
|
|
bpf_prog_get_fd_by_id(next)
|
|
|
|
.map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
.map_err(|io_error| SyscallError {
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.and_then(|fd| {
|
|
|
|
.and_then(|fd| {
|
|
|
|
bpf_prog_get_info_by_fd(fd.as_raw_fd())
|
|
|
|
bpf_prog_get_info_by_fd(fd.as_raw_fd())
|
|
|
|
.map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
.map_err(|io_error| SyscallError {
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
call: "bpf_prog_get_info_by_fd",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(ProgramInfo)
|
|
|
|
.map(ProgramInfo)
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
|
|
|
|
.map_err(Into::into),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(None) => None,
|
|
|
|
Ok(None) => None,
|
|
|
@ -1018,10 +1011,11 @@ impl Iterator for ProgramsIter {
|
|
|
|
// If getting the next program failed, we have to yield None in our next
|
|
|
|
// If getting the next program failed, we have to yield None in our next
|
|
|
|
// iteration to avoid an infinite loop.
|
|
|
|
// iteration to avoid an infinite loop.
|
|
|
|
self.error = true;
|
|
|
|
self.error = true;
|
|
|
|
Some(Err(ProgramError::SyscallError {
|
|
|
|
Some(Err(SyscallError {
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
.into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|