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)