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