lib: newlib: add read/write syscalls

The read/write implementations call directly into the console drivers
using the hook mechanism, causing faults if invoked from user mode.

Add system calls for read() and write() such that we do a privilege
elevation first.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
diff --git a/include/misc/libc-hooks.h b/include/misc/libc-hooks.h
index 82d9f19..d7f6bc5 100644
--- a/include/misc/libc-hooks.h
+++ b/include/misc/libc-hooks.h
@@ -16,6 +16,18 @@
  * that need to call into the kernel as system calls
  */
 
+#ifdef CONFIG_NEWLIB_LIBC
+
+/* syscall generation ignores preprocessor, ensure this is defined to ensure
+ * we don't have compile errors
+ */
+#define _MLIBC_RESTRICT
+
+__syscall int _zephyr_read(char *buf, int nbytes);
+
+__syscall int _zephyr_write(char *buf, int nbytes);
+
+#else
 /* Minimal libc */
 
 __syscall int _zephyr_fputc(int c, FILE *stream);
@@ -23,6 +35,8 @@
 __syscall size_t _zephyr_fwrite(const void *_MLIBC_RESTRICT ptr, size_t size,
 				size_t nitems, FILE *_MLIBC_RESTRICT stream);
 
+#endif /* CONFIG_NEWLIB_LIBC */
+
 #include <syscalls/libc-hooks.h>
 
 #endif /* ZEPHYR_LIBC_HOOKS_H */
diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c
index cfcb136..f1709f8 100644
--- a/lib/libc/newlib/libc-hooks.c
+++ b/lib/libc/newlib/libc-hooks.c
@@ -12,6 +12,8 @@
 #include <misc/util.h>
 #include <kernel_internal.h>
 #include <misc/errno_private.h>
+#include <misc/libc-hooks.h>
+#include <syscall_handler.h>
 
 #define USED_RAM_END_ADDR   POINTER_TO_UINT(&_end)
 
@@ -76,8 +78,7 @@
 	_stdin_hook = hook;
 }
 
-#ifndef CONFIG_POSIX_FS
-int _read(int fd, char *buf, int nbytes)
+int _impl__zephyr_read(char *buf, int nbytes)
 {
 	int i = 0;
 
@@ -90,9 +91,16 @@
 	}
 	return i;
 }
-FUNC_ALIAS(_read, read, int);
 
-int _write(int fd, char *buf, int nbytes)
+#ifdef CONFIG_USERSPACE
+Z_SYSCALL_HANDLER(_zephyr_read, buf, nbytes)
+{
+	Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, nbytes));
+	return _impl__zephyr_read((char *)buf, nbytes);
+}
+#endif
+
+int _impl__zephyr_write(char *buf, int nbytes)
 {
 	int i;
 
@@ -104,6 +112,30 @@
 	}
 	return nbytes;
 }
+
+#ifdef CONFIG_USERSPACE
+Z_SYSCALL_HANDLER(_zephyr_write, buf, nbytes)
+{
+	Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, nbytes));
+	return _impl__zephyr_write((char *)buf, nbytes);
+}
+#endif
+
+#ifndef CONFIG_POSIX_FS
+int _read(int fd, char *buf, int nbytes)
+{
+	ARG_UNUSED(fd);
+
+	return _zephyr_read(buf, nbytes);
+}
+FUNC_ALIAS(_read, read, int);
+
+int _write(int fd, char *buf, int nbytes)
+{
+	ARG_UNUSED(fd);
+
+	return _zephyr_write(buf, nbytes);
+}
 FUNC_ALIAS(_write, write, int);
 
 int _open(const char *name, int mode)