From 9f17f6b787492822adc851fe538a738e18be4ca4 Mon Sep 17 00:00:00 2001 From: Liu Jiang Date: Sun, 22 Mar 2020 13:38:38 +0800 Subject: [PATCH 1/3] Refine dependency on vm-memory Refine dependency on vm-memory crate by: 1) relax version number constraint to "0.x.y" 2) enable feature vm-memory/backend-mmap for development only because it's used by unit test cases. Signed-off-by: Liu Jiang --- Cargo.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b6a3a0d4..a229f62e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,7 @@ elf = [] bzimage = [] [dependencies] -vm-memory = {version = ">=0.2.0", features = ["backend-mmap"]} +vm-memory = ">=0.2.0" + +[dev-dependencies] +vm-memory = {features = ["backend-mmap"]} From 6ea4c5a6eafab25dcebff1acbe3613f690925921 Mon Sep 17 00:00:00 2001 From: Liu Jiang Date: Sun, 22 Mar 2020 14:22:54 +0800 Subject: [PATCH 2/3] Uniquely identify the PVH note header According to Linux kernel documentation: Each note has three parts: a name, a type and a desc. The name is intended to distinguish the note's originator, so it would be a company, project, subsystem, etc; it must be in a suitable form for use in a section name. The type is an integer which is used to tag the data, and is considered to be within the "name" namespace (so "FooCo"'s type 42 is distinct from "BarProj"'s type 42). The "desc" field is the actual data. There are no constraints on the desc field's contents, though typically they're fairly small. So check both name and type when searching for the PVH note. Signed-off-by: Liu Jiang --- src/loader/x86_64/elf/mod.rs | 19 ++++++++++++++----- src/loader/x86_64/elf/test_badnote.bin | Bin 640 -> 632 bytes src/loader/x86_64/elf/test_elfnote.bin | Bin 648 -> 640 bytes 3 files changed, 14 insertions(+), 5 deletions(-) mode change 100755 => 100644 src/loader/x86_64/elf/test_badnote.bin mode change 100755 => 100644 src/loader/x86_64/elf/test_elfnote.bin diff --git a/src/loader/x86_64/elf/mod.rs b/src/loader/x86_64/elf/mod.rs index 347e1c72..34ea6092 100644 --- a/src/loader/x86_64/elf/mod.rs +++ b/src/loader/x86_64/elf/mod.rs @@ -249,6 +249,9 @@ impl KernelLoader for Elf { } } +// Size of string "Xen", including the terminating NULL. +const PVH_NOTE_STR_SZ: usize = 4; + /// Examines a supplied elf program header of type `PT_NOTE` to determine if it contains an entry /// of type `XEN_ELFNOTE_PHYS32_ENTRY` (0x12). Notes of this type encode a physical 32-bit entry /// point address into the kernel, which is used when launching guests in 32-bit (protected) mode @@ -281,11 +284,17 @@ where .read_from(0, kernel_image, nhdr_sz) .map_err(|_| Error::ReadNoteHeader)?; - // If the note header found is not the desired one, keep reading until the end of the - // segment. - if nhdr.n_type == XEN_ELFNOTE_PHYS32_ENTRY { - break; + // Check if the note header's name and type match the ones specified by the PVH ABI. + if nhdr.n_type == XEN_ELFNOTE_PHYS32_ENTRY && nhdr.n_namesz as usize == PVH_NOTE_STR_SZ { + let mut buf = [0u8; PVH_NOTE_STR_SZ]; + kernel_image + .read_exact(&mut buf) + .map_err(|_| Error::ReadNoteHeader)?; + if buf == [b'X', b'e', b'n', b'\0'] { + break; + } } + // Skip the note header plus the size of its fields (with alignment). read_size += nhdr_sz + align_up(u64::from(nhdr.n_namesz), n_align) @@ -306,7 +315,7 @@ where // just skip the name field contents. kernel_image .seek(SeekFrom::Current( - align_up(u64::from(nhdr.n_namesz), n_align) as i64, + align_up(u64::from(nhdr.n_namesz), n_align) as i64 - PVH_NOTE_STR_SZ as i64, )) .map_err(|_| Error::SeekNoteHeader)?; diff --git a/src/loader/x86_64/elf/test_badnote.bin b/src/loader/x86_64/elf/test_badnote.bin old mode 100755 new mode 100644 index cbe4cb5971f7b3b1883a62eee27e7766bd63d410..99013dd50fe9aa7f7f751177106c3c6bb93e99c5 GIT binary patch delta 155 zcmZo*{lPLpLXd^gfdK>{Bm;xRL``!}7Dlib1Ixrrea;XFn;~T4LT!E)AcqNvg@8CB zHE-g5QISV`M7mCL|IfR-^2L@lw_p2SSUd69WDZ7IW}y6J9mXw;B9j*~%1bH&b+AKq X11W|FP%9rymSnPr+h{U5kx3o^qxT@1 delta 204 zcmeyt(!e@FLXd;efdK>{B#@q{Y0k;P2o_`Dn3$>083AE4L`+<$oxlO)Fafa;5C?>L z_~ns0(Ik)$%0Jwa3@+!j%1Pt E02`+$1ONa4 diff --git a/src/loader/x86_64/elf/test_elfnote.bin b/src/loader/x86_64/elf/test_elfnote.bin old mode 100755 new mode 100644 index 36efd2d3f1a02ef7f9228e87506a8ef5c88e1246..e2fc7faa4f1ed2e46b7198b4f0dd88c9132f5c4b GIT binary patch delta 155 zcmeBRZD5@sA;`h#zyJae5=c+fH0R`C1dB0nOw82hjDWBiA|@`>=4SzNIDl9Ph$B+- zCf=76(Kusk+xc|=G4>Vb9&4T{xUk5 delta 161 zcmZo*?O>fCA;`n%zyJael7YcvqNX_~4 Date: Sun, 22 Mar 2020 16:14:53 +0800 Subject: [PATCH 3/3] Do not assume program header is sorted by VA Do not assume program header is sorted ascendantly by virtual address, otherwise loader_result.kernel_end may be wrong. Signed-off-by: Liu Jiang --- coverage_config_x86_64.json | 2 +- src/loader/x86_64/elf/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 27f86931..898d1bf0 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 74.7, + "coverage_score": 74.8, "exclude_path": "", "crate_features": "" } diff --git a/src/loader/x86_64/elf/mod.rs b/src/loader/x86_64/elf/mod.rs index 34ea6092..4b6de40b 100644 --- a/src/loader/x86_64/elf/mod.rs +++ b/src/loader/x86_64/elf/mod.rs @@ -236,10 +236,11 @@ impl KernelLoader for Elf { .read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize) .map_err(|_| Error::ReadKernelImage)?; - loader_result.kernel_end = mem_offset + let kernel_end = mem_offset .raw_value() .checked_add(phdr.p_memsz as GuestUsize) .ok_or(KernelLoaderError::MemoryOverflow)?; + loader_result.kernel_end = std::cmp::max(loader_result.kernel_end, kernel_end); } // elf image has no setup_header which is defined for bzImage