Merge "[avb] Improve error reporting when parsing descriptors from VBMeta"
diff --git a/pvmfw/avb/fuzz/Android.bp b/pvmfw/avb/fuzz/Android.bp
index 451fd8a..e970eed 100644
--- a/pvmfw/avb/fuzz/Android.bp
+++ b/pvmfw/avb/fuzz/Android.bp
@@ -31,4 +31,18 @@
},
}
-// TODO(b/260574387): Add avb_kernel_with_footer_verify_fuzzer
+rust_fuzz {
+ name: "avb_kernel_with_footer_verify_fuzzer",
+ srcs: ["with_footer_verify_fuzzer.rs"],
+ rustlibs: [
+ "libpvmfw_avb_nostd",
+ "libavb_bindgen_nostd",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-kvm@google.com",
+ ],
+ fuzz_on_haiku_device: true,
+ fuzz_on_haiku_host: true,
+ },
+}
diff --git a/pvmfw/avb/fuzz/with_footer_verify_fuzzer.rs b/pvmfw/avb/fuzz/with_footer_verify_fuzzer.rs
new file mode 100644
index 0000000..6eed15b
--- /dev/null
+++ b/pvmfw/avb/fuzz/with_footer_verify_fuzzer.rs
@@ -0,0 +1,59 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![allow(missing_docs)]
+#![no_main]
+
+use avb_bindgen::{
+ AvbFooter, AvbVBMetaImageHeader, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN, AVB_MAGIC,
+ AVB_MAGIC_LEN, AVB_VERSION_MAJOR, AVB_VERSION_MINOR,
+};
+use libfuzzer_sys::fuzz_target;
+use pvmfw_avb::verify_payload;
+use std::mem::{size_of, transmute};
+
+fuzz_target!(|kernel_and_vbmeta: &[u8]| {
+ // This fuzzer is mostly supposed to catch the memory corruption in
+ // VBMeta parsing. It is unlikely that the randomly generated
+ // kernel can pass the kernel verification, so the value of `initrd`
+ // is not so important as we won't reach initrd verification with
+ // this fuzzer.
+ const VBMETA_SIZE: usize = size_of::<AvbVBMetaImageHeader>();
+ const RESERVED_REGION_SIZE: usize = 28;
+
+ if kernel_and_vbmeta.len() < VBMETA_SIZE {
+ return;
+ }
+ let kernel_size = kernel_and_vbmeta.len() - VBMETA_SIZE;
+ let avb_footer = AvbFooter {
+ magic: AVB_FOOTER_MAGIC[..(AVB_FOOTER_MAGIC_LEN as usize)].try_into().unwrap(),
+ version_major: AVB_VERSION_MAJOR.to_be(),
+ version_minor: AVB_VERSION_MINOR.to_be(),
+ original_image_size: (kernel_size as u64).to_be(),
+ vbmeta_offset: (kernel_size as u64).to_be(),
+ vbmeta_size: (VBMETA_SIZE as u64).to_be(),
+ reserved: [0u8; RESERVED_REGION_SIZE],
+ };
+ // SAFETY: It is safe as avb_footer is a valid AvbFooter struct.
+ let avb_footer = unsafe { transmute::<AvbFooter, [u8; size_of::<AvbFooter>()]>(avb_footer) };
+
+ let mut modified_kernel = vec![0u8; kernel_and_vbmeta.len() + size_of::<AvbFooter>()];
+ modified_kernel[..kernel_and_vbmeta.len()].copy_from_slice(kernel_and_vbmeta);
+ // Sets the magic for AvbVBMetaImageHeader.
+ modified_kernel[kernel_size..(kernel_size + AVB_MAGIC_LEN as usize)]
+ .copy_from_slice(&AVB_MAGIC[..(AVB_MAGIC_LEN as usize)]);
+ modified_kernel[kernel_and_vbmeta.len()..].copy_from_slice(&avb_footer);
+
+ let _ = verify_payload(&modified_kernel, /*initrd=*/ None, &[0u8; 64]);
+});