Skip to content

Commit 707db11

Browse files
authored
Merge pull request #524 from rust-osdev/fix/buffer-overflow
fix buffer overflow in `DiskAccess::read_exact_into`
2 parents 9a5cf6b + f5b3bdb commit 707db11

File tree

7 files changed

+22
-28
lines changed

7 files changed

+22
-28
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ overflow-checks = false
8383
# duplicated from `bios/stage-2/Cargo.toml`
8484
[profile.stage-2]
8585
inherits = "release"
86-
opt-level = "s"
86+
opt-level = "z"
8787
codegen-units = 1
8888
debug = false
8989
overflow-checks = true

bios/stage-2/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bootloader-x86_64-bios-common = { workspace = true }
1818
# See https://github.com/rust-lang/cargo/issues/8264 for details.
1919
[profile.stage-2]
2020
inherits = "release"
21-
opt-level = "s"
21+
opt-level = "z"
2222
codegen-units = 1
2323
debug = false
2424
overflow-checks = true

bios/stage-2/src/disk.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ pub struct DiskAccess {
88
}
99

1010
impl Read for DiskAccess {
11-
unsafe fn read_exact(&mut self, len: usize) -> &[u8] {
12-
let current_sector_offset = usize::try_from(self.current_offset % 512).unwrap();
11+
unsafe fn read_exact_at(&mut self, len: usize, offset: u64) -> &[u8] {
12+
self.seek(SeekFrom::Start(offset - (offset % 512)));
13+
let current_sector_offset = usize::try_from(offset % 512).unwrap();
1314

1415
static mut TMP_BUF: AlignedArrayBuffer<1024> = AlignedArrayBuffer {
1516
buffer: [0; 512 * 2],
@@ -62,6 +63,7 @@ impl Seek for DiskAccess {
6263
fn seek(&mut self, pos: SeekFrom) -> u64 {
6364
match pos {
6465
SeekFrom::Start(offset) => {
66+
assert_eq!(offset % 512, 0);
6567
self.current_offset = offset;
6668
self.current_offset
6769
}
@@ -70,7 +72,7 @@ impl Seek for DiskAccess {
7072
}
7173

7274
pub trait Read {
73-
unsafe fn read_exact(&mut self, len: usize) -> &[u8];
75+
unsafe fn read_exact_at(&mut self, len: usize, offset: u64) -> &[u8];
7476
fn read_exact_into(&mut self, len: usize, buf: &mut dyn AlignedBuffer);
7577
}
7678

bios/stage-2/src/fat.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ struct Bpb {
3232
}
3333

3434
impl Bpb {
35-
fn parse<D: Read + Seek>(disk: &mut D) -> Self {
36-
disk.seek(SeekFrom::Start(0));
37-
let raw = unsafe { disk.read_exact(512) };
35+
fn parse<D: Read>(disk: &mut D) -> Self {
36+
let raw = unsafe { disk.read_exact_at(512, 0) };
3837

3938
let bytes_per_sector = u16::from_le_bytes(raw[11..13].try_into().unwrap());
4039
let sectors_per_cluster = raw[13];
@@ -256,7 +255,7 @@ struct Traverser<'a, D> {
256255

257256
impl<D> Traverser<'_, D>
258257
where
259-
D: Read + Seek,
258+
D: Read,
260259
{
261260
fn next_cluster(&mut self) -> Result<Option<Cluster>, ()> {
262261
let entry = classify_fat_entry(
@@ -286,7 +285,7 @@ where
286285

287286
impl<D> Iterator for Traverser<'_, D>
288287
where
289-
D: Read + Seek,
288+
D: Read,
290289
{
291290
type Item = Result<Cluster, ()>;
292291

@@ -476,28 +475,25 @@ enum FileFatEntry {
476475

477476
fn fat_entry_of_nth_cluster<D>(disk: &mut D, fat_type: FatType, fat_start: u64, n: u32) -> u32
478477
where
479-
D: Seek + Read,
478+
D: Read,
480479
{
481480
debug_assert!(n >= 2);
482481
match fat_type {
483482
FatType::Fat32 => {
484483
let base = n as u64 * 4;
485-
disk.seek(SeekFrom::Start(fat_start + base));
486-
let buf = unsafe { disk.read_exact(4) };
484+
let buf = unsafe { disk.read_exact_at(4, fat_start + base) };
487485
let buf: [u8; 4] = buf.try_into().unwrap();
488486
u32::from_le_bytes(buf) & 0x0FFFFFFF
489487
}
490488
FatType::Fat16 => {
491489
let base = n as u64 * 2;
492-
disk.seek(SeekFrom::Start(fat_start + base));
493-
let buf = unsafe { disk.read_exact(2) };
490+
let buf = unsafe { disk.read_exact_at(2, fat_start + base) };
494491
let buf: [u8; 2] = buf.try_into().unwrap();
495492
u16::from_le_bytes(buf) as u32
496493
}
497494
FatType::Fat12 => {
498495
let base = n as u64 + (n as u64 / 2);
499-
disk.seek(SeekFrom::Start(fat_start + base));
500-
let buf = unsafe { disk.read_exact(2) };
496+
let buf = unsafe { disk.read_exact_at(2, fat_start + base) };
501497
let buf: [u8; 2] = buf.try_into().unwrap();
502498
let entry16 = u16::from_le_bytes(buf);
503499
if n & 1 == 0 {

build.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ fn build_bios_stage_2() -> PathBuf {
215215
cmd.env_remove("RUSTFLAGS");
216216
cmd.env_remove("CARGO_ENCODED_RUSTFLAGS");
217217
cmd.env_remove("RUSTC_WORKSPACE_WRAPPER"); // used by clippy
218-
cmd.env(
219-
"RUSTFLAGS",
220-
"-Csymbol-mangling-version=legacy -Zunstable-options",
221-
);
222218
let status = cmd
223219
.status()
224220
.expect("failed to run cargo install for bios second stage");

examples/basic/Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/test_kernels/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)