Browse Source

Merge pull request #583 from 0xrawsec/fix-builtin-linkage

Fix builtin linkage
Alessandro Decina 1 year ago
parent
commit
b2d5059
1 changed files with 86 additions and 15 deletions
  1. 86 15
      aya-obj/src/btf/btf.rs

+ 86 - 15
aya-obj/src/btf/btf.rs

@@ -551,22 +551,39 @@ impl Btf {
                     types.types[i] = enum_type;
                 }
                 // Sanitize FUNC
-                BtfType::Func(ty) if !features.btf_func => {
-                    debug!("{}: not supported. replacing with TYPEDEF", kind);
-                    let typedef_type = BtfType::Typedef(Typedef::new(ty.name_offset, ty.btf_type));
-                    types.types[i] = typedef_type;
-                }
-                // Sanitize BTF_FUNC_GLOBAL
-                BtfType::Func(ty) if !features.btf_func_global => {
-                    let mut fixed_ty = ty.clone();
-                    if ty.linkage() == FuncLinkage::Global {
-                        debug!(
-                            "{}: BTF_FUNC_GLOBAL not supported. replacing with BTF_FUNC_STATIC",
-                            kind
-                        );
-                        fixed_ty.set_linkage(FuncLinkage::Static);
+                BtfType::Func(ty) => {
+                    let name = self.string_at(ty.name_offset)?;
+                    // Sanitize FUNC
+                    if !features.btf_func {
+                        debug!("{}: not supported. replacing with TYPEDEF", kind);
+                        let typedef_type =
+                            BtfType::Typedef(Typedef::new(ty.name_offset, ty.btf_type));
+                        types.types[i] = typedef_type;
+                    } else if !features.btf_func_global
+                        || name == "memset"
+                        || name == "memcpy"
+                        || name == "memmove"
+                        || name == "memcmp"
+                    {
+                        // Sanitize BTF_FUNC_GLOBAL when not supported and ensure that
+                        // memory builtins are marked as static. Globals are type checked
+                        // and verified separately from their callers, while instead we
+                        // want tracking info (eg bound checks) to be propagated to the
+                        // memory builtins.
+                        let mut fixed_ty = ty.clone();
+                        if ty.linkage() == FuncLinkage::Global {
+                            if !features.btf_func_global {
+                                debug!(
+                                    "{}: BTF_FUNC_GLOBAL not supported. replacing with BTF_FUNC_STATIC",
+                                    kind
+                                );
+                            } else {
+                                debug!("changing FUNC {name} linkage to BTF_FUNC_STATIC");
+                            }
+                            fixed_ty.set_linkage(FuncLinkage::Static);
+                        }
+                        types.types[i] = BtfType::Func(fixed_ty);
                     }
-                    types.types[i] = BtfType::Func(fixed_ty);
                 }
                 // Sanitize FLOAT
                 BtfType::Float(ty) if !features.btf_float => {
@@ -1365,6 +1382,60 @@ mod tests {
         Btf::parse(&raw, Endianness::default()).unwrap();
     }
 
+    #[test]
+    fn test_sanitize_mem_builtins() {
+        let mut btf = Btf::new();
+        let name_offset = btf.add_string("int".to_string());
+        let int_type_id = btf.add_type(BtfType::Int(Int::new(
+            name_offset,
+            4,
+            IntEncoding::Signed,
+            0,
+        )));
+
+        let params = vec![
+            BtfParam {
+                name_offset: btf.add_string("a".to_string()),
+                btf_type: int_type_id,
+            },
+            BtfParam {
+                name_offset: btf.add_string("b".to_string()),
+                btf_type: int_type_id,
+            },
+        ];
+        let func_proto_type_id =
+            btf.add_type(BtfType::FuncProto(FuncProto::new(params, int_type_id)));
+
+        let builtins = ["memset", "memcpy", "memcmp", "memmove"];
+        for fname in builtins {
+            let func_name_offset = btf.add_string(fname.to_string());
+            let func_type_id = btf.add_type(BtfType::Func(Func::new(
+                func_name_offset,
+                func_proto_type_id,
+                FuncLinkage::Global,
+            )));
+
+            let features = BtfFeatures {
+                btf_func: true,
+                btf_func_global: true, // to force function name check
+                ..Default::default()
+            };
+
+            btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
+                .unwrap();
+
+            if let BtfType::Func(fixed) = btf.type_by_id(func_type_id).unwrap() {
+                assert!(fixed.linkage() == FuncLinkage::Static);
+            } else {
+                panic!("not a func")
+            }
+
+            // Ensure we can convert to bytes and back again
+            let raw = btf.to_bytes();
+            Btf::parse(&raw, Endianness::default()).unwrap();
+        }
+    }
+
     #[test]
     fn test_sanitize_float() {
         let mut btf = Btf::new();