From 12e6aadcb0a9f87f89e48ac47aa08b8744fbe55a Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Mon, 26 Mar 2018 17:07:33 -0700 Subject: [PATCH] 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 --- include/misc/libc-hooks.h | 14 +++++++++++++ lib/libc/newlib/libc-hooks.c | 40 ++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/misc/libc-hooks.h b/include/misc/libc-hooks.h index 82d9f191d6b..d7f6bc58e81 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 int _zephyr_fputc(int c, FILE *stream); __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 #endif /* ZEPHYR_LIBC_HOOKS_H */ diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index cfcb1368664..f1709f8a496 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #define USED_RAM_END_ADDR POINTER_TO_UINT(&_end) @@ -76,8 +78,7 @@ void __stdin_hook_install(unsigned char (*hook)(void)) _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 @@ int _read(int fd, char *buf, int nbytes) } 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 @@ int _write(int fd, char *buf, int nbytes) } 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)