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::{ sys::{
bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_btf_datasec_supported, 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_decl_tag_supported, is_btf_float_supported, is_btf_func_global_supported,
is_btf_supported, is_prog_name_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}, util::{bytes_of, possible_cpus, VerifierLog, POSSIBLE_CPUS},
}; };
@ -91,6 +91,8 @@ pub(crate) struct Features {
pub btf_func_global: bool, pub btf_func_global: bool,
pub btf_datasec: bool, pub btf_datasec: bool,
pub btf_float: bool, pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
} }
impl Features { impl Features {
@ -119,6 +121,12 @@ impl Features {
self.btf_float = is_btf_float_supported(); self.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", self.btf_float); 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::*; use BtfType::*;
match ty { match ty {
Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) => { Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) | TypeTag(ty) => {
// Safety: union // Safety: union
type_id = unsafe { ty.__bindgen_anon_1.type_ }; type_id = unsafe { ty.__bindgen_anon_1.type_ };
continue; continue;
@ -391,7 +391,13 @@ impl Btf {
unsafe { ty.__bindgen_anon_1.size as usize } unsafe { ty.__bindgen_anon_1.size as usize }
} }
Ptr(_) => mem::size_of::<*const c_void>(), // FIXME 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 // Safety: union
type_id = unsafe { ty.__bindgen_anon_1.type_ }; type_id = unsafe { ty.__bindgen_anon_1.type_ };
continue; continue;
@ -606,6 +612,24 @@ impl Btf {
btf.add_type(BtfType::Float(*ty)); 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 // The type does not need sanitizing
ty => { ty => {
btf.add_type(ty.clone()); 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); let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL);
btf.add_type(func); 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([ let cases = HashMap::from([
( (
"noop", "noop",
@ -1038,6 +1070,8 @@ mod tests {
btf_func_global: true, btf_func_global: true,
btf_datasec: true, btf_datasec: true,
btf_float: true, btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
}, },
), ),
( (
@ -1049,6 +1083,8 @@ mod tests {
btf_func_global: true, btf_func_global: true,
btf_datasec: false, btf_datasec: false,
btf_float: true, btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
}, },
), ),
( (
@ -1060,6 +1096,8 @@ mod tests {
btf_func_global: true, btf_func_global: true,
btf_datasec: true, btf_datasec: true,
btf_float: false, btf_float: false,
btf_decl_tag: true,
btf_type_tag: true,
}, },
), ),
( (
@ -1071,6 +1109,8 @@ mod tests {
btf_func_global: true, btf_func_global: true,
btf_datasec: true, btf_datasec: true,
btf_float: true, btf_float: true,
btf_decl_tag: true,
btf_type_tag: true,
}, },
), ),
( (
@ -1082,6 +1122,34 @@ mod tests {
btf_func_global: false, btf_func_global: false,
btf_datasec: true, btf_datasec: true,
btf_float: 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_func_global: false,
btf_datasec: false, btf_datasec: false,
btf_float: false, btf_float: false,
btf_decl_tag: false,
btf_type_tag: false,
}, },
), ),
]); ]);

