diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs
index 82beba842759a87aa5844803de6dea9425ebb703..9c5364e5a1d484a05f9a70b54079dff2264cfa55 100644
--- a/src/arch/x86_64/interrupt/syscall.rs
+++ b/src/arch/x86_64/interrupt/syscall.rs
@@ -95,8 +95,7 @@ interrupt_stack!(syscall, |stack| {
             let context = contexts.current();
             if let Some(current) = context {
                 let current = current.read();
-                let name = current.name.read();
-                println!("Warning: Context {} used deprecated `int 0x80` construct", core::str::from_utf8(&name).unwrap_or("(invalid utf8)"));
+                println!("Warning: Context {} used deprecated `int 0x80` construct", *current.name.read());
             } else {
                 println!("Warning: Unknown context used deprecated `int 0x80` construct");
             }
diff --git a/src/context/context.rs b/src/context/context.rs
index 15163e57d9e633b80f8e3340b68380cdb4757ad4..f2da71ab4d82f7c433122e08dc4673ab8e3c6d05 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -1,10 +1,15 @@
-use alloc::sync::Arc;
-use alloc::boxed::Box;
-use alloc::vec::Vec;
-use alloc::collections::VecDeque;
-use core::alloc::{GlobalAlloc, Layout};
-use core::cmp::Ordering;
-use core::mem;
+use alloc::{
+    boxed::Box,
+    collections::VecDeque,
+    string::String,
+    sync::Arc,
+    vec::Vec,
+};
+use core::{
+    alloc::{GlobalAlloc, Layout},
+    cmp::Ordering,
+    mem,
+};
 use spin::{Mutex, RwLock};
 
 use crate::arch::{interrupt::InterruptStack, paging::PAGE_SIZE};
@@ -112,7 +117,7 @@ pub struct ContextSnapshot {
     pub syscall: Option<(usize, usize, usize, usize, usize, usize)>,
     // Clone fields
     //TODO: is there a faster way than allocation?
-    pub name: Box<[u8]>,
+    pub name: Box<str>,
     pub files: Vec<Option<FileDescription>>,
     // pub cwd: Box<[u8]>,
 }
@@ -230,7 +235,7 @@ pub struct Context {
     /// User grants
     pub grants: Arc<Mutex<UserGrants>>,
     /// The name of the context
-    pub name: Arc<RwLock<Box<[u8]>>>,
+    pub name: Arc<RwLock<Box<str>>>,
     /// The current working directory
     pub cwd: Arc<Mutex<Vec<u8>>>,
     /// The open files in the scheme
@@ -287,7 +292,7 @@ impl Context {
             sigstack: None,
             tls: None,
             grants: Arc::new(Mutex::new(UserGrants::default())),
-            name: Arc::new(RwLock::new(Vec::new().into_boxed_slice())),
+            name: Arc::new(RwLock::new(String::new().into_boxed_str())),
             cwd: Arc::new(Mutex::new(Vec::new())),
             files: Arc::new(Mutex::new(Vec::new())),
             actions: Arc::new(Mutex::new(vec![(
diff --git a/src/context/switch.rs b/src/context/switch.rs
index 2423d55e418efc959294bf33dbadcc8e56e52fef..67b083225e77335d8011f28b7d478e6c2ea0bf60 100644
--- a/src/context/switch.rs
+++ b/src/context/switch.rs
@@ -13,7 +13,7 @@ unsafe fn update(context: &mut Context, cpu_id: usize) {
     // Take ownership if not already owned
     if context.cpu_id == None {
         context.cpu_id = Some(cpu_id);
-        // println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.read()));
+        // println!("{}: take {} {}", cpu_id, context.id, *context.name.read());
     }
 
     // Restore from signal, must only be done from another context to avoid overwriting the stack!
diff --git a/src/lib.rs b/src/lib.rs
index a18fb2718a772ee9ee34ebcd6cedba7f83dab195..ec36059cfd4322a3c7d033fbfb13ae3cbebea8d7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -279,7 +279,7 @@ pub extern fn ksignal(signal: usize) {
         let contexts = context::contexts();
         if let Some(context_lock) = contexts.current() {
             let context = context_lock.read();
-            info!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.read()) });
+            info!("NAME {}", *context.name.read());
         }
     }
 
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
index 99d19e352162ffb6e42fe183ff9a89fc7ef96cfd..60a73955744c2b29208c6b2ecbc2a5da75cff29c 100644
--- a/src/scheme/proc.rs
+++ b/src/scheme/proc.rs
@@ -236,7 +236,9 @@ impl Scheme for ProcScheme {
             data = match operation {
                 Operation::Memory => OperationData::Memory(MemData::default()),
                 Operation::Trace => OperationData::Trace(TraceData::default()),
-                Operation::Static(_) => OperationData::Static(StaticData::new(target.name.read().clone())),
+                Operation::Static(_) => OperationData::Static(StaticData::new(
+                    target.name.read().clone().into()
+                )),
                 _ => OperationData::Other,
             };
 
diff --git a/src/scheme/sys/block.rs b/src/scheme/sys/block.rs
index ff9d094453df0b4b34003d37a8fb86cf12b94fd2..2d58e1619230950457bf1233342e31cdf2e4837b 100644
--- a/src/scheme/sys/block.rs
+++ b/src/scheme/sys/block.rs
@@ -1,7 +1,6 @@
 use alloc::string::String;
 use alloc::vec::Vec;
 use core::fmt::Write;
-use core::str;
 
 use crate::context;
 use crate::syscall::error::Result;
@@ -21,7 +20,7 @@ pub fn resource() -> Result<Vec<u8>> {
 
         for row in rows.iter() {
             let id: usize = row.0.into();
-            let name = str::from_utf8(&row.1).unwrap_or(".");
+            let name = &row.1;
 
             let _ = writeln!(string, "{}: {}", id, name);
 
diff --git a/src/scheme/sys/context.rs b/src/scheme/sys/context.rs
index df457c875bcac9a2f17193ac0480a10b4ae9398b..26e3ae05148a527ad918eba779451ee32d6907f4 100644
--- a/src/scheme/sys/context.rs
+++ b/src/scheme/sys/context.rs
@@ -1,6 +1,5 @@
 use alloc::string::String;
 use alloc::vec::Vec;
-use core::str;
 
 use crate::context;
 use crate::syscall::error::Result;
@@ -107,9 +106,6 @@ pub fn resource() -> Result<Vec<u8>> {
                 format!("{} B", memory)
             };
 
-            let name_bytes = context.name.read();
-            let name = str::from_utf8(&name_bytes).unwrap_or("");
-
             string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<8}{}\n",
                                context.id.into(),
                                context.pgid.into(),
@@ -124,7 +120,7 @@ pub fn resource() -> Result<Vec<u8>> {
                                cpu_string,
                                ticks_string,
                                memory_string,
-                               name));
+                               *context.name.read()));
         }
     }
 
diff --git a/src/scheme/sys/exe.rs b/src/scheme/sys/exe.rs
index 69e2261fb9f9dccb583a69cd645a2f7508076277..43aaf3545d68bd262131c269a61c6f8d6c5c2a74 100644
--- a/src/scheme/sys/exe.rs
+++ b/src/scheme/sys/exe.rs
@@ -1,4 +1,7 @@
-use alloc::vec::Vec;
+use alloc::{
+    boxed::Box,
+    vec::Vec,
+};
 
 use crate::context;
 use crate::syscall::error::{Error, ESRCH, Result};
@@ -9,7 +12,8 @@ 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.read();
-        name.clone().into_vec()
+        let name_bytes: Box<[u8]> = name.clone().into();
+        name_bytes.into_vec()
     };
     Ok(name)
 }
diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs
index 3aac16ea83dcbdbd2353f49222e00c08843765aa..6a7322798d2c78cee3895a35cb256600a6661a0c 100644
--- a/src/scheme/sys/iostat.rs
+++ b/src/scheme/sys/iostat.rs
@@ -22,7 +22,7 @@ pub fn resource() -> Result<Vec<u8>> {
 
         for row in rows.iter() {
             let id: usize = row.0.into();
-            let name = str::from_utf8(&row.1).unwrap_or(".");
+            let name = &row.1;
             let _ = writeln!(string, "{}: {}", id, name);
 
             for (fd, f) in row.2.iter().enumerate() {
diff --git a/src/scheme/sys/syscall.rs b/src/scheme/sys/syscall.rs
index c458d4e7ff240ecdd5ba6fa7debabf0d59fa3711..a1999982459ea68f331429223147576176702bf3 100644
--- a/src/scheme/sys/syscall.rs
+++ b/src/scheme/sys/syscall.rs
@@ -1,7 +1,6 @@
 use alloc::string::String;
 use alloc::vec::Vec;
 use core::fmt::Write;
-use core::str;
 
 use crate::context;
 use crate::syscall;
@@ -22,7 +21,7 @@ pub fn resource() -> Result<Vec<u8>> {
 
         for row in rows.iter() {
             let id: usize = row.0.into();
-            let name = str::from_utf8(&row.1).unwrap_or(".");
+            let name = &row.1;
 
             let _ = writeln!(string, "{}: {}", id, name);
 
diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs
index eec730020f0e8a0063db5a4c1a3119b06e782652..9f8139b21c21b75133a14766afcb2b9bf6a6cc0f 100644
--- a/src/syscall/mod.rs
+++ b/src/syscall/mod.rs
@@ -82,8 +82,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                                 let contexts = crate::context::contexts();
                                 let current = contexts.current().unwrap();
                                 let current = current.read();
-                                let name = current.name.read();
-                                println!("{:?} using deprecated fmap(...) call", core::str::from_utf8(&name));
+                                println!("{:?} using deprecated fmap(...) call", *current.name.read());
                             }
                             file_op(a, fd, c, d)
                         },
@@ -92,8 +91,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
                                 let contexts = crate::context::contexts();
                                 let current = contexts.current().unwrap();
                                 let current = current.read();
-                                let name = current.name.read();
-                                println!("{:?} using deprecated funmap(...) call", core::str::from_utf8(&name));
+                                println!("{:?} using deprecated funmap(...) call", *current.name.read());
                             }
                             funmap_old(b)
                         },
@@ -208,8 +206,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
         let contexts = crate::context::contexts();
         if let Some(context_lock) = contexts.current() {
             let context = context_lock.read();
-            let name_raw = context.name.read();
-            let name = unsafe { core::str::from_utf8_unchecked(&name_raw) };
+            let name = context.name.read();
             if name.contains("redoxfs") {
                 if a == SYS_CLOCK_GETTIME || a == SYS_YIELD {
                     false
@@ -230,7 +227,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
         let contexts = crate::context::contexts();
         if let Some(context_lock) = contexts.current() {
             let context = context_lock.read();
-            print!("{} ({}): ", unsafe { core::str::from_utf8_unchecked(&context.name.read()) }, context.id.into());
+            print!("{} ({}): ", *context.name.read(), context.id.into());
         }
 
         println!("{}", debug::format_call(a, b, c, d, e, f));
@@ -265,7 +262,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
         let contexts = crate::context::contexts();
         if let Some(context_lock) = contexts.current() {
             let context = context_lock.read();
-            print!("{} ({}): ", unsafe { core::str::from_utf8_unchecked(&context.name.read()) }, context.id.into());
+            print!("{} ({}): ", *context.name.read(), context.id.into());
         }
 
         print!("{} = ", debug::format_call(a, b, c, d, e, f));
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index b034358d456ba088a5304d23585030f6d33024ad..6b15779aa1e95021593dec46b4a30a886e7bee5b 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -1,7 +1,10 @@
-use alloc::boxed::Box;
-use alloc::collections::BTreeSet;
-use alloc::sync::Arc;
-use alloc::vec::Vec;
+use alloc::{
+    boxed::Box,
+    collections::BTreeSet,
+    string::String,
+    sync::Arc,
+    vec::Vec,
+};
 use core::alloc::{GlobalAlloc, Layout};
 use core::ops::DerefMut;
 use core::{intrinsics, mem};
@@ -608,7 +611,7 @@ fn empty(context: &mut context::Context, reaping: bool) {
         let grants = mem::replace(&mut *grants, UserGrants::default());
         for grant in grants.inner.into_iter() {
             if reaping {
-                println!("{}: {}: Grant should not exist: {:?}", context.id.into(), unsafe { ::core::str::from_utf8_unchecked(&context.name.read()) }, grant);
+                println!("{}: {}: Grant should not exist: {:?}", context.id.into(), *context.name.read(), grant);
 
                 let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_utable()) };
                 let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::USER_TMP_GRANT_OFFSET)));
@@ -632,7 +635,7 @@ impl Drop for ExecFile {
 fn fexec_noreturn(
     setuid: Option<u32>,
     setgid: Option<u32>,
-    name: Box<[u8]>,
+    name: Box<str>,
     data: Box<[u8]>,
     args: Box<[Box<[u8]>]>,
     vars: Box<[Box<[u8]>]>,
@@ -893,7 +896,7 @@ fn fexec_noreturn(
     unsafe { usermode(entry, sp, 0, singlestep) }
 }
 
-pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>]>, name_override_opt: Option<Box<[u8]>>, auxv: Option<Vec<usize>>) -> Result<usize> {
+pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>]>, name_override_opt: Option<Box<str>>, auxv: Option<Vec<usize>>) -> Result<usize> {
     let (uid, gid) = {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -902,7 +905,7 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
     };
 
     let mut stat: Stat;
-    let mut name: Vec<u8>;
+    let name: String;
     let mut data: Vec<u8>;
     {
         let file = ExecFile(fd);
@@ -926,11 +929,18 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
         }
 
         if let Some(name_override) = name_override_opt {
-            name = Vec::from(name_override);
+            name = String::from(name_override);
         } else {
-            name = vec![0; 4096];
-            let len = syscall::file_op_mut_slice(syscall::number::SYS_FPATH, file.0, &mut name)?;
-            name.truncate(len);
+            let mut name_bytes = vec![0; 4096];
+            let len = syscall::file_op_mut_slice(syscall::number::SYS_FPATH, file.0, &mut name_bytes)?;
+            name_bytes.truncate(len);
+            name = match String::from_utf8(name_bytes) {
+                Ok(ok) => ok,
+                Err(_err) => {
+                    //TODO: print error?
+                    return Err(Error::new(EINVAL));
+                }
+            };
         }
 
         //TODO: Only read elf header, not entire file. Then read required segments
@@ -974,7 +984,7 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
                 println!(
                     "{}: {}: fexec failed to execute {}: {}",
                     context.id.into(),
-                    unsafe { ::core::str::from_utf8_unchecked(&context.name.read()) },
+                    *context.name.read(),
                     fd.into(),
                     err
                 );
@@ -1026,8 +1036,8 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
 
                 let mut args_vec = Vec::from(args);
                 //TODO: pass file handle in auxv
-                let name_override = name.into_boxed_slice();
-                args_vec[0] = name_override.clone();
+                let name_override = name.into_boxed_str();
+                args_vec[0] = name_override.clone().into();
 
                 // Drop variables, since fexec_kernel probably won't return
                 drop(elf);
@@ -1060,7 +1070,7 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>
     // 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.
-    fexec_noreturn(setuid, setgid, name.into_boxed_slice(), data.into_boxed_slice(), args, vars, auxv.into_boxed_slice());
+    fexec_noreturn(setuid, setgid, name.into_boxed_str(), data.into_boxed_slice(), args, vars, auxv.into_boxed_slice());
 }
 
 pub fn fexec(fd: FileHandle, arg_ptrs: &[[usize; 2]], var_ptrs: &[[usize; 2]]) -> Result<usize> {