diff options
author | David Pursell <dpursell@google.com> | 2024-01-18 17:57:19 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2024-01-18 17:57:19 +0000 |
commit | 896bbdb4ac6da107b2a1c4607897797b75e4c524 (patch) | |
tree | c3a0108b7b474d67e47a3d823343717055a28fa3 | |
parent | e7663b9a93b0c8aca8f5d15c5cf5a2c1669219cf (diff) | |
parent | 4a8e3b12ca51b32ccf98520ef5356c3533416e5c (diff) | |
download | avb-896bbdb4ac6da107b2a1c4607897797b75e4c524.tar.gz |
libavb_rs: add kernel commandline descriptors am: 4a8e3b12ca
Original change: https://android-review.googlesource.com/c/platform/external/avb/+/2912602
Change-Id: Ic07f1f2ccaaeab654fbf40375e7c492ea07eaa99
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | rust/Android.bp | 20 | ||||
-rw-r--r-- | rust/src/descriptor/commandline.rs | 113 | ||||
-rw-r--r-- | rust/src/descriptor/hash.rs | 12 | ||||
-rw-r--r-- | rust/src/descriptor/hashtree.rs | 12 | ||||
-rw-r--r-- | rust/src/descriptor/mod.rs | 29 | ||||
-rw-r--r-- | rust/src/descriptor/property.rs | 2 | ||||
-rw-r--r-- | rust/src/lib.rs | 3 | ||||
-rw-r--r-- | rust/tests/verify_tests.rs | 121 |
8 files changed, 236 insertions, 76 deletions
diff --git a/rust/Android.bp b/rust/Android.bp index c7c0128..27c5fce 100644 --- a/rust/Android.bp +++ b/rust/Android.bp @@ -31,15 +31,12 @@ rust_defaults { source_stem: "bindings", bindgen_flags: [ "--constified-enum-module=AvbDescriptorTag", - "--bitfield-enum=AvbHashDescriptorFlags", - "--bitfield-enum=AvbHashtreeDescriptorFlags", - "--bitfield-enum=AvbSlotVerifyFlags", + "--bitfield-enum=Avb.*Flags", "--default-enum-style rust", "--with-derive-default", "--with-derive-custom=Avb.*Descriptor=FromZeroes,FromBytes", "--allowlist-type=AvbDescriptorTag", - "--allowlist-type=AvbHashDescriptorFlags", - "--allowlist-type=AvbHashtreeDescriptorFlags", + "--allowlist-type=Avb.*Flags", "--allowlist-function=.*", "--allowlist-var=AVB.*", "--use-core", @@ -266,6 +263,7 @@ rust_defaults { ":avbrs_test_vbmeta", ":avbrs_test_vbmeta_2_parts", ":avbrs_test_vbmeta_persistent_digest", + ":avbrs_test_vbmeta_with_commandline", ":avbrs_test_vbmeta_with_hashtree", ":avbrs_test_vbmeta_with_property", ], @@ -404,6 +402,18 @@ genrule { cmd: "$(location avbtool) make_vbmeta_image --key $(location :avb_testkey_rsa4096) --algorithm SHA512_RSA4096 --include_descriptors_from_image $(location :avbrs_test_image_descriptor_hashtree) --output $(out)", } +// Standalone vbmeta image with kernel commandline "test_cmdline_key=test_cmdline_value". +genrule { + name: "avbrs_test_vbmeta_with_commandline", + tools: ["avbtool"], + srcs: [ + ":avbrs_test_image_descriptor", + ":avb_testkey_rsa4096", + ], + out: ["test_vbmeta_with_commandline.img"], + cmd: "$(location avbtool) make_vbmeta_image --kernel_cmdline test_cmdline_key=test_cmdline_value --key $(location :avb_testkey_rsa4096) --algorithm SHA512_RSA4096 --include_descriptors_from_image $(location :avbrs_test_image_descriptor) --output $(out)", +} + // Combined test image + signed vbmeta footer for "test_part". avb_add_hash_footer { name: "avbrs_test_image_with_vbmeta_footer", diff --git a/rust/src/descriptor/commandline.rs b/rust/src/descriptor/commandline.rs new file mode 100644 index 0000000..4f45c3b --- /dev/null +++ b/rust/src/descriptor/commandline.rs @@ -0,0 +1,113 @@ +// Copyright 2024, 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. + +//! Kernel commandline descriptors. + +use super::{ + util::{parse_descriptor, split_slice, ValidateAndByteswap, ValidationFunc}, + DescriptorResult, +}; +use avb_bindgen::{ + avb_kernel_cmdline_descriptor_validate_and_byteswap, AvbKernelCmdlineDescriptor, +}; +use core::str::from_utf8; + +/// `AvbKernelCmdlineFlags`; see libavb docs for details. +pub use avb_bindgen::AvbKernelCmdlineFlags as KernelCommandlineDescriptorFlags; + +/// Wraps an `AvbKernelCmdlineDescriptor` stored in a vbmeta image. +#[derive(Debug, PartialEq, Eq)] +pub struct KernelCommandlineDescriptor<'a> { + /// Flags. + pub flags: KernelCommandlineDescriptorFlags, + + /// Kernel commandline. + pub commandline: &'a str, +} + +// SAFETY: `VALIDATE_AND_BYTESWAP_FUNC` is the correct libavb validator for this descriptor type. +unsafe impl ValidateAndByteswap for AvbKernelCmdlineDescriptor { + const VALIDATE_AND_BYTESWAP_FUNC: ValidationFunc<Self> = + avb_kernel_cmdline_descriptor_validate_and_byteswap; +} + +impl<'a> KernelCommandlineDescriptor<'a> { + /// Extracts a `KernelCommandlineDescriptor` from the given descriptor contents. + /// + /// # Arguments + /// * `contents`: descriptor contents, including the header, in raw big-endian format. + /// + /// # Returns + /// The new descriptor, or `DescriptorError` if the given `contents` aren't a valid + /// `AvbKernelCmdlineDescriptor`. + pub(super) fn new(contents: &'a [u8]) -> DescriptorResult<Self> { + // Descriptor contains: header + commandline. + let descriptor = parse_descriptor::<AvbKernelCmdlineDescriptor>(contents)?; + let (commandline, _) = + split_slice(descriptor.body, descriptor.header.kernel_cmdline_length)?; + + Ok(Self { + flags: KernelCommandlineDescriptorFlags(descriptor.header.flags), + commandline: from_utf8(commandline)?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::DescriptorError; + use std::mem::size_of; + + /// A valid kernel commandline descriptor in raw big-endian format. + const TEST_KERNEL_COMMANDLINE_DESCRIPTOR: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, + 0x6D, 0x64, 0x6C, 0x69, 0x6E, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x3D, 0x74, 0x65, 0x73, 0x74, + 0x5F, 0x63, 0x6D, 0x64, 0x6C, 0x69, 0x6E, 0x65, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + #[test] + fn new_commandline_descriptor_success() { + let descriptor = KernelCommandlineDescriptor::new(TEST_KERNEL_COMMANDLINE_DESCRIPTOR); + assert!(descriptor.is_ok()); + } + + #[test] + fn new_commandline_descriptor_too_short_header_fails() { + let bad_header_size = size_of::<KernelCommandlineDescriptor>() - 1; + assert_eq!( + KernelCommandlineDescriptor::new( + &TEST_KERNEL_COMMANDLINE_DESCRIPTOR[..bad_header_size] + ) + .unwrap_err(), + DescriptorError::InvalidHeader + ); + } + + #[test] + fn new_commandline_descriptor_too_short_contents_fails() { + // The last 5 bytes are padding, so we need to drop 6 bytes to trigger an error. + let bad_contents_size = TEST_KERNEL_COMMANDLINE_DESCRIPTOR.len() - 6; + assert_eq!( + KernelCommandlineDescriptor::new( + &TEST_KERNEL_COMMANDLINE_DESCRIPTOR[..bad_contents_size] + ) + .unwrap_err(), + DescriptorError::InvalidSize + ); + } +} diff --git a/rust/src/descriptor/hash.rs b/rust/src/descriptor/hash.rs index 3ad52f0..6bd47c0 100644 --- a/rust/src/descriptor/hash.rs +++ b/rust/src/descriptor/hash.rs @@ -16,7 +16,7 @@ use super::{ util::{parse_descriptor, split_slice, ValidateAndByteswap, ValidationFunc}, - DescriptorError, DescriptorResult, + DescriptorResult, }; use avb_bindgen::{avb_hash_descriptor_validate_and_byteswap, AvbHashDescriptor}; use core::{ffi::CStr, str::from_utf8}; @@ -79,16 +79,14 @@ impl<'a> HashDescriptor<'a> { // byte-swapped header doesn't live past this function. // The hash algorithm is a nul-terminated UTF-8 string which is identical in the raw // and byteswapped headers. - let hash_algorithm = CStr::from_bytes_until_nul(&descriptor.raw_header.hash_algorithm) - .map_err(|_| DescriptorError::InvalidValue)? - .to_str() - .map_err(|_| DescriptorError::InvalidUtf8)?; + let hash_algorithm = + CStr::from_bytes_until_nul(&descriptor.raw_header.hash_algorithm)?.to_str()?; Ok(Self { image_size: descriptor.header.image_size, hash_algorithm, flags: HashDescriptorFlags(descriptor.header.flags), - partition_name: from_utf8(partition_name).map_err(|_| DescriptorError::InvalidUtf8)?, + partition_name: from_utf8(partition_name)?, salt, digest, }) @@ -98,6 +96,8 @@ impl<'a> HashDescriptor<'a> { #[cfg(test)] mod tests { use super::*; + + use crate::DescriptorError; use std::mem::size_of; /// A valid hash descriptor in raw big-endian format. diff --git a/rust/src/descriptor/hashtree.rs b/rust/src/descriptor/hashtree.rs index 5b44eaf..a811cc5 100644 --- a/rust/src/descriptor/hashtree.rs +++ b/rust/src/descriptor/hashtree.rs @@ -16,7 +16,7 @@ use super::{ util::{parse_descriptor, split_slice, ValidateAndByteswap, ValidationFunc}, - DescriptorError, DescriptorResult, + DescriptorResult, }; use avb_bindgen::{avb_hashtree_descriptor_validate_and_byteswap, AvbHashtreeDescriptor}; use core::{ffi::CStr, str::from_utf8}; @@ -97,10 +97,8 @@ impl<'a> HashtreeDescriptor<'a> { // byte-swapped header doesn't live past this function. // The hash algorithm is a nul-terminated UTF-8 string which is identical in the raw // and byteswapped headers. - let hash_algorithm = CStr::from_bytes_until_nul(&descriptor.raw_header.hash_algorithm) - .map_err(|_| DescriptorError::InvalidValue)? - .to_str() - .map_err(|_| DescriptorError::InvalidUtf8)?; + let hash_algorithm = + CStr::from_bytes_until_nul(&descriptor.raw_header.hash_algorithm)?.to_str()?; Ok(Self { dm_verity_version: descriptor.header.dm_verity_version, @@ -113,7 +111,7 @@ impl<'a> HashtreeDescriptor<'a> { fec_offset: descriptor.header.fec_offset, fec_size: descriptor.header.fec_size, hash_algorithm, - partition_name: from_utf8(partition_name).map_err(|_| DescriptorError::InvalidUtf8)?, + partition_name: from_utf8(partition_name)?, salt, root_digest, flags: HashtreeDescriptorFlags(descriptor.header.flags), @@ -124,6 +122,8 @@ impl<'a> HashtreeDescriptor<'a> { #[cfg(test)] mod tests { use super::*; + + use crate::DescriptorError; use std::mem::size_of; /// A valid hashtree descriptor in raw big-endian format. diff --git a/rust/src/descriptor/mod.rs b/rust/src/descriptor/mod.rs index 82b434e..929ec2f 100644 --- a/rust/src/descriptor/mod.rs +++ b/rust/src/descriptor/mod.rs @@ -19,6 +19,7 @@ extern crate alloc; +mod commandline; mod hash; mod hashtree; mod property; @@ -29,8 +30,14 @@ use alloc::vec::Vec; use avb_bindgen::{ avb_descriptor_foreach, avb_descriptor_validate_and_byteswap, AvbDescriptor, AvbDescriptorTag, }; -use core::{ffi::c_void, mem::size_of, slice}; +use core::{ + ffi::{c_void, FromBytesUntilNulError}, + mem::size_of, + slice, + str::Utf8Error, +}; +pub use commandline::{KernelCommandlineDescriptor, KernelCommandlineDescriptorFlags}; pub use hash::{HashDescriptor, HashDescriptorFlags}; pub use hashtree::{HashtreeDescriptor, HashtreeDescriptorFlags}; pub use property::PropertyDescriptor; @@ -46,7 +53,7 @@ pub enum Descriptor<'a> { /// Wraps `AvbHashDescriptor`. Hash(HashDescriptor<'a>), /// Wraps `AvbKernelCmdlineDescriptor`. - KernelCommandline(&'a [u8]), + KernelCommandline(KernelCommandlineDescriptor<'a>), /// Wraps `AvbChainPartitionDescriptor`. ChainPartition(&'a [u8]), /// Unknown descriptor type. @@ -68,6 +75,18 @@ pub enum DescriptorError { InvalidContents, } +impl From<Utf8Error> for DescriptorError { + fn from(_: Utf8Error) -> Self { + Self::InvalidUtf8 + } +} + +impl From<FromBytesUntilNulError> for DescriptorError { + fn from(_: FromBytesUntilNulError) -> Self { + Self::InvalidContents + } +} + /// `Result` type for `DescriptorError` errors. pub type DescriptorResult<T> = Result<T, DescriptorError>; @@ -118,9 +137,9 @@ impl<'a> Descriptor<'a> { Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_HASH) => { Ok(Descriptor::Hash(HashDescriptor::new(contents)?)) } - Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) => { - Ok(Descriptor::KernelCommandline(contents)) - } + Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) => Ok( + Descriptor::KernelCommandline(KernelCommandlineDescriptor::new(contents)?), + ), Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) => { Ok(Descriptor::ChainPartition(contents)) } diff --git a/rust/src/descriptor/property.rs b/rust/src/descriptor/property.rs index 62c3be0..ce24bea 100644 --- a/rust/src/descriptor/property.rs +++ b/rust/src/descriptor/property.rs @@ -65,7 +65,7 @@ impl<'a> PropertyDescriptor<'a> { extract_nul(remainder)?; Ok(Self { - key: from_utf8(key).map_err(|_| DescriptorError::InvalidUtf8)?, + key: from_utf8(key)?, value, }) } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 312f71e..c41b80a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -33,7 +33,8 @@ mod verify; pub use descriptor::{ Descriptor, DescriptorError, DescriptorResult, HashDescriptor, HashDescriptorFlags, - HashtreeDescriptor, HashtreeDescriptorFlags, PropertyDescriptor, + HashtreeDescriptor, HashtreeDescriptorFlags, KernelCommandlineDescriptor, + KernelCommandlineDescriptorFlags, PropertyDescriptor, }; pub use error::{ IoError, IoResult, SlotVerifyError, SlotVerifyNoDataResult, SlotVerifyResult, diff --git a/rust/tests/verify_tests.rs b/rust/tests/verify_tests.rs index 7c5bb0a..14d2b79 100644 --- a/rust/tests/verify_tests.rs +++ b/rust/tests/verify_tests.rs @@ -17,8 +17,9 @@ use crate::test_ops::TestOps; use avb::{ slot_verify, Descriptor, HashDescriptor, HashDescriptorFlags, HashtreeDescriptor, - HashtreeDescriptorFlags, HashtreeErrorMode, IoError, PropertyDescriptor, SlotVerifyData, - SlotVerifyError, SlotVerifyFlags, SlotVerifyResult, + HashtreeDescriptorFlags, HashtreeErrorMode, IoError, KernelCommandlineDescriptor, + KernelCommandlineDescriptorFlags, PropertyDescriptor, SlotVerifyData, SlotVerifyError, + SlotVerifyFlags, SlotVerifyResult, }; use hex::decode; use std::{ffi::CString, fs}; @@ -35,6 +36,7 @@ const TEST_VBMETA_2_PARTITIONS_PATH: &str = "test_vbmeta_2_parts.img"; const TEST_VBMETA_PERSISTENT_DIGEST_PATH: &str = "test_vbmeta_persistent_digest.img"; const TEST_VBMETA_WITH_PROPERTY_PATH: &str = "test_vbmeta_with_property.img"; const TEST_VBMETA_WITH_HASHTREE_PATH: &str = "test_vbmeta_with_hashtree.img"; +const TEST_VBMETA_WITH_COMMANDLINE_PATH: &str = "test_vbmeta_with_commandline.img"; const TEST_IMAGE_WITH_VBMETA_FOOTER_PATH: &str = "avbrs_test_image_with_vbmeta_footer.img"; const TEST_IMAGE_WITH_VBMETA_FOOTER_FOR_BOOT_PATH: &str = "avbrs_test_image_with_vbmeta_footer_for_boot.img"; @@ -47,6 +49,7 @@ const TEST_PARTITION_HASH_TREE_NAME: &str = "test_part_hashtree"; const TEST_VBMETA_ROLLBACK_LOCATION: usize = 0; // Default value, we don't explicitly set this. const TEST_PROPERTY_KEY: &str = "test_prop_key"; const TEST_PROPERTY_VALUE: &[u8] = b"test_prop_value"; +const TEST_KERNEL_COMMANDLINE: &str = "test_cmdline_key=test_cmdline_value"; // Expected values determined by examining the vbmeta image with `avbtool info_image`. // Images can be found in <out>/soong/.intermediates/external/avb/rust/. @@ -640,70 +643,84 @@ fn two_images_gives_two_descriptors() { assert_eq!(data.vbmeta_data()[0].descriptors().unwrap().len(), 2); } -#[test] -fn verify_hash_descriptor() { +/// Runs verification on the given contents and checks for a resulting descriptor. +/// +/// This test helper performs the following steps: +/// +/// 1. set up a `TestOps` for the default test image/vbmeta +/// 2. replace the vbmeta image with the contents at `vbmeta_path` +/// 3. run verification +/// 4. check that the given `descriptor` exists in the verification data +fn verify_and_find_descriptor(vbmeta_path: &str, expected_descriptor: &Descriptor) { let mut ops = test_ops_one_image_one_vbmeta(); + // Replace the vbmeta image with the requested variation. + ops.add_partition("vbmeta", fs::read(vbmeta_path).unwrap()); + let result = verify_one_image_one_vbmeta(&mut ops); let data = result.unwrap(); let descriptors = &data.vbmeta_data()[0].descriptors().unwrap(); + assert!(descriptors.contains(expected_descriptor)); +} - let expected = HashDescriptor { - image_size: TEST_IMAGE_SIZE as u64, - hash_algorithm: TEST_IMAGE_HASH_ALGO, - flags: HashDescriptorFlags(0), - partition_name: TEST_PARTITION_NAME, - salt: &decode(TEST_IMAGE_SALT_HEX).unwrap(), - digest: &decode(TEST_IMAGE_DIGEST_HEX).unwrap(), - }; - assert!(descriptors.contains(&Descriptor::Hash(expected))); +#[test] +fn verify_hash_descriptor() { + verify_and_find_descriptor( + // The standard vbmeta image should contain the hash descriptor. + TEST_VBMETA_PATH, + &Descriptor::Hash(HashDescriptor { + image_size: TEST_IMAGE_SIZE as u64, + hash_algorithm: TEST_IMAGE_HASH_ALGO, + flags: HashDescriptorFlags(0), + partition_name: TEST_PARTITION_NAME, + salt: &decode(TEST_IMAGE_SALT_HEX).unwrap(), + digest: &decode(TEST_IMAGE_DIGEST_HEX).unwrap(), + }), + ); } #[test] fn verify_property_descriptor() { - let mut ops = test_ops_one_image_one_vbmeta(); - // Replace vbmeta with the version containing a property descriptor. - ops.add_partition("vbmeta", fs::read(TEST_VBMETA_WITH_PROPERTY_PATH).unwrap()); - - let result = verify_one_image_one_vbmeta(&mut ops); - - let data = result.unwrap(); - let descriptors = &data.vbmeta_data()[0].descriptors().unwrap(); - - let expected = PropertyDescriptor { - key: TEST_PROPERTY_KEY, - value: TEST_PROPERTY_VALUE, - }; - assert!(descriptors.contains(&Descriptor::Property(expected))); + verify_and_find_descriptor( + TEST_VBMETA_WITH_PROPERTY_PATH, + &Descriptor::Property(PropertyDescriptor { + key: TEST_PROPERTY_KEY, + value: TEST_PROPERTY_VALUE, + }), + ); } #[test] fn verify_hashtree_descriptor() { - let mut ops = test_ops_one_image_one_vbmeta(); - // Replace vbmeta with the version containing a hashtree descriptor. - ops.add_partition("vbmeta", fs::read(TEST_VBMETA_WITH_HASHTREE_PATH).unwrap()); - - let result = verify_one_image_one_vbmeta(&mut ops); - - let data = result.unwrap(); - let descriptors = &data.vbmeta_data()[0].descriptors().unwrap(); + verify_and_find_descriptor( + TEST_VBMETA_WITH_HASHTREE_PATH, + &Descriptor::Hashtree(HashtreeDescriptor { + dm_verity_version: 1, + image_size: TEST_IMAGE_SIZE as u64, + tree_offset: TEST_IMAGE_SIZE as u64, + tree_size: 4096, + data_block_size: 4096, + hash_block_size: 4096, + fec_num_roots: 0, + fec_offset: 0, + fec_size: 0, + hash_algorithm: TEST_HASHTREE_ALGORITHM, + flags: HashtreeDescriptorFlags(0), + partition_name: TEST_PARTITION_HASH_TREE_NAME, + salt: &decode(TEST_HASHTREE_SALT_HEX).unwrap(), + root_digest: &decode(TEST_HASHTREE_DIGEST_HEX).unwrap(), + }), + ); +} - let expected = HashtreeDescriptor { - dm_verity_version: 1, - image_size: TEST_IMAGE_SIZE as u64, - tree_offset: TEST_IMAGE_SIZE as u64, - tree_size: 4096, - data_block_size: 4096, - hash_block_size: 4096, - fec_num_roots: 0, - fec_offset: 0, - fec_size: 0, - hash_algorithm: TEST_HASHTREE_ALGORITHM, - flags: HashtreeDescriptorFlags(0), - partition_name: TEST_PARTITION_HASH_TREE_NAME, - salt: &decode(TEST_HASHTREE_SALT_HEX).unwrap(), - root_digest: &decode(TEST_HASHTREE_DIGEST_HEX).unwrap(), - }; - assert!(descriptors.contains(&Descriptor::Hashtree(expected))); +#[test] +fn verify_kernel_commandline_descriptor() { + verify_and_find_descriptor( + TEST_VBMETA_WITH_COMMANDLINE_PATH, + &Descriptor::KernelCommandline(KernelCommandlineDescriptor { + flags: KernelCommandlineDescriptorFlags(0), + commandline: TEST_KERNEL_COMMANDLINE, + }), + ); } |