Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix possible bugs when loading ELF/PVH kernel #29

Merged
merged 4 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ bzimage = []
pe = []

[dependencies]
vm-memory = {version = ">=0.2.0", features = ["backend-mmap"]}
vm-memory = ">=0.2.0"

[dev-dependencies]
vm-memory = {features = ["backend-mmap"]}
2 changes: 1 addition & 1 deletion coverage_config_x86_64.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"coverage_score": 74.7,
"coverage_score": 74.8,
"exclude_path": "",
"crate_features": ""
}
22 changes: 16 additions & 6 deletions src/loader/x86_64/elf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -249,6 +250,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
Expand Down Expand Up @@ -281,11 +285,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)
Expand All @@ -306,7 +316,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)?;

Expand Down
Binary file modified src/loader/x86_64/elf/test_badnote.bin
100755 → 100644
Binary file not shown.
Binary file modified src/loader/x86_64/elf/test_elfnote.bin
100755 → 100644
Binary file not shown.