From 67cc6799bd2e5e54b34d60e026aeaf7cb22e1a5e Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Tue, 22 Dec 2020 15:30:40 +0100
Subject: [PATCH] Fix possible UB by checking for null allocating FX.

Namely, the global allocator API in Rust, actually only returns a null
pointer on failure, rather than wrapping it in a Result, which AllocRef
does. Since Box::from_raw(null) is direct UB, this can in theory lead to
very strange behavior.
---
 src/syscall/process.rs | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 19a3210e..79629226 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -87,10 +87,20 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
             arch = context.arch.clone();
 
             if let Some(ref fx) = context.kfx {
-                let mut new_fx = unsafe { Box::from_raw(crate::ALLOCATOR.alloc(Layout::from_size_align_unchecked(1024, 16)) as *mut [u8; 1024]) };
-                for (new_b, b) in new_fx.iter_mut().zip(fx.iter()) {
-                    *new_b = *b;
-                }
+                let mut new_fx = unsafe {
+                    let new_fx_ptr = crate::ALLOCATOR.alloc(Layout::from_size_align_unchecked(1024, 16));
+                    if new_fx_ptr.is_null() {
+                        // FIXME: It's mildly ironic that the only place where clone can fail with
+                        // ENOMEM, is when copying 1024 bytes to merely store vector registers.
+                        // Although in order to achieve full kernel-panic immunity, we'll need to
+                        // completely phase out all usage of liballoc data structures, and use our
+                        // own library/port liballoc, since panicking on OOM is not good for a
+                        // kernel.
+                        return Err(Error::new(ENOMEM));
+                    }
+                    new_fx_ptr.copy_from_nonoverlapping(fx.as_ptr(), fx.len());
+                    Box::from_raw(new_fx_ptr as *mut [u8; 1024])
+                };
                 kfx_opt = Some(new_fx);
             }
 
-- 
GitLab