@ -8,11 +8,12 @@ use object::Endianness;
use crate::{ use crate::{
generated::{ 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_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_DATASEC, BTF_KIND_DECL_TAG, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC,
BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT, BTF_KIND_STRUCT, BTF_KIND_FUNC_PROTO, BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR, BTF_KIND_RESTRICT,
BTF_KIND_TYPEDEF, BTF_KIND_UNION, BTF_KIND_UNKN, BTF_KIND_VAR, BTF_KIND_VOLATILE, 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}, obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH},
}; };
@ -36,6 +37,8 @@ pub(crate) enum BtfType {
FuncProto(btf_type, Vec<btf_param>), FuncProto(btf_type, Vec<btf_param>),
Var(btf_type, btf_var), Var(btf_type, btf_var),
DataSec(btf_type, Vec<btf_var_secinfo>), DataSec(btf_type, Vec<btf_var_secinfo>),
DeclTag(btf_type, btf_decl_tag),
TypeTag(btf_type),
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -58,6 +61,8 @@ pub(crate) enum BtfKind {
FuncProto = BTF_KIND_FUNC_PROTO, FuncProto = BTF_KIND_FUNC_PROTO,
Var = BTF_KIND_VAR, Var = BTF_KIND_VAR,
DataSec = BTF_KIND_DATASEC, DataSec = BTF_KIND_DATASEC,
DeclTag = BTF_KIND_DECL_TAG,
TypeTag = BTF_KIND_TYPE_TAG,
} }
impl TryFrom<u32> for BtfKind { impl TryFrom<u32> for BtfKind {
@ -83,6 +88,8 @@ impl TryFrom<u32> for BtfKind {
BTF_KIND_FUNC_PROTO => FuncProto, BTF_KIND_FUNC_PROTO => FuncProto,
BTF_KIND_VAR => Var, BTF_KIND_VAR => Var,
BTF_KIND_DATASEC => DataSec, BTF_KIND_DATASEC => DataSec,
BTF_KIND_DECL_TAG => DeclTag,
BTF_KIND_TYPE_TAG => TypeTag,
kind => return Err(BtfError::InvalidTypeKind { kind }), kind => return Err(BtfError::InvalidTypeKind { kind }),
}) })
} }
@ -108,6 +115,8 @@ impl Display for BtfKind {
BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"), BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"),
BtfKind::Var => write!(f, "[VAR]"), BtfKind::Var => write!(f, "[VAR]"),
BtfKind::DataSec => write!(f, "[DATASEC]"), 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::FuncProto => FuncProto(ty, unsafe { read_array(data, vlen)? }),
BtfKind::Var => Var(ty, unsafe { read(data)? }), BtfKind::Var => Var(ty, unsafe { read(data)? }),
BtfKind::DataSec => DataSec(ty, unsafe { read_array(data, vlen)? }), 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::Ptr(btf_type)
| BtfType::Typedef(btf_type) | BtfType::Typedef(btf_type)
| BtfType::Func(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) => { BtfType::Int(btf_type, len) => {
let mut buf = bytes_of::<btf_type>(btf_type).to_vec(); let mut buf = bytes_of::<btf_type>(btf_type).to_vec();
buf.append(&mut len.to_ne_bytes().to_vec()); buf.append(&mut len.to_ne_bytes().to_vec());
@ -238,6 +250,11 @@ impl BtfType {
buf buf
} }
BtfType::Unknown => vec![], 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 { match self {
Unknown => ty_size, Unknown => ty_size,
Fwd(_) | Const(_) | Volatile(_) | Restrict(_) | Ptr(_) | Typedef(_) | Func(_) Fwd(_) | Const(_) | Volatile(_) | Restrict(_) | Ptr(_) | Typedef(_) | Func(_)
| Float(_) => ty_size, | Float(_) | TypeTag(_) => ty_size,
Int(_, _) => ty_size + mem::size_of::<u32>(), Int(_, _) => ty_size + mem::size_of::<u32>(),
Enum(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_enum>(), Enum(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_enum>(),
Array(_, _) => ty_size + mem::size_of::<btf_array>(), 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>(), FuncProto(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_param>(),
Var(_, _) => ty_size + mem::size_of::<btf_var>(), Var(_, _) => ty_size + mem::size_of::<btf_var>(),
DataSec(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_var_secinfo>(), 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, FuncProto(ty, _) => ty,
Var(ty, _) => ty, Var(ty, _) => ty,
DataSec(ty, _) => ty, DataSec(ty, _) => ty,
DeclTag(ty, _) => ty,
TypeTag(ty) => ty,
}) })
} }
@ -408,6 +428,43 @@ impl BtfType {
}; };
BtfType::Array(btf_type, btf_array) 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> { 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 { pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult {
syscall(Syscall::Bpf { cmd, attr }) syscall(Syscall::Bpf { cmd, attr })
} }

Loading…
Cancel
Save