Skip to content

Commit ce5ac4a

Browse files
committed
libbpf-cargo: Wrap generated "unsafe" type in MaybeUninit
Certain Rust types that we use in our generated skeleton are not valid for all bit patterns. Bools, for example, are defined to be one byte in size, but their representation allows only for 0 and 1 values to be used in said byte -- everything else is undefined behavior. Enums have similar problems, in that not the entire space of the backing type is necessarily used by variants. The result is an unsoundness issue in our generated skeletons, because C code could accidentally set an enum to an invalid value and Rust code would exhibit undefined behavior. This change fixes this problem by wrapping the corresponding attributes in MaybeUninit. In so doing users have to be explicit when accessing them and make sure that the current representation is indeed valid. Closes: #589 Signed-off-by: Daniel Müller <[email protected]>
1 parent 3f3b872 commit ce5ac4a

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

libbpf-cargo/src/gen/btf.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ use libbpf_rs::ReferencesType;
2424

2525
const ANON_PREFIX: &str = "__anon_";
2626

27+
/// Check whether the provided type is "unsafe" to use.
28+
///
29+
/// A type is considered unsafe by this function if it is not valid for
30+
/// any bit pattern.
31+
fn is_unsafe(ty: BtfType<'_>) -> bool {
32+
let ty = ty.skip_mods_and_typedefs();
33+
34+
btf_type_match!(match ty {
35+
BtfKind::Int(t) => matches!(t.encoding, types::IntEncoding::Bool),
36+
BtfKind::Enum | BtfKind::Enum64 => true,
37+
_ => false,
38+
})
39+
}
40+
2741
pub struct GenBtf<'s> {
2842
btf: Btf<'s>,
2943
// We use refcell here because the design of this type unfortunately causes a lot of borrowing
@@ -394,7 +408,13 @@ impl<'s> GenBtf<'s> {
394408
let field_name = if let Some(name) = member.name {
395409
name.to_string_lossy()
396410
} else {
397-
field_ty_str.as_str().into()
411+
Cow::Borrowed(field_ty_str.as_str())
412+
};
413+
414+
let field_ty_str = if is_unsafe(field_ty) {
415+
Cow::Owned(format!("std::mem::MaybeUninit<{field_ty_str}>"))
416+
} else {
417+
Cow::Borrowed(field_ty_str.as_str())
398418
};
399419

400420
agg_content.push(format!(r#" pub {field_name}: {field_ty_str},"#));

0 commit comments

Comments
 (0)