diff --git a/src/context/context.rs b/src/context/context.rs
index f9c01ea4d08212cea1903be7139580ef5e2e06c4..b06a397f69d4ad41b6b28fd1ab7e0e0c4503e8bd 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -147,7 +147,7 @@ pub struct Context {
     /// User grants
     pub grants: Arc<Mutex<Vec<Grant>>>,
     /// The name of the context
-    pub name: Arc<Mutex<Vec<u8>>>,
+    pub name: Arc<Mutex<Box<[u8]>>>,
     /// The current working directory
     pub cwd: Arc<Mutex<Vec<u8>>>,
     /// Kernel events
@@ -191,7 +191,7 @@ impl Context {
             sigstack: None,
             tls: None,
             grants: Arc::new(Mutex::new(Vec::new())),
-            name: Arc::new(Mutex::new(Vec::new())),
+            name: Arc::new(Mutex::new(Vec::new().into_boxed_slice())),
             cwd: Arc::new(Mutex::new(Vec::new())),
             events: Arc::new(WaitQueue::new()),
             env: Arc::new(Mutex::new(BTreeMap::new())),
diff --git a/src/scheme/sys/exe.rs b/src/scheme/sys/exe.rs
index 0fa7a82d8c09c0eb39c2b1fdf8aa74efdaff1ed0..87cb0d66eb689a7c5d58239b39f5f42a7e35995b 100644
--- a/src/scheme/sys/exe.rs
+++ b/src/scheme/sys/exe.rs
@@ -9,7 +9,7 @@ pub fn resource() -> Result<Vec<u8>> {
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
         let name = context.name.lock();
-        name.clone()
+        name.clone().into_vec()
     };
     name.push(b'\n');
     Ok(name)
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 1b0bb2dd117dce1061e6d59c7fc7d102197bdb5a..049582ad0f97f5c901a33db4d1bcdfd6982c5302 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -542,306 +542,355 @@ impl Drop for ExecFile {
     }
 }
 
-pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
-    let entry;
+fn exec_noreturn(elf: elf::Elf, canonical: Box<[u8]>, setuid: Option<u32>, setgid: Option<u32>, args: Box<[Box<[u8]>]>) -> ! {
+    let entry = elf.entry();
     let mut sp = ::USER_STACK_OFFSET + ::USER_STACK_SIZE - 256;
 
     {
-        let mut args = Vec::new();
-        for arg_ptr in arg_ptrs {
-            let arg = validate_slice(arg_ptr[0] as *const u8, arg_ptr[1])?;
-            args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory
-        }
-
-        let (uid, gid, mut canonical) = {
+        let (vfork, ppid, files) = {
             let contexts = context::contexts();
-            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
-            let context = context_lock.read();
-            (context.euid, context.egid, context.canonicalize(path))
-        };
+            let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exec_noreturn pid not found");
+            let mut context = context_lock.write();
 
-        let mut stat: Stat;
-        let mut data: Vec<u8>;
-        loop {
-            let file = ExecFile(syscall::open(&canonical, syscall::flag::O_RDONLY)?);
+            // Set name
+            context.name = Arc::new(Mutex::new(canonical));
 
-            stat = Stat::default();
-            syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file.0, &mut stat)?;
+            empty(&mut context, false);
 
-            let mut perm = stat.st_mode & 0o7;
-            if stat.st_uid == uid {
-                perm |= (stat.st_mode >> 6) & 0o7;
-            }
-            if stat.st_gid == gid {
-                perm |= (stat.st_mode >> 3) & 0o7;
-            }
-            if uid == 0 {
-                perm |= 0o7;
+            if let Some(uid) = setuid {
+                context.euid = uid;
             }
 
-            if perm & 0o1 != 0o1 {
-                return Err(Error::new(EACCES));
+            if let Some(gid) = setgid {
+                context.egid = gid;
             }
 
-            //TODO: Only read elf header, not entire file. Then read required segments
-            data = vec![0; stat.st_size as usize];
-            syscall::file_op_mut_slice(syscall::number::SYS_READ, file.0, &mut data)?;
-            drop(file);
-
-            if data.starts_with(b"#!") {
-                if let Some(line) = data[2..].split(|&b| b == b'\n').next() {
-                    // Strip whitespace
-                    let line = &line[line.iter().position(|&b| b != b' ')
-                                         .unwrap_or(0)..];
-                    let executable = line.split(|x| *x == b' ').next().unwrap_or(b"");
-                    let mut parts = line.split(|x| *x == b' ')
-                        .map(|x| x.iter().cloned().collect::<Vec<_>>())
-                        .collect::<Vec<_>>();
-                    if ! args.is_empty() {
-                        args.remove(0);
+            // Map and copy new segments
+            let mut tls_option = None;
+            for segment in elf.segments() {
+                if segment.p_type == program_header::PT_LOAD {
+                    let voff = segment.p_vaddr % 4096;
+                    let vaddr = segment.p_vaddr - voff;
+
+                    let mut memory = context::memory::Memory::new(
+                        VirtualAddress::new(vaddr as usize),
+                        segment.p_memsz as usize + voff as usize,
+                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE,
+                        true
+                    );
+
+                    unsafe {
+                        // Copy file data
+                        intrinsics::copy((elf.data.as_ptr() as usize + segment.p_offset as usize) as *const u8,
+                                        segment.p_vaddr as *mut u8,
+                                        segment.p_filesz as usize);
+                    }
+
+                    let mut flags = EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE;
+
+                    if segment.p_flags & program_header::PF_R == program_header::PF_R {
+                        flags.insert(EntryFlags::PRESENT);
+                    }
+
+                    // W ^ X. If it is executable, do not allow it to be writable, even if requested
+                    if segment.p_flags & program_header::PF_X == program_header::PF_X {
+                        flags.remove(EntryFlags::NO_EXECUTE);
+                    } else if segment.p_flags & program_header::PF_W == program_header::PF_W {
+                        flags.insert(EntryFlags::WRITABLE);
                     }
-                    parts.push(path.to_vec());
-                    parts.extend(args.iter().cloned());
-                    args = parts;
-                    canonical = {
-                        let contexts = context::contexts();
-                        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
-                        let context = context_lock.read();
-                        context.canonicalize(executable)
+
+                    memory.remap(flags);
+
+                    context.image.push(memory.to_shared());
+                } else if segment.p_type == program_header::PT_TLS {
+                    let memory = context::memory::Memory::new(
+                        VirtualAddress::new(::USER_TCB_OFFSET),
+                        4096,
+                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
+                        true
+                    );
+                    let aligned_size = if segment.p_align > 0 {
+                        ((segment.p_memsz + (segment.p_align - 1))/segment.p_align) * segment.p_align
+                    } else {
+                        segment.p_memsz
                     };
-                } else {
-                    println!("invalid script {}", unsafe { str::from_utf8_unchecked(path) });
-                    return Err(Error::new(ENOEXEC));
+                    let rounded_size = ((aligned_size + 4095)/4096) * 4096;
+                    let rounded_offset = rounded_size - aligned_size;
+                    let tcb_offset = ::USER_TLS_OFFSET + rounded_size as usize;
+                    unsafe { *(::USER_TCB_OFFSET as *mut usize) = tcb_offset; }
+
+                    context.image.push(memory.to_shared());
+
+                    tls_option = Some((
+                        VirtualAddress::new(segment.p_vaddr as usize),
+                        segment.p_filesz as usize,
+                        rounded_size as usize,
+                        rounded_offset as usize,
+                    ));
                 }
-            } else {
-                break;
             }
-        }
 
-        match elf::Elf::from(&data) {
-            Ok(elf) => {
-                entry = elf.entry();
+            // Map heap
+            context.heap = Some(context::memory::Memory::new(
+                VirtualAddress::new(::USER_HEAP_OFFSET),
+                0,
+                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
+                true
+            ).to_shared());
+
+            // Map stack
+            context.stack = Some(context::memory::Memory::new(
+                VirtualAddress::new(::USER_STACK_OFFSET),
+                ::USER_STACK_SIZE,
+                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
+                true
+            ));
+
+            // Map stack
+            context.sigstack = Some(context::memory::Memory::new(
+                VirtualAddress::new(::USER_SIGSTACK_OFFSET),
+                ::USER_SIGSTACK_SIZE,
+                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
+                true
+            ));
+
+            // Map TLS
+            if let Some((master, file_size, size, offset)) = tls_option {
+                let mut tls = context::memory::Tls {
+                    master: master,
+                    file_size: file_size,
+                    mem: context::memory::Memory::new(
+                        VirtualAddress::new(::USER_TLS_OFFSET),
+                        size,
+                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
+                        true
+                    ),
+                    offset: offset,
+                };
 
-                drop(path); // Drop so that usage is not allowed after unmapping context
-                drop(arg_ptrs); // Drop so that usage is not allowed after unmapping context
+                unsafe {
+                    tls.load();
+                }
 
-                let (vfork, ppid, files) = {
-                    let contexts = context::contexts();
-                    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
-                    let mut context = context_lock.write();
+                context.tls = Some(tls);
+            }
 
-                    // Set name
-                    context.name = Arc::new(Mutex::new(canonical));
+            // Push arguments
+            let mut arg_size = 0;
+            for arg in args.iter().rev() {
+                sp -= mem::size_of::<usize>();
+                unsafe { *(sp as *mut usize) = ::USER_ARG_OFFSET + arg_size; }
+                sp -= mem::size_of::<usize>();
+                unsafe { *(sp as *mut usize) = arg.len(); }
 
-                    empty(&mut context, false);
+                arg_size += arg.len();
+            }
 
-                    if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID {
-                        context.euid = stat.st_uid;
-                    }
+            sp -= mem::size_of::<usize>();
+            unsafe { *(sp as *mut usize) = args.len(); }
 
-                    if stat.st_mode & syscall::flag::MODE_SETGID == syscall::flag::MODE_SETGID {
-                        context.egid = stat.st_gid;
-                    }
+            if arg_size > 0 {
+                let mut memory = context::memory::Memory::new(
+                    VirtualAddress::new(::USER_ARG_OFFSET),
+                    arg_size,
+                    EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE,
+                    true
+                );
 
-                    // Map and copy new segments
-                    let mut tls_option = None;
-                    for segment in elf.segments() {
-                        if segment.p_type == program_header::PT_LOAD {
-                            let voff = segment.p_vaddr % 4096;
-                            let vaddr = segment.p_vaddr - voff;
-
-                            let mut memory = context::memory::Memory::new(
-                                VirtualAddress::new(vaddr as usize),
-                                segment.p_memsz as usize + voff as usize,
-                                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE,
-                                true
-                            );
-
-                            unsafe {
-                                // Copy file data
-                                intrinsics::copy((elf.data.as_ptr() as usize + segment.p_offset as usize) as *const u8,
-                                                segment.p_vaddr as *mut u8,
-                                                segment.p_filesz as usize);
-                            }
-
-                            let mut flags = EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE;
-
-                            if segment.p_flags & program_header::PF_R == program_header::PF_R {
-                                flags.insert(EntryFlags::PRESENT);
-                            }
-
-                            // W ^ X. If it is executable, do not allow it to be writable, even if requested
-                            if segment.p_flags & program_header::PF_X == program_header::PF_X {
-                                flags.remove(EntryFlags::NO_EXECUTE);
-                            } else if segment.p_flags & program_header::PF_W == program_header::PF_W {
-                                flags.insert(EntryFlags::WRITABLE);
-                            }
-
-                            memory.remap(flags);
-
-                            context.image.push(memory.to_shared());
-                        } else if segment.p_type == program_header::PT_TLS {
-                            let memory = context::memory::Memory::new(
-                                VirtualAddress::new(::USER_TCB_OFFSET),
-                                4096,
-                                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
-                                true
-                            );
-                            let aligned_size = if segment.p_align > 0 {
-                                ((segment.p_memsz + (segment.p_align - 1))/segment.p_align) * segment.p_align
-                            } else {
-                                segment.p_memsz
-                            };
-                            let rounded_size = ((aligned_size + 4095)/4096) * 4096;
-                            let rounded_offset = rounded_size - aligned_size;
-                            let tcb_offset = ::USER_TLS_OFFSET + rounded_size as usize;
-                            unsafe { *(::USER_TCB_OFFSET as *mut usize) = tcb_offset; }
-
-                            context.image.push(memory.to_shared());
-
-                            tls_option = Some((
-                                VirtualAddress::new(segment.p_vaddr as usize),
-                                segment.p_filesz as usize,
-                                rounded_size as usize,
-                                rounded_offset as usize,
-                            ));
-                        }
+                let mut arg_offset = 0;
+                for arg in args.iter().rev() {
+                    unsafe {
+                        intrinsics::copy(arg.as_ptr(),
+                               (::USER_ARG_OFFSET + arg_offset) as *mut u8,
+                               arg.len());
                     }
 
-                    // Map heap
-                    context.heap = Some(context::memory::Memory::new(
-                        VirtualAddress::new(::USER_HEAP_OFFSET),
-                        0,
-                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
-                        true
-                    ).to_shared());
+                    arg_offset += arg.len();
+                }
 
-                    // Map stack
-                    context.stack = Some(context::memory::Memory::new(
-                        VirtualAddress::new(::USER_STACK_OFFSET),
-                        ::USER_STACK_SIZE,
-                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
-                        true
-                    ));
+                memory.remap(EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE);
 
-                    // Map stack
-                    context.sigstack = Some(context::memory::Memory::new(
-                        VirtualAddress::new(::USER_SIGSTACK_OFFSET),
-                        ::USER_SIGSTACK_SIZE,
-                        EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
-                        true
-                    ));
+                context.image.push(memory.to_shared());
+            }
 
-                    // Map TLS
-                    if let Some((master, file_size, size, offset)) = tls_option {
-                        let mut tls = context::memory::Tls {
-                            master: master,
-                            file_size: file_size,
-                            mem: context::memory::Memory::new(
-                                VirtualAddress::new(::USER_TLS_OFFSET),
-                                size,
-                                EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE,
-                                true
-                            ),
-                            offset: offset,
-                        };
+            context.actions = Arc::new(Mutex::new(vec![(
+                SigAction {
+                    sa_handler: unsafe { mem::transmute(SIG_DFL) },
+                    sa_mask: [0; 2],
+                    sa_flags: 0,
+                },
+                0
+            ); 128]));
 
-                        unsafe {
-                            tls.load();
-                        }
+            let vfork = context.vfork;
+            context.vfork = false;
 
-                        context.tls = Some(tls);
-                    }
+            let files = Arc::clone(&context.files);
 
-                    // Push arguments
-                    let mut arg_size = 0;
-                    for arg in args.iter().rev() {
-                        sp -= mem::size_of::<usize>();
-                        unsafe { *(sp as *mut usize) = ::USER_ARG_OFFSET + arg_size; }
-                        sp -= mem::size_of::<usize>();
-                        unsafe { *(sp as *mut usize) = arg.len(); }
+            (vfork, context.ppid, files)
+        };
 
-                        arg_size += arg.len();
-                    }
+        for (fd, file_option) in files.lock().iter_mut().enumerate() {
+            let mut cloexec = false;
+            if let Some(ref file) = *file_option {
+                if file.cloexec {
+                    cloexec = true;
+                }
+            }
 
-                    sp -= mem::size_of::<usize>();
-                    unsafe { *(sp as *mut usize) = args.len(); }
+            if cloexec {
+                let _ = file_option.take().unwrap().close(FileHandle::from(fd));
+            }
+        }
 
-                    if arg_size > 0 {
-                        let mut memory = context::memory::Memory::new(
-                            VirtualAddress::new(::USER_ARG_OFFSET),
-                            arg_size,
-                            EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE,
-                            true
-                        );
+        if vfork {
+            let contexts = context::contexts();
+            if let Some(context_lock) = contexts.get(ppid) {
+                let mut context = context_lock.write();
+                if ! context.unblock() {
+                    println!("{} not blocked for exec vfork unblock", ppid.into());
+                }
+            } else {
+                println!("{} not found for exec vfork unblock", ppid.into());
+            }
+        }
+    }
 
-                        let mut arg_offset = 0;
-                        for arg in args.iter().rev() {
-                            unsafe {
-                                intrinsics::copy(arg.as_ptr(),
-                                       (::USER_ARG_OFFSET + arg_offset) as *mut u8,
-                                       arg.len());
-                            }
+    // Go to usermode
+    unsafe { usermode(entry, sp, 0); }
+}
 
-                            arg_offset += arg.len();
-                        }
+pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
+    let mut args = Vec::new();
+    for arg_ptr in arg_ptrs {
+        let arg = validate_slice(arg_ptr[0] as *const u8, arg_ptr[1])?;
+        // Argument must be moved into kernel space before exec unmaps all memory
+        args.push(arg.to_vec().into_boxed_slice());
+    }
 
-                        memory.remap(EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE);
+    let (uid, gid, mut canonical) = {
+        let contexts = context::contexts();
+        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+        let context = context_lock.read();
+        (context.euid, context.egid, context.canonicalize(path))
+    };
 
-                        context.image.push(memory.to_shared());
-                    }
+    let mut stat: Stat;
+    let mut data: Vec<u8>;
+    loop {
+        let file = ExecFile(syscall::open(&canonical, syscall::flag::O_RDONLY)?);
 
-                    context.actions = Arc::new(Mutex::new(vec![(
-                        SigAction {
-                            sa_handler: unsafe { mem::transmute(SIG_DFL) },
-                            sa_mask: [0; 2],
-                            sa_flags: 0,
-                        },
-                        0
-                    ); 128]));
+        stat = Stat::default();
+        syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file.0, &mut stat)?;
 
-                    let vfork = context.vfork;
-                    context.vfork = false;
+        let mut perm = stat.st_mode & 0o7;
+        if stat.st_uid == uid {
+            perm |= (stat.st_mode >> 6) & 0o7;
+        }
+        if stat.st_gid == gid {
+            perm |= (stat.st_mode >> 3) & 0o7;
+        }
+        if uid == 0 {
+            perm |= 0o7;
+        }
 
-                    let files = Arc::clone(&context.files);
+        if perm & 0o1 != 0o1 {
+            return Err(Error::new(EACCES));
+        }
 
-                    (vfork, context.ppid, files)
+        //TODO: Only read elf header, not entire file. Then read required segments
+        data = vec![0; stat.st_size as usize];
+        syscall::file_op_mut_slice(syscall::number::SYS_READ, file.0, &mut data)?;
+        drop(file);
+
+        if data.starts_with(b"#!") {
+            if let Some(line) = data[2..].split(|&b| b == b'\n').next() {
+                // Strip whitespace
+                let line = &line[line.iter().position(|&b| b != b' ')
+                                     .unwrap_or(0)..];
+                let executable = line.split(|x| *x == b' ').next().unwrap_or(b"");
+                let mut parts = line.split(|x| *x == b' ')
+                    .map(|x| x.iter().cloned().collect::<Vec<_>>().into_boxed_slice())
+                    .collect::<Vec<_>>();
+                if ! args.is_empty() {
+                    args.remove(0);
+                }
+                parts.push(path.to_vec().into_boxed_slice());
+                parts.extend(args.iter().cloned());
+                args = parts;
+                canonical = {
+                    let contexts = context::contexts();
+                    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+                    let context = context_lock.read();
+                    context.canonicalize(executable)
                 };
+            } else {
+                println!("invalid script {}", unsafe { str::from_utf8_unchecked(path) });
+                return Err(Error::new(ENOEXEC));
+            }
+        } else {
+            break;
+        }
+    }
 
-                for (fd, file_option) in files.lock().iter_mut().enumerate() {
-                    let mut cloexec = false;
-                    if let Some(ref file) = *file_option {
-                        if file.cloexec {
-                            cloexec = true;
-                        }
-                    }
+    // Set UID and GID are determined after resolving any hashbangs
+    let setuid = if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID {
+        Some(stat.st_uid)
+    } else {
+        None
+    };
 
-                    if cloexec {
-                        let _ = file_option.take().unwrap().close(FileHandle::from(fd));
-                    }
-                }
+    let setgid = if stat.st_mode & syscall::flag::MODE_SETGID == syscall::flag::MODE_SETGID {
+        Some(stat.st_gid)
+    } else {
+        None
+    };
 
-                if vfork {
-                    let contexts = context::contexts();
-                    if let Some(context_lock) = contexts.get(ppid) {
-                        let mut context = context_lock.write();
-                        if ! context.unblock() {
-                            println!("{} not blocked for exec vfork unblock", ppid.into());
-                        }
-                    } else {
-                        println!("{} not found for exec vfork unblock", ppid.into());
+    // The argument list is limited to avoid using too much userspace stack
+    // This check is done last to allow all hashbangs to be resolved
+    //
+    // This should be based on the size of the userspace stack, divided
+    // by the cost of each argument, which should be usize * 2, with
+    // one additional argument added to represent the total size of the
+    // argument pointer array and potential padding
+    //
+    // A limit of 4095 would mean a stack of (4095 + 1) * 8 * 2 = 65536, or 64KB
+    if args.len() > 4095 {
+        return Err(Error::new(E2BIG));
+    }
+
+    match elf::Elf::from(&data) {
+        Ok(elf) => {
+            // Drop so that usage is not allowed after unmapping context
+            drop(path);
+            drop(arg_ptrs);
+
+            // We check the validity of all loadable sections here
+            for segment in elf.segments() {
+                if segment.p_type == program_header::PT_LOAD {
+                    let voff = segment.p_vaddr % 4096;
+                    let vaddr = segment.p_vaddr - voff;
+
+                    // Due to the Userspace and kernel TLS bases being located right above 2GB,
+                    // limit any loadable sections to lower than that. Eventually we will need
+                    // to replace this with a more intelligent TLS address
+                    if vaddr >= 0x8000_0000 {
+                        println!("exec: invalid section address {:X}", segment.p_vaddr);
+                        return Err(Error::new(ENOEXEC));
                     }
                 }
-            },
-            Err(err) => {
-                println!("failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err);
-                return Err(Error::new(ENOEXEC));
             }
+
+            // This is the point of no return, quite literaly. Any checks for validity need
+            // to be done before, and appropriate errors returned. Otherwise, we have nothing
+            // to return to.
+            exec_noreturn(elf, canonical.into_boxed_slice(), setuid, setgid, args.into_boxed_slice());
+        },
+        Err(err) => {
+            println!("exec: failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err);
+            Err(Error::new(ENOEXEC))
         }
     }
-
-    // Go to usermode
-    unsafe { usermode(entry, sp, 0); }
 }
 
 pub fn exit(status: usize) -> ! {