btf: Add support for BTF_TYPE_KIND_{TAG,DECL_TAG}

Adds support for two new BTF kinds including feature probes and BTF
sanitization

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/168/head
Dave Tucker 3 years ago
parent 1492d85a7b
commit 5d9ff70498

@ -28,8 +28,8 @@ use crate::{
},
sys::{
bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_btf_datasec_supported,
is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported,
is_btf_supported, is_prog_name_supported,
is_btf_decl_tag_supported, is_btf_float_supported, is_btf_func_global_supported,
is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_prog_name_supported,
},
util::{bytes_of, possible_cpus, VerifierLog, POSSIBLE_CPUS},
};
@ -91,6 +91,8 @@ pub(crate) struct Features {
pub btf_func_global: bool,
pub btf_datasec: bool,
pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
}
impl Features {
@ -119,6 +121,12 @@ impl Features {
self.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", self.btf_float);
self.btf_decl_tag = is_btf_decl_tag_supported();
debug!("[FEAT PROBE] BTF decl_tag support: {}", self.btf_decl_tag);
self.btf_type_tag = is_btf_type_tag_supported();
debug!("[FEAT PROBE] BTF type_tag support: {}", self.btf_type_tag);
}
}
}

@ -323,7 +323,7 @@ impl Btf {
use BtfType::*;
match ty {
Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) => {
Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) | TypeTag(ty) => {
// Safety: union
type_id = unsafe { ty.__bindgen_anon_1.type_ };
continue;
@ -391,7 +391,13 @@ impl Btf {
unsafe { ty.__bindgen_anon_1.size as usize }
}
Ptr(_) => mem::size_of::<*const c_void>(), // FIXME
Typedef(ty) | Volatile(ty) | Const(ty) | Restrict(ty) | Var(ty, _) => {
Typedef(ty)
| Volatile(ty)
| Const(ty)
| Restrict(ty)
| Var(ty, _)
| DeclTag(ty, _)
| TypeTag(ty) => {
// Safety: union
type_id = unsafe { ty.__bindgen_anon_1.type_ };
continue;
@ -606,6 +612,24 @@ impl Btf {
btf.add_type(BtfType::Float(*ty));
}
}
BtfType::DeclTag(ty, btf_decl_tag) => {
if !features.btf_decl_tag {
debug!("{}: not supported. replacing with INT", kind);
let int_type = BtfType::new_int(ty.name_off, 1, 0, 0);
btf.add_type(int_type);
} else {
btf.add_type(BtfType::DeclTag(*ty, *btf_decl_tag));
}
}
BtfType::TypeTag(ty) => {
if !features.btf_type_tag {
debug!("{}: not supported. replacing with CONST", kind);
let const_type = BtfType::new_const(unsafe { ty.__bindgen_anon_1.type_ });
btf.add_type(const_type);
} else {
btf.add_type(BtfType::TypeTag(*ty));
}
}
// The type does not need sanitizing
ty => {
btf.add_type(ty.clone());
@ -1028,6 +1052,14 @@ mod tests {
let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL);
btf.add_type(func);
let name_offset = btf.add_string("int".to_string());
let type_tag = BtfType::new_type_tag(name_offset, int_type_id);
btf.add_type(type_tag);
let name_offset = btf.add_string("decl_tag".to_string());
let decl_tag = BtfType::new_decl_tag(name_offset, var_type_id, -1);
btf.add_type(decl_tag);
let cases = HashMap::from([
(
"noop",
@ -1038,6 +1070,8 @@ mod tests {
btf_func_global: true,
btf_datasec: true,
btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
},
),
(
@ -1049,6 +1083,8 @@ mod tests {
btf_func_global: true,
btf_datasec: false,
btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
},
),
(
@ -1060,6 +1096,8 @@ mod tests {
btf_func_global: true,
btf_datasec: true,
btf_float: false,
btf_decl_tag: true,
btf_type_tag: true,
},
),
(
@ -1071,6 +1109,8 @@ mod tests {
btf_func_global: true,
btf_datasec: true,
btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
},
),
(
@ -1082,6 +1122,34 @@ mod tests {
btf_func_global: false,
btf_datasec: true,
btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
},
),
(
"no decl tag",
Features {
bpf_name: true,
btf: true,
btf_func: true,
btf_func_global: true,
btf_datasec: true,
btf_float: true,
btf_decl_tag: false,
btf_type_tag: true,
},
),
(
"no type tag",
Features {
bpf_name: true,
btf: true,
btf_func: true,
btf_func_global: true,
btf_datasec: true,
btf_float: true,
btf_decl_tag: true,
btf_type_tag: false,
},
),
(
@ -1093,6 +1161,8 @@ mod tests {
btf_func_global: false,
btf_datasec: false,
btf_float: false,
btf_decl_tag: false,
btf_type_tag: false,
},
),
]);

@ -8,11 +8,12 @@ use object::Endianness;
use crate::{
generated::{
btf_array, btf_enum, btf_func_linkage, btf_member, btf_param, btf_type,
btf_array, btf_decl_tag, btf_enum, btf_func_linkage, btf_member, btf_param, btf_type,
btf_type__bindgen_ty_1, btf_var, btf_var_secinfo, BTF_KIND_ARRAY, BTF_KIND_CONST,
BTF_KIND_DATASEC, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC, BTF_KIND_FUNC_PROTO,
BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT, BTF_KIND_STRUCT,
BTF_KIND_TYPEDEF, BTF_KIND_UNION, BTF_KIND_UNKN, BTF_KIND_VAR, BTF_KIND_VOLATILE,
BTF_KIND_DATASEC, BTF_KIND_DECL_TAG, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC,
BTF_KIND_FUNC_PROTO, BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT,
BTF_KIND_STRUCT, BTF_KIND_TYPEDEF, BTF_KIND_TYPE_TAG, BTF_KIND_UNION, BTF_KIND_UNKN,
BTF_KIND_VAR, BTF_KIND_VOLATILE,
},
obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH},
};
@ -36,6 +37,8 @@ pub(crate) enum BtfType {
FuncProto(btf_type, Vec<btf_param>),
Var(btf_type, btf_var),
DataSec(btf_type, Vec<btf_var_secinfo>),
DeclTag(btf_type, btf_decl_tag),
TypeTag(btf_type),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -58,6 +61,8 @@ pub(crate) enum BtfKind {
FuncProto = BTF_KIND_FUNC_PROTO,
Var = BTF_KIND_VAR,
DataSec = BTF_KIND_DATASEC,
DeclTag = BTF_KIND_DECL_TAG,
TypeTag = BTF_KIND_TYPE_TAG,
}
impl TryFrom<u32> for BtfKind {
@ -83,6 +88,8 @@ impl TryFrom<u32> for BtfKind {
BTF_KIND_FUNC_PROTO => FuncProto,
BTF_KIND_VAR => Var,
BTF_KIND_DATASEC => DataSec,
BTF_KIND_DECL_TAG => DeclTag,
BTF_KIND_TYPE_TAG => TypeTag,
kind => return Err(BtfError::InvalidTypeKind { kind }),
})
}
@ -108,6 +115,8 @@ impl Display for BtfKind {
BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"),
BtfKind::Var => write!(f, "[VAR]"),
BtfKind::DataSec => write!(f, "[DATASEC]"),
BtfKind::DeclTag => write!(f, "[DECL_TAG]"),
BtfKind::TypeTag => write!(f, "[TYPE_TAG]"),
}
}
}
@ -177,6 +186,8 @@ impl BtfType {
BtfKind::FuncProto => FuncProto(ty, unsafe { read_array(data, vlen)? }),
BtfKind::Var => Var(ty, unsafe { read(data)? }),
BtfKind::DataSec => DataSec(ty, unsafe { read_array(data, vlen)? }),
BtfKind::DeclTag => DeclTag(ty, unsafe { read(data)? }),
BtfKind::TypeTag => TypeTag(ty),
})
}
@ -193,7 +204,8 @@ impl BtfType {
| BtfType::Ptr(btf_type)
| BtfType::Typedef(btf_type)
| BtfType::Func(btf_type)
| BtfType::Float(btf_type) => bytes_of::<btf_type>(btf_type).to_vec(),
| BtfType::Float(btf_type)
| BtfType::TypeTag(btf_type) => bytes_of::<btf_type>(btf_type).to_vec(),
BtfType::Int(btf_type, len) => {
let mut buf = bytes_of::<btf_type>(btf_type).to_vec();
buf.append(&mut len.to_ne_bytes().to_vec());
@ -238,6 +250,11 @@ impl BtfType {
buf
}
BtfType::Unknown => vec![],
BtfType::DeclTag(btf_type, btf_decl_tag) => {
let mut buf = bytes_of::<btf_type>(btf_type).to_vec();
buf.append(&mut bytes_of::<btf_decl_tag>(btf_decl_tag).to_vec());
buf
}
}
}
@ -248,7 +265,7 @@ impl BtfType {
match self {
Unknown => ty_size,
Fwd(_) | Const(_) | Volatile(_) | Restrict(_) | Ptr(_) | Typedef(_) | Func(_)
| Float(_) => ty_size,
| Float(_) | TypeTag(_) => ty_size,
Int(_, _) => ty_size + mem::size_of::<u32>(),
Enum(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_enum>(),
Array(_, _) => ty_size + mem::size_of::<btf_array>(),
@ -257,6 +274,7 @@ impl BtfType {
FuncProto(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_param>(),
Var(_, _) => ty_size + mem::size_of::<btf_var>(),
DataSec(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_var_secinfo>(),
DeclTag(_, _) => ty_size + mem::size_of::<btf_decl_tag>(),
}
}
@ -280,6 +298,8 @@ impl BtfType {
FuncProto(ty, _) => ty,
Var(ty, _) => ty,
DataSec(ty, _) => ty,
DeclTag(ty, _) => ty,
TypeTag(ty) => ty,
})
}
@ -408,6 +428,43 @@ impl BtfType {
};
BtfType::Array(btf_type, btf_array)
}
pub(crate) fn new_decl_tag(name_off: u32, type_: u32, component_idx: i32) -> BtfType {
let info = (BTF_KIND_DECL_TAG) << 24;
let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
btf_type.name_off = name_off;
btf_type.info = info;
btf_type.__bindgen_anon_1.type_ = type_;
let btf_decl_tag = btf_decl_tag { component_idx };
BtfType::DeclTag(btf_type, btf_decl_tag)
}
pub(crate) fn new_type_tag(name_off: u32, type_: u32) -> BtfType {
let info = (BTF_KIND_TYPE_TAG) << 24;
let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
btf_type.name_off = name_off;
btf_type.info = info;
btf_type.__bindgen_anon_1.type_ = type_;
BtfType::TypeTag(btf_type)
}
pub(crate) fn new_ptr(type_: u32) -> BtfType {
let info = (BTF_KIND_PTR) << 24;
let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
btf_type.name_off = 0;
btf_type.info = info;
btf_type.__bindgen_anon_1.type_ = type_;
BtfType::Ptr(btf_type)
}
pub(crate) fn new_const(type_: u32) -> BtfType {
let info = (BTF_KIND_CONST) << 24;
let mut btf_type = unsafe { std::mem::zeroed::<btf_type>() };
btf_type.name_off = 0;
btf_type.info = info;
btf_type.__bindgen_anon_1.type_ = type_;
BtfType::Const(btf_type)
}
}
fn type_kind(ty: &btf_type) -> Result<BtfKind, BtfError> {

@ -670,6 +670,66 @@ pub(crate) fn is_btf_float_supported() -> bool {
}
}
pub(crate) fn is_btf_decl_tag_supported() -> bool {
let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0);
let int_type_id = btf.add_type(int_type);
let name_offset = btf.add_string("foo".to_string());
let var_type = BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC);
let var_type_id = btf.add_type(var_type);
let name_offset = btf.add_string("decl_tag".to_string());
let decl_tag = BtfType::new_decl_tag(name_offset, var_type_id, -1);
btf.add_type(decl_tag);
let btf_bytes = btf.to_bytes();
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = btf_bytes.as_ptr() as u64;
u.btf_size = btf_bytes.len() as u32;
match sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) {
Ok(v) => {
let fd = v as RawFd;
unsafe { close(fd) };
true
}
Err(_) => false,
}
}
pub(crate) fn is_btf_type_tag_supported() -> bool {
let mut btf = Btf::new();
let int_type = BtfType::new_int(0, 4, BTF_INT_SIGNED, 0);
let int_type_id = btf.add_type(int_type);
let name_offset = btf.add_string("int".to_string());
let type_tag = BtfType::new_type_tag(name_offset, int_type_id);
let type_tag_type = btf.add_type(type_tag);
btf.add_type(BtfType::new_ptr(type_tag_type));
let btf_bytes = btf.to_bytes();
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = btf_bytes.as_ptr() as u64;
u.btf_size = btf_bytes.len() as u32;
match sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) {
Ok(v) => {
let fd = v as RawFd;
unsafe { close(fd) };
true
}
Err(_) => false,
}
}
pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult {
syscall(Syscall::Bpf { cmd, attr })
}

Loading…
Cancel
Save