fix(userspace): clip display rects, bounds-check session app ids and fat16 handles, reject bad fat16 geometry, session kills via process cap
This commit is contained in:
@@ -1,21 +1,25 @@
|
||||
use crate::adapters::mock_block::MockBlockDevice;
|
||||
use port_block_device::{BlockDevice, SectorId};
|
||||
use crate::filesystem::{DirEntry, FileSystem};
|
||||
use crate::fs::fat16::Fat16;
|
||||
use port_block_device::{BlockDevice, SectorId};
|
||||
|
||||
fn format_fat16_disk(sectors: usize) -> MockBlockDevice {
|
||||
let mut dev = MockBlockDevice::new(sectors);
|
||||
let mut boot = [0u8; 512];
|
||||
|
||||
// BPB
|
||||
boot[11] = 0x00; boot[12] = 0x02; // bytes_per_sector = 512
|
||||
boot[13] = 1; // sectors_per_cluster = 1
|
||||
boot[14] = 1; boot[15] = 0; // reserved_sectors = 1
|
||||
boot[16] = 1; // num_fats = 1
|
||||
boot[17] = 16; boot[18] = 0; // root_entry_count = 16
|
||||
boot[19] = sectors as u8; // total_sectors
|
||||
boot[11] = 0x00;
|
||||
boot[12] = 0x02; // bytes_per_sector = 512
|
||||
boot[13] = 1; // sectors_per_cluster = 1
|
||||
boot[14] = 1;
|
||||
boot[15] = 0; // reserved_sectors = 1
|
||||
boot[16] = 1; // num_fats = 1
|
||||
boot[17] = 16;
|
||||
boot[18] = 0; // root_entry_count = 16
|
||||
boot[19] = sectors as u8; // total_sectors
|
||||
boot[20] = (sectors >> 8) as u8;
|
||||
boot[22] = 1; boot[23] = 0; // sectors_per_fat = 1
|
||||
boot[22] = 1;
|
||||
boot[23] = 0; // sectors_per_fat = 1
|
||||
|
||||
// boot signature
|
||||
boot[510] = 0x55;
|
||||
@@ -110,3 +114,75 @@ fn create_duplicate_returns_none() {
|
||||
fs.create(b"dup.txt").map(|h| fs.close(h));
|
||||
assert!(fs.create(b"dup.txt").is_none());
|
||||
}
|
||||
|
||||
// ---- hostile input: handles from clients, geometry and chains from disk ----
|
||||
|
||||
fn with_boot_byte(sectors: usize, index: usize, value: u8) -> MockBlockDevice {
|
||||
let mut dev = format_fat16_disk(sectors);
|
||||
let mut boot = [0u8; 512];
|
||||
dev.read_sector(SectorId::new(0), &mut boot);
|
||||
boot[index] = value;
|
||||
dev.write_sector(SectorId::new(0), &boot);
|
||||
dev
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mount_rejects_geometry_the_driver_cannot_use() {
|
||||
// sectors_per_cluster 0 or 3, bytes_per_sector 513 or 0, no FATs, no
|
||||
// FAT sectors
|
||||
for (index, value) in [(13, 0), (13, 3), (11, 1), (12, 0), (16, 0), (22, 0)] {
|
||||
let dev = with_boot_byte(32, index, value);
|
||||
assert!(
|
||||
Fat16::mount(dev).is_none(),
|
||||
"byte {index} = {value} accepted"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handles_past_the_table_are_rejected_not_indexed() {
|
||||
use crate::filesystem::FileHandle;
|
||||
let mut fs = mount_test_disk();
|
||||
let mut buf = [0u8; 16];
|
||||
for raw in [8, 9, u16::MAX] {
|
||||
let h = FileHandle::new(raw);
|
||||
assert_eq!(fs.read(h, &mut buf), None);
|
||||
assert_eq!(fs.write(h, b"x"), None);
|
||||
assert_eq!(fs.file_size(h), None);
|
||||
fs.close(h);
|
||||
}
|
||||
}
|
||||
|
||||
/// Points a root-directory entry for `name` at `cluster` with `size`.
|
||||
fn plant_entry(dev: &mut MockBlockDevice, name: &[u8; 11], cluster: u16, size: u32) {
|
||||
// root dir starts after 1 reserved + 1 FAT sector
|
||||
let mut dir = [0u8; 512];
|
||||
dir[..11].copy_from_slice(name);
|
||||
dir[11] = 0x20;
|
||||
dir[26..28].copy_from_slice(&cluster.to_le_bytes());
|
||||
dir[28..32].copy_from_slice(&size.to_le_bytes());
|
||||
dev.write_sector(SectorId::new(2), &dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_file_pointing_at_cluster_zero_reads_nothing() {
|
||||
let mut dev = format_fat16_disk(32);
|
||||
plant_entry(&mut dev, b"BAD BIN", 0, 4096);
|
||||
let mut fs = Fat16::mount(dev).unwrap();
|
||||
let h = fs.open(b"bad.bin").expect("open");
|
||||
let mut buf = [0u8; 64];
|
||||
assert_eq!(fs.read(h, &mut buf), Some(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deleting_a_file_with_a_cyclic_chain_terminates() {
|
||||
let mut dev = format_fat16_disk(32);
|
||||
// cluster 2 -> 3 -> 2 -> ...
|
||||
let mut fat = [0u8; 512];
|
||||
fat[4..6].copy_from_slice(&3u16.to_le_bytes());
|
||||
fat[6..8].copy_from_slice(&2u16.to_le_bytes());
|
||||
dev.write_sector(SectorId::new(1), &fat);
|
||||
plant_entry(&mut dev, b"LOOP BIN", 2, 4096);
|
||||
let mut fs = Fat16::mount(dev).unwrap();
|
||||
assert!(fs.delete(b"loop.bin"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user