From ad58ca1de6882a89b9b917167289fcd4bfb2fcb5 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 20 Feb 2021 17:14:39 +0100 Subject: [PATCH] Give schemes a dangling address for empty slices. This allows schemes to avoid checking the length against zero before constructing a slice from pointer+len that the kernel gave. Additionally, the address is now non-canonical on x86, meaning that userspace will fail instead of continuing with UB, if they would ever forget to check the length. --- src/scheme/user.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/scheme/user.rs b/src/scheme/user.rs index b6a8922..bac2a50 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -131,7 +131,18 @@ impl UserInner { // TODO: More abstractions over grant creation! if size == 0 { - return Ok(VirtualAddress::new(0)); + // NOTE: Rather than returning NULL, we return a dummy dangling address, that is also + // non-canonical on x86. This means that scheme handlers do not need to check the + // length before creating a Rust slice (which cannot have NULL as address regardless of + // the length; this actually made nulld think that an empty path was invalid UTF-8 + // because of enum layout optimization), independent of whatever alignment this slice + // will have. Additionally, they would generate a general protection fault immediately + // if they ever tried to access this dangling address. + + // Set the most significant bit. + let dangling: usize = 1 << (core::mem::size_of::() * 8 - 1); + + return Ok(VirtualAddress::new(dangling)); } let context_lock = context_weak.upgrade().ok_or(Error::new(ESRCH))?;