|
|
@ -1,7 +1,7 @@
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
cmp::{self, min},
|
|
|
|
cmp::{self, min},
|
|
|
|
ffi::{CStr, CString},
|
|
|
|
ffi::{CStr, CString},
|
|
|
|
io,
|
|
|
|
io, iter,
|
|
|
|
mem::{self, MaybeUninit},
|
|
|
|
mem::{self, MaybeUninit},
|
|
|
|
os::fd::{AsRawFd, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
|
|
|
|
os::fd::{AsRawFd, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
|
|
|
|
slice,
|
|
|
|
slice,
|
|
|
@ -28,7 +28,7 @@ use crate::{
|
|
|
|
},
|
|
|
|
},
|
|
|
|
copy_instructions,
|
|
|
|
copy_instructions,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
sys::{syscall, SysResult, Syscall},
|
|
|
|
sys::{syscall, SysResult, Syscall, SyscallError},
|
|
|
|
Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN,
|
|
|
|
Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -90,7 +90,7 @@ pub(crate) fn bpf_create_map(
|
|
|
|
.copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) });
|
|
|
|
.copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
|
|
|
|
pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
|
|
|
@ -98,14 +98,14 @@ pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_4 };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_4 };
|
|
|
|
u.bpf_fd = fd as u32;
|
|
|
|
u.bpf_fd = fd as u32;
|
|
|
|
u.pathname = path.as_ptr() as u64;
|
|
|
|
u.pathname = path.as_ptr() as u64;
|
|
|
|
sys_bpf(bpf_cmd::BPF_OBJ_PIN, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_OBJ_PIN, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_get_object(path: &CStr) -> SysResult<c_long> {
|
|
|
|
pub(crate) fn bpf_get_object(path: &CStr) -> SysResult<c_long> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_4 };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_4 };
|
|
|
|
u.pathname = path.as_ptr() as u64;
|
|
|
|
u.pathname = path.as_ptr() as u64;
|
|
|
|
sys_bpf(bpf_cmd::BPF_OBJ_GET, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_OBJ_GET, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) struct BpfLoadProgramAttrs<'a> {
|
|
|
|
pub(crate) struct BpfLoadProgramAttrs<'a> {
|
|
|
@ -188,7 +188,7 @@ pub(crate) fn bpf_load_program(
|
|
|
|
if let Some(v) = aya_attr.attach_btf_id {
|
|
|
|
if let Some(v) = aya_attr.attach_btf_id {
|
|
|
|
u.attach_btf_id = v;
|
|
|
|
u.attach_btf_id = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn lookup<K: Pod, V: Pod>(
|
|
|
|
fn lookup<K: Pod, V: Pod>(
|
|
|
@ -208,7 +208,7 @@ fn lookup<K: Pod, V: Pod>(
|
|
|
|
u.__bindgen_anon_1.value = &mut value as *mut _ as u64;
|
|
|
|
u.__bindgen_anon_1.value = &mut value as *mut _ as u64;
|
|
|
|
u.flags = flags;
|
|
|
|
u.flags = flags;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(cmd, &attr) {
|
|
|
|
match sys_bpf(cmd, &mut attr) {
|
|
|
|
Ok(_) => Ok(Some(unsafe { value.assume_init() })),
|
|
|
|
Ok(_) => Ok(Some(unsafe { value.assume_init() })),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
Err(e) => Err(e),
|
|
|
@ -260,7 +260,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
|
|
|
|
u.__bindgen_anon_1.value = value as u64;
|
|
|
|
u.__bindgen_anon_1.value = value as u64;
|
|
|
|
u.flags = flags;
|
|
|
|
u.flags = flags;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_MAP_LOOKUP_ELEM, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_MAP_LOOKUP_ELEM, &mut attr) {
|
|
|
|
Ok(_) => Ok(Some(())),
|
|
|
|
Ok(_) => Ok(Some(())),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
Err(e) => Err(e),
|
|
|
@ -283,7 +283,7 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
|
|
|
|
u.__bindgen_anon_1.value = value as *const _ as u64;
|
|
|
|
u.__bindgen_anon_1.value = value as *const _ as u64;
|
|
|
|
u.flags = flags;
|
|
|
|
u.flags = flags;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> SysResult<c_long> {
|
|
|
|
pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> SysResult<c_long> {
|
|
|
@ -294,7 +294,7 @@ pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> Sys
|
|
|
|
u.__bindgen_anon_1.value = value as *const _ as u64;
|
|
|
|
u.__bindgen_anon_1.value = value as *const _ as u64;
|
|
|
|
u.flags = flags;
|
|
|
|
u.flags = flags;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_map_update_elem_ptr<K, V>(
|
|
|
|
pub(crate) fn bpf_map_update_elem_ptr<K, V>(
|
|
|
@ -311,7 +311,7 @@ pub(crate) fn bpf_map_update_elem_ptr<K, V>(
|
|
|
|
u.__bindgen_anon_1.value = value as u64;
|
|
|
|
u.__bindgen_anon_1.value = value as u64;
|
|
|
|
u.flags = flags;
|
|
|
|
u.flags = flags;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_map_update_elem_per_cpu<K: Pod, V: Pod>(
|
|
|
|
pub(crate) fn bpf_map_update_elem_per_cpu<K: Pod, V: Pod>(
|
|
|
@ -331,7 +331,7 @@ pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: RawFd, key: &K) -> SysResult<c_lon
|
|
|
|
u.map_fd = fd as u32;
|
|
|
|
u.map_fd = fd as u32;
|
|
|
|
u.key = key as *const _ as u64;
|
|
|
|
u.key = key as *const _ as u64;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_map_get_next_key<K: Pod>(
|
|
|
|
pub(crate) fn bpf_map_get_next_key<K: Pod>(
|
|
|
@ -348,7 +348,7 @@ pub(crate) fn bpf_map_get_next_key<K: Pod>(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
u.__bindgen_anon_1.next_key = &mut next_key as *mut _ as u64;
|
|
|
|
u.__bindgen_anon_1.next_key = &mut next_key as *mut _ as u64;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_MAP_GET_NEXT_KEY, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_MAP_GET_NEXT_KEY, &mut attr) {
|
|
|
|
Ok(_) => Ok(Some(unsafe { next_key.assume_init() })),
|
|
|
|
Ok(_) => Ok(Some(unsafe { next_key.assume_init() })),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
Err(e) => Err(e),
|
|
|
@ -360,7 +360,7 @@ pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult<c_long> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_2 };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_2 };
|
|
|
|
u.map_fd = fd as u32;
|
|
|
|
u.map_fd = fd as u32;
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// since kernel 5.7
|
|
|
|
// since kernel 5.7
|
|
|
@ -381,7 +381,7 @@ pub(crate) fn bpf_link_create(
|
|
|
|
attr.link_create.__bindgen_anon_3.target_btf_id = btf_id;
|
|
|
|
attr.link_create.__bindgen_anon_3.target_btf_id = btf_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_LINK_CREATE, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_LINK_CREATE, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// since kernel 5.7
|
|
|
|
// since kernel 5.7
|
|
|
@ -402,7 +402,7 @@ pub(crate) fn bpf_link_update(
|
|
|
|
attr.link_update.flags = flags;
|
|
|
|
attr.link_update.flags = flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_LINK_UPDATE, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_LINK_UPDATE, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_attach(
|
|
|
|
pub(crate) fn bpf_prog_attach(
|
|
|
@ -416,7 +416,7 @@ pub(crate) fn bpf_prog_attach(
|
|
|
|
attr.__bindgen_anon_5.target_fd = target_fd as u32;
|
|
|
|
attr.__bindgen_anon_5.target_fd = target_fd as u32;
|
|
|
|
attr.__bindgen_anon_5.attach_type = attach_type as u32;
|
|
|
|
attr.__bindgen_anon_5.attach_type = attach_type as u32;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_detach(
|
|
|
|
pub(crate) fn bpf_prog_detach(
|
|
|
@ -430,7 +430,7 @@ pub(crate) fn bpf_prog_detach(
|
|
|
|
attr.__bindgen_anon_5.target_fd = map_fd as u32;
|
|
|
|
attr.__bindgen_anon_5.target_fd = map_fd as u32;
|
|
|
|
attr.__bindgen_anon_5.attach_type = attach_type as u32;
|
|
|
|
attr.__bindgen_anon_5.attach_type = attach_type as u32;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_DETACH, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_PROG_DETACH, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_query(
|
|
|
|
pub(crate) fn bpf_prog_query(
|
|
|
@ -449,7 +449,7 @@ pub(crate) fn bpf_prog_query(
|
|
|
|
attr.query.prog_cnt = prog_ids.len() as u32;
|
|
|
|
attr.query.prog_cnt = prog_ids.len() as u32;
|
|
|
|
attr.query.prog_ids = prog_ids.as_mut_ptr() as u64;
|
|
|
|
attr.query.prog_ids = prog_ids.as_mut_ptr() as u64;
|
|
|
|
|
|
|
|
|
|
|
|
let ret = sys_bpf(bpf_cmd::BPF_PROG_QUERY, &attr);
|
|
|
|
let ret = sys_bpf(bpf_cmd::BPF_PROG_QUERY, &mut attr);
|
|
|
|
|
|
|
|
|
|
|
|
*prog_cnt = unsafe { attr.query.prog_cnt };
|
|
|
|
*prog_cnt = unsafe { attr.query.prog_cnt };
|
|
|
|
|
|
|
|
|
|
|
@ -460,57 +460,71 @@ pub(crate) fn bpf_prog_query(
|
|
|
|
ret
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result<OwnedFd, io::Error> {
|
|
|
|
pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result<OwnedFd, SyscallError> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
|
|
|
|
|
|
|
|
attr.__bindgen_anon_6.__bindgen_anon_1.prog_id = prog_id;
|
|
|
|
attr.__bindgen_anon_6.__bindgen_anon_1.prog_id = prog_id;
|
|
|
|
// SAFETY: BPF_PROG_GET_FD_BY_ID returns a new file descriptor.
|
|
|
|
// SAFETY: BPF_PROG_GET_FD_BY_ID returns a new file descriptor.
|
|
|
|
unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_GET_FD_BY_ID, &attr).map_err(|(_, e)| e) }
|
|
|
|
unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_GET_FD_BY_ID, &mut attr) }.map_err(|(code, io_error)| {
|
|
|
|
|
|
|
|
assert_eq!(code, -1);
|
|
|
|
|
|
|
|
SyscallError {
|
|
|
|
|
|
|
|
call: "bpf_prog_get_fd_by_id",
|
|
|
|
|
|
|
|
io_error,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, io::Error> {
|
|
|
|
fn bpf_obj_get_info_by_fd<T>(fd: BorrowedFd<'_>) -> Result<T, SyscallError> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
// info gets entirely populated by the kernel
|
|
|
|
// info gets entirely populated by the kernel
|
|
|
|
let info = MaybeUninit::zeroed();
|
|
|
|
let info = MaybeUninit::zeroed();
|
|
|
|
|
|
|
|
|
|
|
|
attr.info.bpf_fd = prog_fd as u32;
|
|
|
|
attr.info.bpf_fd = fd.as_raw_fd() as u32;
|
|
|
|
attr.info.info = &info as *const _ as u64;
|
|
|
|
attr.info.info = &info as *const _ as u64;
|
|
|
|
attr.info.info_len = mem::size_of::<bpf_prog_info>() as u32;
|
|
|
|
attr.info.info_len = mem::size_of_val(&info) as u32;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) {
|
|
|
|
Ok(_) => Ok(unsafe { info.assume_init() }),
|
|
|
|
Ok(code) => {
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
assert_eq!(code, 0);
|
|
|
|
|
|
|
|
Ok(unsafe { info.assume_init() })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Err((code, io_error)) => {
|
|
|
|
|
|
|
|
assert_eq!(code, -1);
|
|
|
|
|
|
|
|
Err(SyscallError {
|
|
|
|
|
|
|
|
call: "bpf_obj_get_info_by_fd",
|
|
|
|
|
|
|
|
io_error,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_map_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_map_info, io::Error> {
|
|
|
|
pub(crate) fn bpf_prog_get_info_by_fd(fd: RawFd) -> Result<bpf_prog_info, SyscallError> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
|
|
|
|
// info gets entirely populated by the kernel
|
|
|
|
bpf_obj_get_info_by_fd::<bpf_prog_info>(fd)
|
|
|
|
let info = MaybeUninit::zeroed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
attr.info.bpf_fd = prog_fd as u32;
|
|
|
|
|
|
|
|
attr.info.info = info.as_ptr() as *const _ as u64;
|
|
|
|
|
|
|
|
attr.info.info_len = mem::size_of::<bpf_map_info>() as u32;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
|
|
|
|
pub(crate) fn bpf_map_get_info_by_fd(fd: RawFd) -> Result<bpf_map_info, SyscallError> {
|
|
|
|
Ok(_) => Ok(unsafe { info.assume_init() }),
|
|
|
|
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
bpf_obj_get_info_by_fd::<bpf_map_info>(fd)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_link_get_info_by_fd(link_fd: RawFd) -> Result<bpf_link_info, io::Error> {
|
|
|
|
pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result<OwnedFd, SyscallError> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
// info gets entirely populated by the kernel
|
|
|
|
|
|
|
|
let info = unsafe { MaybeUninit::zeroed().assume_init() };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
attr.info.bpf_fd = link_fd as u32;
|
|
|
|
attr.__bindgen_anon_6.__bindgen_anon_1.link_id = link_id;
|
|
|
|
attr.info.info = &info as *const _ as u64;
|
|
|
|
// SAFETY: BPF_LINK_GET_FD_BY_ID returns a new file descriptor.
|
|
|
|
attr.info.info_len = mem::size_of::<bpf_link_info>() as u32;
|
|
|
|
unsafe { fd_sys_bpf(bpf_cmd::BPF_LINK_GET_FD_BY_ID, &mut attr) }.map_err(|(code, io_error)| {
|
|
|
|
|
|
|
|
assert_eq!(code, -1);
|
|
|
|
|
|
|
|
SyscallError {
|
|
|
|
|
|
|
|
call: "bpf_link_get_fd_by_id",
|
|
|
|
|
|
|
|
io_error,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
|
|
|
|
pub(crate) fn bpf_link_get_info_by_fd(fd: RawFd) -> Result<bpf_link_info, SyscallError> {
|
|
|
|
Ok(_) => Ok(info),
|
|
|
|
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
bpf_obj_get_info_by_fd::<bpf_link_info>(fd)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn btf_obj_get_info_by_fd(
|
|
|
|
pub(crate) fn btf_obj_get_info_by_fd(
|
|
|
@ -526,7 +540,7 @@ pub(crate) fn btf_obj_get_info_by_fd(
|
|
|
|
attr.info.info = &info as *const bpf_btf_info as u64;
|
|
|
|
attr.info.info = &info as *const bpf_btf_info as u64;
|
|
|
|
attr.info.info_len = mem::size_of::<bpf_btf_info>() as u32;
|
|
|
|
attr.info.info_len = mem::size_of::<bpf_btf_info>() as u32;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) {
|
|
|
|
Ok(_) => Ok(info),
|
|
|
|
Ok(_) => Ok(info),
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -541,7 +555,7 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy
|
|
|
|
};
|
|
|
|
};
|
|
|
|
attr.raw_tracepoint.prog_fd = prog_fd as u32;
|
|
|
|
attr.raw_tracepoint.prog_fd = prog_fd as u32;
|
|
|
|
|
|
|
|
|
|
|
|
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)
|
|
|
|
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &mut attr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_load_btf(
|
|
|
|
pub(crate) fn bpf_load_btf(
|
|
|
@ -559,11 +573,11 @@ pub(crate) fn bpf_load_btf(
|
|
|
|
u.btf_log_size = log_buf.len() as u32;
|
|
|
|
u.btf_log_size = log_buf.len() as u32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// SAFETY: `BPF_BTF_LOAD` returns a newly created fd.
|
|
|
|
// SAFETY: `BPF_BTF_LOAD` returns a newly created fd.
|
|
|
|
unsafe { fd_sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) }
|
|
|
|
unsafe { fd_sys_bpf(bpf_cmd::BPF_BTF_LOAD, &mut attr) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SAFETY: only use for bpf_cmd that return a new file descriptor on success.
|
|
|
|
// SAFETY: only use for bpf_cmd that return a new file descriptor on success.
|
|
|
|
unsafe fn fd_sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult<OwnedFd> {
|
|
|
|
unsafe fn fd_sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<OwnedFd> {
|
|
|
|
let fd = sys_bpf(cmd, attr)?;
|
|
|
|
let fd = sys_bpf(cmd, attr)?;
|
|
|
|
let fd = fd.try_into().map_err(|_| {
|
|
|
|
let fd = fd.try_into().map_err(|_| {
|
|
|
|
(
|
|
|
|
(
|
|
|
@ -581,7 +595,7 @@ pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<RawFd, io::Error> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
attr.__bindgen_anon_6.__bindgen_anon_1.btf_id = id;
|
|
|
|
attr.__bindgen_anon_6.__bindgen_anon_1.btf_id = id;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_BTF_GET_FD_BY_ID, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_BTF_GET_FD_BY_ID, &mut attr) {
|
|
|
|
Ok(v) => Ok(v as RawFd),
|
|
|
|
Ok(v) => Ok(v as RawFd),
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
Err((_, err)) => Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -612,7 +626,7 @@ pub(crate) fn is_prog_name_supported() -> bool {
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
|
|
|
|
Ok(v) => {
|
|
|
|
Ok(v) => {
|
|
|
|
let fd = v as RawFd;
|
|
|
|
let fd = v as RawFd;
|
|
|
|
unsafe { close(fd) };
|
|
|
|
unsafe { close(fd) };
|
|
|
@ -643,7 +657,7 @@ pub(crate) fn is_probe_read_kernel_supported() -> bool {
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
|
|
|
|
Ok(v) => {
|
|
|
|
Ok(v) => {
|
|
|
|
let fd = v as RawFd;
|
|
|
|
let fd = v as RawFd;
|
|
|
|
unsafe { close(fd) };
|
|
|
|
unsafe { close(fd) };
|
|
|
@ -670,7 +684,7 @@ pub(crate) fn is_perf_link_supported() -> bool {
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
|
|
|
|
|
|
|
|
|
|
|
|
if let Ok(fd) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
|
|
|
|
if let Ok(fd) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
|
|
|
|
if let Err((_, e)) =
|
|
|
|
if let Err((_, e)) =
|
|
|
|
// Uses an invalid target FD so we get EBADF if supported.
|
|
|
|
// Uses an invalid target FD so we get EBADF if supported.
|
|
|
|
bpf_link_create(fd as i32, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0)
|
|
|
|
bpf_link_create(fd as i32, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0)
|
|
|
@ -726,7 +740,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
|
|
|
|
|
|
|
|
|
|
|
|
if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
|
|
|
|
if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
|
|
|
|
let fd = v as RawFd;
|
|
|
|
let fd = v as RawFd;
|
|
|
|
|
|
|
|
|
|
|
|
unsafe { close(fd) };
|
|
|
|
unsafe { close(fd) };
|
|
|
@ -755,7 +769,7 @@ pub(crate) fn is_bpf_cookie_supported() -> bool {
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.insns = insns.as_ptr() as u64;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_KPROBE as u32;
|
|
|
|
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_KPROBE as u32;
|
|
|
|
|
|
|
|
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
|
|
|
|
Ok(v) => {
|
|
|
|
Ok(v) => {
|
|
|
|
let fd = v as RawFd;
|
|
|
|
let fd = v as RawFd;
|
|
|
|
unsafe { close(fd) };
|
|
|
|
unsafe { close(fd) };
|
|
|
@ -905,21 +919,63 @@ pub(crate) fn is_btf_type_tag_supported() -> bool {
|
|
|
|
bpf_load_btf(btf_bytes.as_slice(), &mut [], Default::default()).is_ok()
|
|
|
|
bpf_load_btf(btf_bytes.as_slice(), &mut [], Default::default()).is_ok()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult<c_long> {
|
|
|
|
fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
|
|
|
|
syscall(Syscall::Bpf { cmd, attr })
|
|
|
|
syscall(Syscall::Bpf { cmd, attr })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, (c_long, io::Error)> {
|
|
|
|
fn bpf_obj_get_next_id(
|
|
|
|
|
|
|
|
id: u32,
|
|
|
|
|
|
|
|
cmd: bpf_cmd,
|
|
|
|
|
|
|
|
name: &'static str,
|
|
|
|
|
|
|
|
) -> Result<Option<u32>, SyscallError> {
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_6 };
|
|
|
|
let u = unsafe { &mut attr.__bindgen_anon_6 };
|
|
|
|
u.__bindgen_anon_1.start_id = id;
|
|
|
|
u.__bindgen_anon_1.start_id = id;
|
|
|
|
match sys_bpf(bpf_cmd::BPF_PROG_GET_NEXT_ID, &attr) {
|
|
|
|
match sys_bpf(cmd, &mut attr) {
|
|
|
|
Ok(_) => Ok(Some(unsafe { attr.__bindgen_anon_6.next_id })),
|
|
|
|
Ok(code) => {
|
|
|
|
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
|
|
|
|
assert_eq!(code, 0);
|
|
|
|
Err(e) => Err(e),
|
|
|
|
Ok(Some(unsafe { attr.__bindgen_anon_6.next_id }))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Err((code, io_error)) => {
|
|
|
|
|
|
|
|
assert_eq!(code, -1);
|
|
|
|
|
|
|
|
if io_error.raw_os_error() == Some(ENOENT) {
|
|
|
|
|
|
|
|
Ok(None)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Err(SyscallError {
|
|
|
|
|
|
|
|
call: name,
|
|
|
|
|
|
|
|
io_error,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn iter_obj_ids(
|
|
|
|
|
|
|
|
cmd: bpf_cmd,
|
|
|
|
|
|
|
|
name: &'static str,
|
|
|
|
|
|
|
|
) -> impl Iterator<Item = Result<u32, SyscallError>> {
|
|
|
|
|
|
|
|
let mut current_id = Some(0);
|
|
|
|
|
|
|
|
iter::from_fn(move || {
|
|
|
|
|
|
|
|
let next_id = {
|
|
|
|
|
|
|
|
let current_id = current_id?;
|
|
|
|
|
|
|
|
bpf_obj_get_next_id(current_id, cmd, name).transpose()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
current_id = next_id.as_ref().and_then(|next_id| match next_id {
|
|
|
|
|
|
|
|
Ok(next_id) => Some(*next_id),
|
|
|
|
|
|
|
|
Err(SyscallError { .. }) => None,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
next_id
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn iter_prog_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
|
|
|
|
|
|
|
|
iter_obj_ids(bpf_cmd::BPF_PROG_GET_NEXT_ID, "bpf_prog_get_next_id")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn iter_link_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
|
|
|
|
|
|
|
|
iter_obj_ids(bpf_cmd::BPF_LINK_GET_NEXT_ID, "bpf_link_get_next_id")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn retry_with_verifier_logs<T>(
|
|
|
|
pub(crate) fn retry_with_verifier_logs<T>(
|
|
|
|
max_retries: usize,
|
|
|
|
max_retries: usize,
|
|
|
|
f: impl Fn(&mut [u8]) -> SysResult<T>,
|
|
|
|
f: impl Fn(&mut [u8]) -> SysResult<T>,
|
|
|
|