Skip to content

Commit 7051f97

Browse files
committed
slice for safety
1 parent e5a6612 commit 7051f97

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

src/structures/gdt.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::PrivilegeLevel;
55
use bit_field::BitField;
66
use bitflags::bitflags;
77
use core::{cmp, fmt, mem};
8+
use crate::structures::tss::InvalidIoMap;
89

910
/// Specifies which element to load into a segment from
1011
/// descriptor tables (i.e., is a index to LDT or GDT table
@@ -307,7 +308,30 @@ impl Descriptor {
307308
#[inline]
308309
pub fn tss_segment(tss: &'static TaskStateSegment) -> Descriptor {
309310
// SAFETY: if iomap_size is zero, there are no requirements to uphold.
310-
unsafe { Self::tss_segment_with_iomap(tss, 0) }
311+
unsafe { Self::tss_segment_raw(tss, 0) }
312+
}
313+
314+
/// Creates a TSS system descriptor for the given TSS, setting up the IO permissions bitmap.
315+
pub fn tss_segment_with_iomap(
316+
tss: &'static TaskStateSegment,
317+
iomap: &'static [u8],
318+
) -> Result<Descriptor, InvalidIoMap> {
319+
if iomap.len() > 8193 {
320+
return Err(InvalidIoMap::TooLong { len: iomap.len() })
321+
}
322+
323+
let distance = iomap.as_ptr() as usize - tss as *const _ as usize;
324+
if distance > 0xdfff {
325+
return Err(InvalidIoMap::TooFarFromTss { distance })
326+
}
327+
328+
let last_byte = *iomap.last().unwrap_or(&0xff);
329+
if last_byte != 0xff {
330+
return Err(InvalidIoMap::InvalidTerminatingByte { byte: last_byte })
331+
}
332+
333+
// SAFETY: all invariants checked above
334+
Ok(unsafe { Self::tss_segment_raw(tss, iomap.len() as u16) })
311335
}
312336

313337
/// Creates a TSS system descriptor for the given TSS, setting up the IO permissions bitmap.
@@ -317,7 +341,7 @@ impl Descriptor {
317341
/// There must be a valid IO map at `(tss as *const u8).offset(tss.iomap_base)`
318342
/// of length `iomap_size`, with the terminating `0xFF` byte. Additionally, `iomap_base` must
319343
/// not exceed `0xDFFF`.
320-
pub unsafe fn tss_segment_with_iomap(
344+
unsafe fn tss_segment_raw(
321345
tss: &'static TaskStateSegment,
322346
iomap_size: u16,
323347
) -> Descriptor {

src/structures/tss.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,21 @@ impl TaskStateSegment {
3838
}
3939
}
4040
}
41+
42+
/// The given IO permissions bitmap is invalid.
43+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
44+
pub enum InvalidIoMap {
45+
/// The IO permissions bitmap is too far from the TSS. It must be within `0xdfff` bytes of the
46+
/// start of the TSS.
47+
TooFarFromTss {
48+
distance: usize,
49+
},
50+
/// The final byte of the IO permissions bitmap was not 0xff
51+
InvalidTerminatingByte {
52+
byte: u8,
53+
},
54+
/// The IO permissions bitmap exceeds the maximum length (8193).
55+
TooLong {
56+
len: usize
57+
},
58+
}

0 commit comments

Comments
 (0)