Next Generation WASM Microkernel Operating System
wasm os rust microkernel
at main 90 lines 3.0 kB view raw
1// Copyright 2025. Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8mycelium_bitfield::bitfield! { 9 /// Rules that dictate how a region of virtual memory may be accessed. 10 /// 11 /// # W^X 12 /// 13 /// In order to prevent malicious code execution as proactively as possible, 14 /// [`AccessRules`] can either allow *writes* OR *execution* but never both. This is enforced 15 /// through the [`WriteOrExecute`] enum field. 16 #[derive(PartialEq, Eq)] 17 pub struct AccessRules<u8> { 18 /// If set, reading from the memory region is allowed. 19 pub const READ: bool; 20 /// Whether executing, or writing this memory region is allowed (or neither). 21 pub const WRITE_OR_EXECUTE: WriteOrExecute; 22 /// If set, requires code in the memory region to use aarch64 Branch Target Identification. 23 /// Does nothing on non-aarch64 architectures. 24 pub const BTI: bool; 25 } 26} 27 28/// Whether executing, or writing this memory region is allowed (or neither). 29/// 30/// This is an enum to enforce [`W^X`] at the type-level. 31/// 32/// [`W^X`]: AccessRules 33#[derive(Copy, Clone, Debug, Eq, PartialEq)] 34#[repr(u8)] 35pub enum WriteOrExecute { 36 /// Neither writing nor execution of the memory region is allowed. 37 Neither = 0b00, 38 /// Writing to the memory region is allowed. 39 Write = 0b01, 40 /// Executing code from the memory region is allowed. 41 Execute = 0b10, 42} 43 44// ===== impl AccessRules ===== 45 46impl AccessRules { 47 pub const fn is_read_only(&self) -> bool { 48 const READ_MASK: u8 = AccessRules::READ.max_value(); 49 self.0 & READ_MASK == 1 50 } 51 52 pub fn allows_read(&self) -> bool { 53 self.get(Self::READ) 54 } 55 56 pub fn allows_write(&self) -> bool { 57 matches!(self.get(Self::WRITE_OR_EXECUTE), WriteOrExecute::Write) 58 } 59 60 pub fn allows_execution(&self) -> bool { 61 matches!(self.get(Self::WRITE_OR_EXECUTE), WriteOrExecute::Execute) 62 } 63} 64 65// ===== impl WriteOrExecute ===== 66 67impl mycelium_bitfield::FromBits<u8> for WriteOrExecute { 68 type Error = core::convert::Infallible; 69 70 /// The number of bits required to represent a value of this type. 71 const BITS: u32 = 2; 72 73 #[inline] 74 fn try_from_bits(bits: u8) -> Result<Self, Self::Error> { 75 match bits { 76 b if b == Self::Neither as u8 => Ok(Self::Neither), 77 b if b == Self::Write as u8 => Ok(Self::Write), 78 b if b == Self::Execute as u8 => Ok(Self::Execute), 79 _ => { 80 // this should never happen unless the bitpacking code is broken 81 unreachable!("invalid memory region access rules {bits:#b}") 82 } 83 } 84 } 85 86 #[inline] 87 fn into_bits(self) -> u8 { 88 self as u8 89 } 90}