diff --git a/kernel/src/arch/loongarch/cpu.rs b/kernel/src/arch/loongarch/cpu.rs index 213f281c6..21ae4eadd 100644 --- a/kernel/src/arch/loongarch/cpu.rs +++ b/kernel/src/arch/loongarch/cpu.rs @@ -152,10 +152,7 @@ impl TryFrom<&CpuExceptionInfo> for PageFaultInfo { _ => return Err(()), }; - Ok(PageFaultInfo { - address: value.page_fault_addr, - required_perms, - }) + Ok(PageFaultInfo::new(value.page_fault_addr, required_perms)) } } diff --git a/kernel/src/arch/riscv/cpu.rs b/kernel/src/arch/riscv/cpu.rs index c05aa69ae..18a3581ec 100644 --- a/kernel/src/arch/riscv/cpu.rs +++ b/kernel/src/arch/riscv/cpu.rs @@ -150,10 +150,7 @@ impl TryFrom<&CpuException> for PageFaultInfo { _ => return Err(()), }; - Ok(PageFaultInfo { - address: *fault_addr, - required_perms, - }) + Ok(PageFaultInfo::new(*fault_addr, required_perms)) } } diff --git a/kernel/src/arch/x86/cpu.rs b/kernel/src/arch/x86/cpu.rs index e5ae85bea..c5477c051 100644 --- a/kernel/src/arch/x86/cpu.rs +++ b/kernel/src/arch/x86/cpu.rs @@ -145,10 +145,7 @@ impl From<&RawPageFaultInfo> for PageFaultInfo { VmPerms::READ }; - PageFaultInfo { - address: raw_info.addr, - required_perms, - } + PageFaultInfo::new(raw_info.addr, required_perms) } } diff --git a/kernel/src/process/posix_thread/futex.rs b/kernel/src/process/posix_thread/futex.rs index 86be02311..34cb49667 100644 --- a/kernel/src/process/posix_thread/futex.rs +++ b/kernel/src/process/posix_thread/futex.rs @@ -72,10 +72,7 @@ pub fn futex_wait_bitset( // The futex word is aligned on a 4-byte boundary, so it cannot cross the page boundary. user_space .vmar() - .handle_page_fault(&PageFaultInfo { - address: futex_addr, - required_perms: VmPerms::READ, - }) + .handle_page_fault(&PageFaultInfo::new(futex_addr, VmPerms::READ)) .map_err(|_| { Error::with_message( Errno::EFAULT, @@ -288,10 +285,10 @@ pub fn futex_wake_op( // The futex word is aligned on a 4-byte boundary, so it cannot cross the page boundary. user_space .vmar() - .handle_page_fault(&PageFaultInfo { - address: futex_addr_2, - required_perms: VmPerms::READ | VmPerms::WRITE, - }) + .handle_page_fault(&PageFaultInfo::new( + futex_addr_2, + VmPerms::READ | VmPerms::WRITE, + )) .map_err(|_| { Error::with_message( Errno::EFAULT, diff --git a/kernel/src/thread/exception.rs b/kernel/src/thread/exception.rs index 61019beb7..7f2f42d57 100644 --- a/kernel/src/thread/exception.rs +++ b/kernel/src/thread/exception.rs @@ -28,6 +28,30 @@ pub struct PageFaultInfo { /// The [`VmPerms`] required by the memory operation that causes page fault. /// For example, a "store" operation may require `VmPerms::WRITE`. pub required_perms: VmPerms, + + /// Whether this page fault is forced (e.g., manually triggered by `ptrace`). + /// A forced page fault may bypass some permission checks. + pub is_forced: bool, + + _private: (), +} + +impl PageFaultInfo { + /// Creates a new `PageFaultInfo`. + pub fn new(address: Vaddr, required_perms: VmPerms) -> Self { + Self { + address, + required_perms, + is_forced: false, + _private: (), + } + } + + /// Marks this page fault as forced. + pub fn force(mut self) -> Self { + self.is_forced = true; + self + } } /// We can't handle most exceptions, just send self a fault signal before return to user space. diff --git a/kernel/src/vm/vmar/vmar_impls/access_remote.rs b/kernel/src/vm/vmar/vmar_impls/access_remote.rs index 97bc70c05..9b0c44a9b 100644 --- a/kernel/src/vm/vmar/vmar_impls/access_remote.rs +++ b/kernel/src/vm/vmar/vmar_impls/access_remote.rs @@ -150,10 +150,7 @@ impl Vmar { Some(_) | None => (), } - let page_fault_info = PageFaultInfo { - address: vaddr, - required_perms: required_page_flags.into(), - }; + let page_fault_info = PageFaultInfo::new(vaddr, required_page_flags.into()).force(); self.handle_page_fault(&page_fault_info)?; item = self.query_page(vaddr)?;