From 7a3b22bcb5082e45d2d6fe973351240cf283ce05 Mon Sep 17 00:00:00 2001 From: Alejandro Jimenez Date: Thu, 27 Feb 2020 23:14:59 -0500 Subject: [PATCH] pvh: Add tests for PVH note parsing Add test cases to verify the functionality that parses the ELF Note header to look for a PVH entry point address if one is encoded. Parse a minimal ELF binary that encodes a predefined address of 0x1e1fe1f, and verify that the same value is read. Also test the case in which a note header is present but no PVH entry point is encoded, as well as a case where the PVH entry address is encoded in the note header using a field of incorrect size. The minimal ELF source code (elfnote.S): #define ELFNOTE_START(name, type, flags) \ .pushsection .note.name, flags, @note ; \ .balign 4 ; \ .long 2f - 1f /* namesz */ ; \ .long 4484f - 3f /* descsz */ ; \ .long type ; \ 1:.asciz #name ; \ 2:.balign 4 ; \ 3: #define ELFNOTE_END \ 4484:.balign 4 ; \ .popsection ; #define ELFNOTE(name, type, desc) \ ELFNOTE_START(name, type, "a") \ desc ; \ ELFNOTE_END #define XEN_ELFNOTE_PHYS32_ENTRY 18 #define NT_VERSION 1 ELFNOTE(dummy, NT_VERSION, .quad 0xcafecafe) ELFNOTE(PVHNote, XEN_ELFNOTE_PHYS32_ENTRY, .quad 0x1e1fe1f) .section ".text","ax" .global _start _start: Built with: $ gcc elfnote.S -s -nostdlib -o test_elfnote.bin The elfnote.S source above is modified to generate the binaries for the rest of the test cases. Signed-off-by: Alejandro Jimenez --- coverage_config_aarch64.json | 2 +- coverage_config_x86_64.json | 2 +- src/loader/mod.rs | 54 ++++++++++++++++++++++++++++++++++ src/loader/test_badnote.bin | Bin 0 -> 640 bytes src/loader/test_dummynote.bin | Bin 0 -> 544 bytes src/loader/test_elfnote.bin | Bin 0 -> 648 bytes 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100755 src/loader/test_badnote.bin create mode 100755 src/loader/test_dummynote.bin create mode 100755 src/loader/test_elfnote.bin diff --git a/coverage_config_aarch64.json b/coverage_config_aarch64.json index 38d81ae2..70ee9da9 100644 --- a/coverage_config_aarch64.json +++ b/coverage_config_aarch64.json @@ -1,5 +1,5 @@ { - "coverage_score": 71, + "coverage_score": 70.9, "exclude_path": "", "crate_features": "" } diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 4ad4557d..648083ff 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 75.9, + "coverage_score": 76.3, "exclude_path": "", "crate_features": "" } diff --git a/src/loader/mod.rs b/src/loader/mod.rs index 74e172e4..a0637635 100644 --- a/src/loader/mod.rs +++ b/src/loader/mod.rs @@ -556,6 +556,24 @@ mod test { v } + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn make_elfnote() -> Vec { + include_bytes!("test_elfnote.bin").to_vec() + } + + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn make_dummy_elfnote() -> Vec { + include_bytes!("test_dummynote.bin").to_vec() + } + + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn make_bad_elfnote() -> Vec { + include_bytes!("test_badnote.bin").to_vec() + } + #[allow(safe_packed_borrows)] #[allow(non_snake_case)] #[test] @@ -678,6 +696,42 @@ mod test { ); } + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + #[test] + fn load_pvh() { + let gm = create_guest_mem(); + let pvhnote_image = make_elfnote(); + let loader_result = Elf::load(&gm, None, &mut Cursor::new(&pvhnote_image), None).unwrap(); + println!( + "PVH entry point at address {:8x} \n", + loader_result.pvh_entry_addr.unwrap().raw_value() + ); + assert_eq!(loader_result.pvh_entry_addr.unwrap().raw_value(), 0x1e1fe1f); + } + + #[test] + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn dumy_elfnote() { + let gm = create_guest_mem(); + let dummynote_image = make_dummy_elfnote(); + let loader_result = Elf::load(&gm, None, &mut Cursor::new(&dummynote_image), None).unwrap(); + assert!(loader_result.pvh_entry_addr.is_none()); + } + + #[test] + #[cfg(feature = "elf")] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn bad_elfnote() { + let gm = create_guest_mem(); + let badnote_image = make_bad_elfnote(); + assert_eq!( + Err(Error::InvalidPvhNote), + Elf::load(&gm, None, &mut Cursor::new(&badnote_image), None) + ); + } + #[test] fn cmdline_overflow() { let gm = create_guest_mem(); diff --git a/src/loader/test_badnote.bin b/src/loader/test_badnote.bin new file mode 100755 index 0000000000000000000000000000000000000000..cbe4cb5971f7b3b1883a62eee27e7766bd63d410 GIT binary patch literal 640 zcmb<-^>JfjWMqH=CI&kO5RZe=0W1U|85kT8N*Ej%EEt%8Br5|8SS<@!C5(XU01I$H z^}%Qc1_iJ3^sGodQx|aV8)w z1jGSh9)9^HsSNUR5PL*`V$4A7?ib3iAl6vdnPMt+a&k1g_wr>Gw2m(6qgj0 zBqlNF3OAkNu`-NDY}^{Kocng+(7N@Kn!v>2*CUg3l|xPFr0*i z157|1$UxSA1{#iMpb8{l3ZXQ*epNL6PoVmrK-H@d&<~0SP`IK4SbSTcNkEeWToeEw C>oXAm literal 0 HcmV?d00001 diff --git a/src/loader/test_dummynote.bin b/src/loader/test_dummynote.bin new file mode 100755 index 0000000000000000000000000000000000000000..990e69ed9259b477b54172c7fcf5e6f1b78c6067 GIT binary patch literal 544 zcmb<-^>JfjWMqH=CI&kO5bpzn16T+`GB7A0lmKNc7?^-03j;G)EelvBjDYEY&>x_} zFdAqQSOla8gg1bBAld=Ug3%Bj15^~E7Nmd;h&g~5Ghffm(P6e{?;A-5z2c1GlA@BtBnG{_{E}2Xh#?SmdS0ns zQfX#Rif(2K$UrIpZlD?LK+FU+3+6wVzh%(uKn+U<25~g~XP_Z+2C7emfPPRofx-hF Oz~Vy-O#&&J!7>2cXDkr_ literal 0 HcmV?d00001 diff --git a/src/loader/test_elfnote.bin b/src/loader/test_elfnote.bin new file mode 100755 index 0000000000000000000000000000000000000000..36efd2d3f1a02ef7f9228e87506a8ef5c88e1246 GIT binary patch literal 648 zcmb<-^>JfjWMqH=CI&kO5RZq^0W1U|85leeN*Ej%EEt%8Br5|8SS<@!C5(XSfY3Zp zeK4AVK>@4~qz8mIfO#O=0nCEYF;H