Skip to content

Commit

Permalink
fix truncation bug in ldt segment limit check (was wrapping 0x10000 t…
Browse files Browse the repository at this point in the history
…o 0, causing all segment register loads in the ldt to trigger #gp)
  • Loading branch information
copy committed Oct 1, 2024
1 parent 4302ddd commit 372cc06
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/rust/cpu/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2373,16 +2373,22 @@ pub unsafe fn lookup_segment_selector(
}

let (table_offset, table_limit) = if selector.is_gdt() {
(*gdtr_offset as u32, *gdtr_size as u16)
(*gdtr_offset as u32, *gdtr_size as u32)
}
else {
(
*segment_offsets.offset(LDTR as isize) as u32,
*segment_limits.offset(LDTR as isize) as u16,
*segment_limits.offset(LDTR as isize) as u32,
)
};

if selector.descriptor_offset() > table_limit {
if selector.descriptor_offset() as u32 > table_limit {
dbg_log!(
"offset={:x} ldt: {:x} {:x}",
selector.descriptor_offset(),
table_offset,
table_limit
);
return Ok(Err(SelectorNullOrInvalid::OutsideOfTableLimit));
}

Expand Down Expand Up @@ -2580,6 +2586,7 @@ pub unsafe fn load_ldt(selector: i32) -> OrPageFault<()> {
let selector = SegmentSelector::of_u16(selector as u16);

if selector.is_null() {
dbg_log!("lldt: null loaded");
*segment_limits.offset(LDTR as isize) = 0;
*segment_offsets.offset(LDTR as isize) = 0;
*sreg.offset(LDTR as isize) = selector.raw;
Expand Down Expand Up @@ -2613,6 +2620,12 @@ pub unsafe fn load_ldt(selector: i32) -> OrPageFault<()> {
);
}

dbg_log!(
"lldt: {:x} offset={:x} limit={:x}",
selector.raw,
descriptor.base(),
descriptor.effective_limit()
);
*segment_limits.offset(LDTR as isize) = descriptor.effective_limit();
*segment_offsets.offset(LDTR as isize) = descriptor.base();
*sreg.offset(LDTR as isize) = selector.raw;
Expand Down

0 comments on commit 372cc06

Please sign in to comment.